Java Applet,游戏循环第一次运行正常,然后在重置时,以一半的速度更新

时间:2012-08-24 15:42:59

标签: java multithreading applet

所以对于我正在创造的游戏,我意识到我的迷雾已经对我的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();
        }
    }

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

2 个答案:

答案 0 :(得分:1)

看起来你正在为每个游戏循环开始一个新线程;这意味着每次游戏循环运行时,您都有另一个线程供Java VM处理。这是非常低效的,因为最终你将有1000个线程在运行,导致巨大的延迟。你有没有办法在没有线程的情况下重写你的代码?

此外,这应该做什么?

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

你为什么要做1000/60?答:为什么不用16? B:看起来你在这里意味着什么,不知道是什么

此外,您的start()stop()方法中的bg变量是什么?

答案 1 :(得分:0)

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

您应该在创建的线程中存储引用并在stop方法中将其中断。

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

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