我写了一个代码,在Snake游戏中为练习生成“蛇”。 (如果你不熟悉蛇游戏中的蛇,它是一个5箱长的蛇头(用JLabel创建)和身体部位(也用JLabel创建)跟在头后面。)
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;
public class SnakeGameFrame extends JFrame {
Thread snakeThread;
GroundPanel p;
public SnakeGameFrame() {
super("Moving Snake!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p = new GroundPanel();
setContentPane(p);
setSize(400,400);
setVisible(true);
p.requestFocus();
snakeThread = new Thread(p);
snakeThread.start();
}
class GroundPanel extends JPanel implements Runnable{
static final int LEFT = 0;
static final int RIGHT = 1;
static final int UP = 2;
static final int DOWN = 3;
int direction;
Image img;
SnakeBody snakeBody;
final int delay = 200;
public GroundPanel() {
setLayout(null);
snakeBody = new SnakeBody();
snakeBody.addIn(this);
direction = LEFT;
this.addKeyListener(new MyKeyListener());
ImageIcon icon = new ImageIcon("twilight.jpg");
img = icon.getImage();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0,0,getWidth(), getHeight(), null);
}
public void run() {
while(true) {
try {
Thread.sleep(delay);
snakeBody.move(direction);
}catch(InterruptedException e) {
return;
}
}
}
class MyKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT:
direction = LEFT;
break;
case KeyEvent.VK_RIGHT:
direction = RIGHT;
break;
case KeyEvent.VK_UP:
direction = UP;
break;
case KeyEvent.VK_DOWN:
direction = DOWN;
break;
}
}
}
}
class SnakeBody {
Vector<JLabel> v = new Vector<JLabel>();
public SnakeBody() {
ImageIcon head = new ImageIcon("head.jpg");
JLabel la = new JLabel(head);
la.setSize(head.getIconWidth(), head.getIconHeight());
la.setLocation(100, 100);
v.add(la);
ImageIcon body = new ImageIcon("body.jpg");
for(int i=1; i<10; i++) {
la = new JLabel(body);
la.setSize(body.getIconWidth(), body.getIconHeight());
la.setLocation(100+i*20, 100);
v.add(la);
}
}
public void addIn(JPanel p) {
for(int i=0; i<v.size(); i++)
p.add(v.get(i));
}
public void move(int direction) {
for(int i=v.size()-1; i>0; i--) {
JLabel b = v.get(i);
JLabel a = v.get(i-1);
b.setLocation(a.getX(), a.getY());
}
JLabel head = v.get(0);
switch(direction) {
case GroundPanel.LEFT :
head.setLocation(head.getX()-20, head.getY());
break;
case GroundPanel.RIGHT :
head.setLocation(head.getX()+20, head.getY());
break;
case GroundPanel.UP :
head.setLocation(head.getX(), head.getY()-20);
break;
case GroundPanel.DOWN :
head.setLocation(head.getX(), head.getY()+20);
break;
}
}
}
public static void main(String[] args) {
new SnakeGameFrame();
}
}
我的问题是为了保持“更新”我的蛇,我想我必须在我的
中使用repaint()方法public void run()
方法。 喜欢这个
尝试{Thread.sleep(延迟); snakeBody.move(方向);重绘(); }
但事实证明没有它就可以正常工作.. 我已经阅读了很多关于repaint()的帖子,但是当我需要使用它时我仍然没有得到。 有人可以用noob友好的术语解释吗?谢谢:))
答案 0 :(得分:2)
每当repaint()
尚未代表您这样做时,您必须调用RepaintManager
,例如更新绑定属性(如文本或颜色)。在您的示例中,更改JLabel
的大小和位置会自动触发重新绘制。
更严重的是,您的示例在两个方面错误地同步:
它会在initial thread而不是event dispatch thread上创建GUI。
它更新事件调度线程以外的线程上的GUI组件,而不同步对共享数据的访问。
相反,请使用javax.swing.Timer
来调整动画的速度。您将在事件派发线程上调用actionPerformed()
的实现。