不止一次拍摄导致摇摆计时器重复

时间:2014-04-02 22:48:48

标签: java swing timer actionlistener keylistener

好吧,所以我有一种方法来射击一个咒语,每当我按空间它就会射击,但是如果我按下空间而它仍然在屏幕上,我的咒语速度加倍并开始重复自己没有我再次推动空间在这里我的代码谢谢:)哦,WizardCells只是一个JLabel的二维数组我知道这是正确的创建和使用所以我不想浪费你的人'时间与该代码谢谢:))

 public void shootSpell(){
        final BlueSpell b = new BlueSpell(GoodGuy.getx(), GoodGuy.gety() +1, BlueSpellWizard());
        int delay = 60;

        ActionListener timeListen = new ActionListener(){
            public void actionPerformed(ActionEvent e){


                    if(b.gety() != 19){
                        WizardCells[b.getx()][b.gety()].setIcon(null);
                        WizardCells[b.getx()][b.changey(b.gety()+1)].setIcon(b.getIcon());

                    }

                    else{
                        WizardCells[b.getx()][b.gety()].setIcon(null);
                        b.changex(GoodGuy.getx());
                        b.changey(GoodGuy.gety() +1);
                        timer.stop();

                    }
                }

        };


            timer = new Timer(delay, timeListen);
            if(timer.isRunning()){
                return;
            }

            else{
            timer.start();
            }


        }

密钥处理程序:

public class WizardKeyHandeler extends WizardBattleGrid implements KeyListener {
GoodGuy Player = new GoodGuy(10, 0, GoodGuyWizardIcon());
BlueSpell GoodSpell = new BlueSpell(10, 1, BlueSpellWizard());
WizardPause pause = new WizardPause();






    @Override
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();

        if(key == KeyEvent.VK_W){

            if(Player.getx() != 0){

                Player.moveUp();
            }

        }

        else if(key == KeyEvent.VK_S){

            if(Player.getx() != 19){

                Player.moveDown();
            }
        }

        else if(key == KeyEvent.VK_D){

            if(Player.gety() != 9){

                Player.moveRight();
            }
        }

        else if(key == KeyEvent.VK_A){

            if(Player.gety() != 0){

                Player.moveLeft();
            }
        }

        else if(key == KeyEvent.VK_SPACE){





                }

        else if(key == KeyEvent.VK_ESCAPE){

            pause.createPause();
        }


    }   











    @Override
    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        if(key == KeyEvent.VK_W){
                if(Player.getx() != 0){

                Player.remainAtPosition();
            }   
            }

        else if(key == KeyEvent.VK_S){

            if(Player.getx() != 19){

                Player.remainAtPosition();
            }
        }

        else if(key == KeyEvent.VK_D){

            if(Player.gety() != 9){

                Player.remainAtPosition();
            }
        }

        else if(key == KeyEvent.VK_A){

            if(Player.gety() != 0){

                Player.remainAtPosition();
            }
        }

        else if(key == KeyEvent.VK_SPACE){


                GoodSpell.shootSpell();


                }

        else if(key == KeyEvent.VK_ESCAPE){

                pause.createPause();
        }

    }



    @Override
    public void keyTyped(KeyEvent e) {
        int key = e.getKeyCode();
        if(key == KeyEvent.VK_W){
            if(Player.getx() != 0){

                Player.moveUp();

            }

            }

        else if(key == KeyEvent.VK_S){

            if(Player.getx() != 19){

                Player.moveDown();
            }
        }

        else if(key == KeyEvent.VK_D){

            if(Player.gety() != 9){

                Player.moveRight();
            }
        }

        else if(key == KeyEvent.VK_A){

            if(Player.gety() != 0){

                Player.moveLeft();
            }
        }

        else if(key == KeyEvent.VK_SPACE){





                }

        else if(key == KeyEvent.VK_ESCAPE){

            pause.createPause();
        }
    }

1 个答案:

答案 0 :(得分:1)

MadPrgrammer和camickr两个好点。我想说明这些观点。

  

MapPrgogrammer:你应该有一个计时器,它负责更新游戏/模型的状态并安排重绘,不要使用多个计时器

您应该做的是List SpellBlueSpell(无论如何)。你想要做的是遍历Timer 你的绘画方法中的列表。像

这样的东西
public class GamePanel extends JPanel {
    List<BlueSpell> spells;
    Timer timer = null;

    public GamePanel() {
        spells = new ArrayList<>();

        timer = new Timer(40, new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                If (spells.size() > 0) {
                    Iterator spellIt = spells.iterator();
                    while (spellIt.hasNext()) {
                        BlueSpell spell = (BlueSpell)spellIt.next();
                        if (spell.collidesWithSomthing()) {
                            // do something, then remove from list
                            spellIt.remove();     
                        } else if (spell.isOffScreen()) {
                            spellIt.remove();  // remove the spell from list
                        } else {
                            spell.animate();  // animate for each tick of timer
                        }
                    }
                }
                repaint();  // just repaint once in each timer tick after all 
            }               // state id update.
        });
        timer.start(); 
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        If (spells.size() > 0) {
             for (BlueSpell spell: spells) {
                  spell.drawSpell(g);
             }
        }
    }
}

您可以在spells回调中看到Timer列表的基本概念。它遍历计时器,如果列表有BlueSpells,那么它将继续检查法术是否与某些东西发生碰撞(如果你需要),它会检查法术是否在屏幕外。使用其中之一,您将要从列表中删除它。 (不要试图在每个循环中使用a。在这种情况下,你应该使用迭代器)。如果它仍然在屏幕上并且没有击中任何东西,那么该法术会动画(可能会移动它x位置或其他东西),然后最后为每个刻度,面板重新绘制。请注意ifpaintComponent中的Timer次检查。如果列表为空,则无需绘制或遍历列表。

你想要在单个计时器中保持所有游戏的状态,而不仅仅是法术。如果法术是动画的唯一内容,如果列表为空,您可能需要在计时器中添加else { timer.stop() }


  

camickr:不要使用KeyListener来控制玩家的移动。有关更多信息和替代方法using Key Bindings

,请参阅使用键盘进行运动

你可以做的是当按下空间时,将new BlueSpell添加到列表中(并启动计时器[仅在必要时])。像

这样的东西
public GamePanel() {
    ...
    InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    inputMap.put(KeyStroke.getKeyStroke("SPACE"), "shootSpell");
    getActionMap().put("shootSpell", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            spells.add(new BlueSpell(...));
        }
    });
}

一旦将法术添加到列表中,该法术将开始动画,直到它与某些东西发生碰撞或离开屏幕。


您可以在this answer中看到两个点的实际示例。

enter image description here

此外,您还可以看到其他一些&#34;动画多个对象&#34; 答案herehere以及here和{{3 }}和here以及here


<强>更新

  

&#34;唯一的问题是在我的重绘方法中,我只是调用我创建的ImageIcon还是必须创建一个新的?&#34;

public class BlueSpell {
    BufferedImage bi;
    int x, y;
    int width = someWidth;
    int height = someHeight;
    JPanel panel;

    public BlueSpell(BufferedImage bi, int x, int y, panel) {
        this.bi = bi;
        this.x = x;
        this.y = y;
        this.panel = panel;
    }

    public void drawSpell(Graphics g) {
        g.drawImage(bi, x, y, width, height, panel);
    }

    public void animate() {
        x += 5;
    }
}

您应该只在BufferedImage中创建一个GamePanel,当您在键绑定中创建new BlueSpell时,只需将图像与其他参数一起传递给它