Java游戏口吃

时间:2014-03-31 18:32:18

标签: java game-engine

我刚开始开发一款侧面滚动平面射击游戏。几天后,我对飞机的运动有疑问。出于某种原因,每隔一秒左右,精灵似乎就会口吃。它几乎就好像它跳回了一个框架或什么东西,然后从它停止的地方继续。我没有找到导致这种情况的原因。有什么想法吗? 整个项目可以在这里找到: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);
    }

}

1 个答案:

答案 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上的官方教程。它会给你一个很好的起点。