java小程序,游戏循环第一次运行良好,然后复位时,以一半的速度更新

dkqlctbz  于 2021-07-09  发布在  Java
关注(0)|答案(2)|浏览(293)

所以对于我正在创建的游戏,我意识到我的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还会停止循环(player内部的线程是为了在player死后完成一些效果):

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;

            }
        }
    }
}

然后在按键事件中使用重新启动:

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();
        }
    }

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

zc0qhyus

zc0qhyus1#

看起来你正在为每个游戏循环启动一个新线程;这意味着每次gameloop运行时,都有另一个线程供javavm处理。这是非常低效的,因为最终会有1000个线程运行,造成巨大的延迟。你有没有办法不用线程来重写你的代码?
还有,这是怎么回事?

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

你为什么要做1000/60?a:为什么不用16呢?b:看来你是想说别的,但不知道是什么意思
另外,您在数据库中引用的bg变量是什么 start() 以及 stop() 方法?

kcrjzv8t

kcrjzv8t2#

看起来您正在尝试使用gamerunning布尔值来停止线程。如果这不是易变的,那么游戏循环可能不会注意到gui线程的更改,而gui线程将其设置为false并将永远运行。即使它是易变的,如果在游戏线程注意到stop命令之前再次调用start,您也有一个争用条件。
相反,您应该在创建的线程中存储一个引用,并在stop方法中中断它。
另外,对于paint方法,所有的更新方法都是线程安全的。updateplayer看起来不是线程安全的,而且您不知道何时调用paint,因此它可能与update方法同时发生。即使paint方法不写入共享数据,由于缺少内存屏障,它仍然可以看到不一致的数据。
我建议在gui线程中进行所有更新,除非它非常慢并且需要多线程处理。看看如何使用swing中的计时器来启动更新逻辑。

相关问题