Java 为什么我的椭圆没有移动
我正在编写一个类似蛇的小游戏,我正在实现按键事件侦听器,所以当按下箭头键时,它会侦听,它会增加或减少椭圆在帧中的位置。下面是我的代码,你认为发生了什么?我试着用谷歌搜索可能的解决方案,但结果是空的Java 为什么我的椭圆没有移动,java,swing,jframe,paint,keylistener,Java,Swing,Jframe,Paint,Keylistener,我正在编写一个类似蛇的小游戏,我正在实现按键事件侦听器,所以当按下箭头键时,它会侦听,它会增加或减少椭圆在帧中的位置。下面是我的代码,你认为发生了什么?我试着用谷歌搜索可能的解决方案,但结果是空的 package snakegame; import java.awt.Graphics; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.JFrame; /** * * @
package snakegame;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
/**
*
* @author PlaixHax0r
*/
public class SnakeGame extends JFrame{
int x, y;
public class ActionListener extends KeyAdapter{
public void KeyPressed(KeyEvent a){
int KeyCode = a.getKeyCode();
if(KeyCode == KeyEvent.VK_RIGHT){
x++;
}
if(KeyCode == KeyEvent.VK_LEFT){
x--;
}
if(KeyCode == KeyEvent.VK_DOWN){
y++;
}
if(KeyCode == KeyEvent.VK_UP){
y--;
}
}
public void KeyReleased(KeyEvent a){
}
}
public SnakeGame(){
addKeyListener(new ActionListener());
setTitle("Snake 1.0");
setVisible(true);
setSize(500, 500);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
x=150;
y=150;
}
public void paint(Graphics g){
g.drawString("Welcome to Snake Empire", 180, 50);
g.fillOval(x, y, 15, 15);
repaint();
}
public static void main(String[] args) {
new SnakeGame();
}
}
若干建议:
- 不要直接在JFrame中绘制。查看绘图教程,您将看到如何在JPanel或其他JComponent的
methodoverride中绘图paintComponent(…)
的第一行通常是对super方法的调用:paintComponent(…)
super.paintComponent(g)
- 不要在
或paint(…)
内部调用paintComponent(…)
。这是一种尝试制作不受控制的动画的糟糕方法repaint()
- 改用摆动计时器
- 不要将类命名为与核心类相同的名称,尤其不要将其命名为ActionListener,因为这将使您在需要时几乎不可能使用实际的ActionListener
- KeyListener仅在侦听的组件可聚焦且具有焦点时才工作
- 避免在Swing应用程序中使用KeyListener,而是使用键绑定。请搜索这个网站,因为这已经讨论了很多次,许多例子,一些我的
请查看,然后查看我使用密钥绑定和的示例代码。除了气垫船看到的问题外,我还看到了以下问题:
- 您没有覆盖任何KeyListener(或KeyAdapter)方法。您的方法名为
,在Java中,方法总是以小写字母开头。该方法名为KeyPressed
。当您打算重写方法时,请始终使用@Override注释。这样,如果由于方法名称中有输入错误而没有输入,则会出现编译器错误:keyPressed()
@Override public void keyPressed(KeyEvent event) { ... }
- 当按下某个键时,您没有调用repaint(),因此Swing没有理由重新绘制帧
- 您正在调用
内部repaint()
。它会在一个绘制事件实际完成之前安排另一个绘制事件。多次调用它会导致cpu崩溃。如果只需要移动椭圆,只需调用paint()
方法末尾的重新绘制keyPressed()
- 你无法控制时间。这会导致游戏在快系统上运行快,在慢系统上运行慢。尝试搜索
游戏循环
- 许多游戏使用多线程。一种逻辑线程,与EDT分开,以防止CPU占用,并以正常速率检测输入
- 避免直接渲染到帧上。仅当您希望活动渲染并创建
(尽管不使用绘制方法)时,才建议使用此方法缓冲策略
- 您没有使用双缓冲。它使游戏闪烁
- 切勿在输入状态下直接更改对象的位置。只需更改它们的特定速度,并在更新时简单地将它们添加到位置(也使用负速度),以确保仅定期更新对象
- 最后,尝试搜索
。有一个简单的框架可以很好地介绍这个主题。(这是一个蛇类游戏的例子)java游戏开发教程
摆脱java中的
.NET
命名约定(以大写字母开始方法名)+1发现编写这个很困难。简短而甜蜜的分析。为什么不在paint(…)
中调用repaint()
?@JanDvorak:因为你正在创建一个无法控制时间间隔的游戏循环,并且你正在将影响程序状态的代码放入paint(…)
中,这是一个不应该做的事情。这是一个潜在的其他问题,是的。请在另一个答案中随意添加。我不确定你不能将密钥侦听器添加到JFrame,而且我懒得检查。非常感谢,这真的很有帮助。我必须改掉方法名称以大写字母开头的习惯。感谢如果您正在创建一个游戏,请使用brilliant library,其中包含了您在游戏中所需的大部分内容,如开箱即用的游戏循环、opengl、音乐和动画课程等。当然,除非您正在自学挥杆绘画的工作原理,而不是随身携带的士兵:)