如何防止我的KeyEvent重新绘制这两个对象?

时间:2016-05-26 02:48:07

标签: java swing paintcomponent repaint

我正在制作一个简单的游戏,需要1个玩家(正方形)和一些在游戏区内随机产生的敌人。我目前遇到了一个问题,因为当我运行我的程序时,按任意箭头键不仅会重新显示玩家的新位置,而且还会将所有敌人重新生成到新位置。

我已经完成了几次我的代码,但我仍然难以理解为什么会发生这种情况。任何帮助将不胜感激。

P.S。我不是一个非常有经验的程序员,因此有些代码可能效率不高,有些东西可能不正确;随时可以指出除了手头的问题之外的任何错误。谢谢!

主要类

    public class Eat {

    public static void main(String[] args) {

        // Creating the main frame
        JFrame main = new JFrame("Eat 'Em All - Version 1.0.2");
        main.setSize(497, 599);
        main.setLocationRelativeTo(null);
        main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        main.setResizable(false);

        // Colours and borders
        Border areaBorder = new LineBorder(Color.LIGHT_GRAY, 3);

        // Creating main JPanel
        JPanel area = new JPanel();
        area.setLayout(new BoxLayout(area, BoxLayout.PAGE_AXIS));
        area.setBackground(Color.WHITE);
        main.setContentPane(area);

        // Creating the drawing/image/player
        DrawPlayer player = new DrawPlayer();
        player.setPreferredSize(new Dimension(497, 539));
        player.setOpaque(false);

        // Enemies
        DrawEnemy enemy = new DrawEnemy();
        enemy.setPreferredSize(new Dimension(497, 539));
        enemy.setBackground(Color.WHITE);

        // Creating the control panel for buttons, etc
        JPanel control = new JPanel();
        control.setPreferredSize(new Dimension(497, 60));
        control.setLayout(new GridLayout(1, 2, 0, 0));
        control.setBorder(areaBorder);

        JLabel welcome = new JLabel("  Welcome to Eat 'Em All   |--|   Press 'Start'");
        JButton start = new JButton("Start");

        // Adding it all to the frame
        main.add(enemy);
        enemy.add(player);
        control.add(welcome);
        control.add(start);
        area.add(control);

        // Adding keylistener and making button false
        player.addKeyListener(player);
        player.setFocusable(true);
        start.setFocusable(false);
        enemy.setFocusable(false);

        // Bring frame to front and visible
        main.toFront();
        main.setVisible(true);

        System.out.println(player.getWidth() / 2);
        System.out.println(player.getHeight() / 2);

    }

}

绘图播放器类

    public class DrawPlayer extends JPanel implements KeyListener {

    long xPosition = 0;
    long yPosition = 0;

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        // Making loop to get points and move it
        // Center of area is x: 245 y: 255
        int xPoints[] = {235, 255, 255, 235, 235, 255};
        int yPoints[] = {265, 265, 245, 245, 265, 245};
        for (int i = 0; i < xPoints.length; i++) {
            xPoints[i] += xPosition;
            yPoints[i] += yPosition;
        }

        g.setColor(Color.BLUE);
        g.drawPolygon(xPoints, yPoints, xPoints.length);
    }

    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
            case KeyEvent.VK_DOWN:
                if (yPosition == 245) {
                    yPosition -= 5;
                } else {
                    yPosition += 5;
                }
                break;
            case KeyEvent.VK_UP:
                if (yPosition == -245) {
                    yPosition += 5;
                } else {
                    yPosition -= 5;
                }
                break;
            case KeyEvent.VK_LEFT:
                if (xPosition == -235) {
                    xPosition += 5;
                } else {
                    xPosition -= 5;
                }
                break;
            case KeyEvent.VK_RIGHT:
                if (xPosition == 235) {
                    xPosition -= 5;
                } else {
                    xPosition += 5;
                }
                break;
        }
        repaint();
    }

    public void keyReleased(KeyEvent e) {

    }

    public void keyTyped(KeyEvent e) {

    }
}

吸引敌人类

public class DrawEnemy extends JPanel {

    public void paintComponent(Graphics f) {
        super.paintComponent(f);

        for (int i = 0; i < 10; i++ ){
            f.setColor(Color.RED);
            f.drawOval((int)(Math.random() * ((440 - 0) + 0) + 0), (int)(Math.random() * ((500 - 0) + 0) + 0), 50, 50);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

你这里有问题:

public void paintComponent(Graphics f) {
    super.paintComponent(f);

    for (int i = 0; i < 10; i++ ){
        f.setColor(Color.RED);
        f.drawOval((int)(Math.random() * ((440 - 0) + 0) + 0), (int)(Math.random() * ((500 - 0) + 0) + 0), 50, 50);
    }
}

你有一个绘画方法的程序逻辑,这是你永远不应该做的事情,因为你永远无法完全控制何时或甚至是否会调用绘画方法。解决方案,获取paintComponent方法的随机化 out 并进入它自己的单独方法,当你和你想要随机化敌人时,你调用的方法,而不是每次你重绘时。

其他问题:

  • 将程序逻辑与GUI分开。
  • 例如,你应该有一个非GUI Enemy类,一个具有自己位置,大小,移动的字段,可能是move()方法,也许是collision(Player p)方法。
  • 你应该只有一个 JPanel进行绘图,这应该是唯一的工作。
  • 同样,你不要将任何东西的运动与绘画方法联系起来。
  • 你会想要某种类型的游戏循环,也许是一个Swing Timer。这会产生规则间隔的蜱虫,刺激敌人和玩家移动。
  • 摆脱KeyListener代码并支持Key Bindings。当涉及到组件焦点时,后者更不用说了。请查看教程。