我刚开始开发一款侧面滚动平面射击游戏。几天后,我对飞机的运动有疑问。出于某种原因,每隔一秒左右,精灵似乎就会口吃。它几乎就好像它跳回了一个框架或什么东西,然后从它停止的地方继续。我没有找到导致这种情况的原因。有什么想法吗? 整个项目可以在这里找到:http://www.upload.ee/files/3975636/planes.zip.html
主要课程:
package planes;
import javax.swing.JFrame;
import planes.Entities.Player;
public class Game extends JFrame{
private static final long serialVersionUID = 1L;
private boolean isRunning = true;
public static int fps = 60;
private Frame frame;
private InputHandler input;
public static Player player;
public static void main(String[] args) {
Game game = new Game();
game.run();
System.exit(0);
}
public void update() {
player.update();
}
public void draw() {
frame.draw();
}
public void initialize() {
Sprites.init();
frame = new Frame();
input = new InputHandler(frame);
player = new Player(0, 0, Sprites.player, input);
}
public void run() {
initialize();
while (isRunning) {
long time = System.currentTimeMillis();
update();
draw();
time = (1000 / fps) - (System.currentTimeMillis() - time);
if (time > 0) {
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
setVisible(false);
}
}
框架类:
package planes;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import javax.swing.JFrame;
public class Frame extends JFrame{
private Insets insets;
private BufferedImage backBuffer;
Frame(){
setTitle("Planes");
setSize(Const.windowWidth, Const.windowHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
insets = getInsets();
setSize(insets.left + Const.windowWidth + insets.right, insets.top
+ Const.windowHeight + insets.bottom);
backBuffer = new BufferedImage(Const.windowWidth, Const.windowHeight,
BufferedImage.TYPE_INT_RGB);
}
public void draw(){
Graphics2D g = (Graphics2D) getGraphics();
Graphics2D bbg = (Graphics2D) backBuffer.getGraphics();
bbg.setColor(Color.WHITE);
bbg.fillRect(0, 0, Const.windowWidth, Const.windowHeight);
Game.player.draw(bbg);
bbg.drawRect(32, 32, 32, 32);
g.drawImage(backBuffer, insets.left, insets.top, this);
}
}
答案 0 :(得分:0)
不要从主线程(或任何其他线程)上绘制或访问GUI组件。您只能从Swing的EDT安全地渲染组件。通过你的程序现在的结构方式(主线程上的循环不断直接重新绘制组件),所有的赌注都是关闭的。您应该使用Swing为您提供的基础架构;特别是,在paint()
中呈现并通过repaint()
正确触发更新。
我建议你将绘图代码移动到组件的paint(Graphics)
中,然后在计时器上驱动游戏逻辑或将其保存在主线程中,并使用repaint()
来触发重绘(可以调用它)来自任何线程,并将导致{1}}在EDT上发生。)
此外,当您最初创建框架时,请在EDT上通过例如SwingUtilities.invokeAndWait()
来自http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html:
忽略此规则的程序可能在大多数情况下正常运行,但会遇到难以重现的不可预测的错误。
阅读concurrency in Swing上的官方教程。它会给你一个很好的起点。