Graphics.clearRect()无法正常工作

时间:2017-10-07 19:44:14

标签: java

(我是编码的菜鸟,所以请原谅不好的代码。)基本上我不久前做了一个蛇游戏(甚至几乎没有接近完成),我停止了工作,因为我有一个bug的问题事情。基本上,当'rec'矩形与它相交时,我希望它清除'food'矩形。它没有做好自己的工作,而是持续一秒钟并保持不变。下面是较小的代码:

if (food.intersects(rec)) {
    g.clearRect(food.x, food.y, food.width, food.height);
    System.out.println("intersect");
    repaint();
}

这是该计划的GIF:https://gyazo.com/570afb285a2806a80466b2e6d4d2440a

下面是完整的代码:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.Timer;

public class SnakePanel extends JPanel implements ActionListener, KeyListener {
    private int size = 10;
    private int x = 0;
    private int y = 0;
    private boolean started;
    private String dir;
    int velX = 0, velY = 0;
    Timer t = new Timer(5, this);
    Random r = new Random();
    int xx = r.nextInt(560) + 1;
    int yy = r.nextInt(540) + 1;

    public SnakePanel() {
        t.start();
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
    }

    public void paint(Graphics g) {
        super.paintComponent(g);
        Rectangle rec = new Rectangle(x, y, size, 10);
        Rectangle food = new Rectangle(xx, yy, 10, 10);
        g.setColor(Color.black);
        g.fillRect(0, 0, 600, 600);
        g.setColor(Color.white);
        g.fillRect(rec.x, rec.y, rec.width, rec.height);
        g.setColor(Color.red);
        g.fillRect(food.x, food.y, food.width, food.height);
        if (food.intersects(rec)) {
            g.clearRect(food.x, food.y, food.width, food.height);
            System.out.println("TSM");
            repaint();
        }
        food.setLocation(xx, yy);
    }

    public void actionPerformed(ActionEvent e) {
        if (x < 0) {
            x = 584;
        }
        if (x > 584) {
            x = 0;
        }
        if (y < 0) {
            y = 561;
        }
        if (y > 561) {
            y = 0;
        }
        x += velX;
        y += velY;
        repaint();
    }

    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        if (code == KeyEvent.VK_DOWN) {
            velY = 1;
            velX = 0;
        }
        if (code == KeyEvent.VK_UP) {
            velY = -1;
            velX = 0;
        }
        if (code == KeyEvent.VK_LEFT) {
            velY = 0;
            velX = -1;
        }
        if (code == KeyEvent.VK_RIGHT) {
            velY = 0;
            velX = 1;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }
}

1 个答案:

答案 0 :(得分:0)

您的问题主要在于您将程序逻辑与绘图代码混合在一起。逻辑 - 食物所在的位置,蛇所在的位置,蛇的运动 - 应该与绘图代码分开进行,当你需要改变程序的状态时 - 例如,制作食物消失,然后你需要对类的一个字段进行更改,例如食物项的ArrayList,而不是局部变量,因为在下一个游戏循环运行时,局部变量的更改不会持久。

其他问题

  • 覆盖paintComponent而不是paint,因为这会导致动画更流畅,更安全。
  • 不要在绘画方法中调用repaint()。这是一个穷人的游戏循环,一个你无法控制的游戏循环。而是使用Swing Timer(Google教程)。事实上,你有一个你似乎没有使用的计时器。
  • 对于Swing GUI,您通常最好使用键绑定而不是KeyListeners。否则,您必须创建kludges以防止应用程序焦点离开已侦听的组件。

例如,如果您有ArrayList<Rectangle>代表您的食物,该怎么办:

private List<Rectangle> food = new ArrayList<>();

然后在你的Swing Timer中,你使用一个交互器,并测试蛇头与每一点食物的交叉点,然后将其删除:

for (Iterator<Rectangle> iterator = food.iterator(); iterator.hasNext();) {
    Rectangle rectangle = (Rectangle) iterator.next();
    if (snakeHead.intersects(rectangle)) {
        iterator.remove();
    }
}

然后你打电话

repaint();

我使用迭代器来浏览List,因为它提供了一种从列表中删除项目而不会出现并发冲突的安全方法。