0

所以对于我正在创建的游戏,我意识到我的 gameLoop 做错了什么,因为我第一次玩我的游戏时它运行得很好,但是第二次或之后的任何事情,它都会减慢一半。即使我将游戏最小化(因为这会停止 gameLoop,然后再次启动它会重新启动它)这里是 gameLoop 代码:

public void gameLoop(){

        new Thread(){
            public void run() {
                while(gameRunning){
                    try {
                        Thread.sleep(1000/60);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    if (tutorial){
                        updateBullet();
                        updatePlayer();
                        repaint();
                    } else {
                        updateEnemies();
                        updateBullet();
                        createEnemies();
                        updateParticles();
                        updatePlayer();
                        repaint();
                    }

                }
                repaint();
            }
        }.start();
}

我第一次在 init() 中启动它

gameLoop();

然后我也有:

public void stop(){
    bg.stop();
    gameRunning = false;
}
public void start(){
    bg.start();
    gameRunning = true;
    gameLoop();

}

最后 playerUpdate 也停止循环(播放器内部的线程是为了让一些效果在播放器死亡后完成):

 public void updatePlayer(){
    if (player.isMovingLeft){
        player.x-=3;
    }
    if (player.isMovingRight){
        player.x+=3;
    }
    for (int j=0; j < enemies.size(); j++){
        if (player.isAlive){
            if (enemies.get(j).x+19 > player.x && enemies.get(j).x < player.x+40 && enemies.get(j).y > player.y  && enemies.get(j).y < player.y+40) {
                enemies.remove(j);
                j--;
                explode.setFramePosition(0);
                explode.start();
                for (int k = 0; k <21; k++){
                    addParticle(player.x+20,player.y+20,2);
                }
                new Thread(){
                    public void run() {
                        try {
                            Thread.sleep(2000);
                            gameRunning = false;
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }.start();

                player.isAlive = false;
                break;

            }
        }
    }
}

然后在 keyPressed 事件中重新启动它:

if (!gameRunning){
        if (arg0.getKeyCode() == KeyEvent.VK_ENTER){
            enemies.clear();
            bullets.clear();
            particles.clear();
            score = 0;
            player.x = 200;
            player.isMovingLeft = false;
            player.isMovingRight = false;
            player.isAlive = (true);

            gameRunning = true;
            gameLoop();
        }
    }

那么为什么每当循环停止并再次启动时,它会以一半的速度运行呢?谢谢!

4

2 回答 2

1

看起来您正在为每个游戏循环启动一个新线程;这意味着每次游戏循环运行时,您都有另一个线程供 Java VM 处理。这是非常低效的,因为最终您将运行 1000 个线程,从而导致巨大的延迟。有没有什么方法可以重写你的代码而不在那里线程?

另外,这应该做什么?

                try {
                    Thread.sleep(1000/60);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

你为什么要做1000/60?A: 为什么不直接使用 16?B: 好像你在这里有别的意思,但不知道是什么意思

另外,您在start()andstop()方法中引用的 bg 变量是什么?

于 2012-08-24T15:45:17.950 回答
0

看起来您正试图通过使用 gameRunning 布尔值来停止线程。如果这不是易失性的,那么游戏循环可能不会注意到将其设置为 false 的 GUI 线程的更改并将永远运行。即使它是不稳定的,如果在游戏线程注意到停止命令之前再次调用 start ,您就会有竞争条件。

相反,您应该存储对创建的线程的引用并在您的 stop 方法中中断它。

相对于paint方法,您的所有更新方法也是线程安全的。updatePlayer 看起来不是线程安全的,而且您不知道何时调用paint,因此它可能与您的更新方法同时发生。即使paint方法不写入共享数据,由于缺少内存屏障,它仍然可能看到不一致的数据。

我建议在 GUI 线程中进行所有更新,除非它非常慢并且您需要多线程。查看使用 Swing 中的 Timer 来启动更新逻辑。

于 2012-08-24T18:48:55.403 回答