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

Java小程序,游戏循环第一次运行正常,然后在重置时以一半的速度更新,java,multithreading,applet,Java,Multithreading,Applet,因此,对于我正在创建的游戏,我意识到我的gameLoop有问题,因为我第一次玩游戏时,它运行得很好,但第二次或之后的任何时候,它都会减慢一半左右。即使我最小化游戏(因为这会停止gameLoop,然后再次启动它会启动它),gameLoop代码如下: public void gameLoop(){ new Thread(){ public void run() { while(gameRunning){

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


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

看起来您正在为每个gameloop启动一个新线程;这意味着每次gameloop运行时,您都有另一个线程供JavaVM处理。这是非常低效的,因为最终会有1000个线程运行,造成巨大的延迟。有没有什么方法可以不用线程来重写代码

还有,这应该做什么

                try {
                    Thread.sleep(1000/60);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
你为什么要做1000/60?A:为什么不用16呢?B:看来你在这里有别的意思,但不确定是什么意思


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

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

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

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


我建议在GUI线程中执行所有更新,除非它非常慢并且需要多线程。看看如何使用Swing中的计时器来启动更新逻辑。

1000/60计算循环每秒处理60次的时间量。换句话说,每秒60帧。还有其他方法可以实现这一点,更不用说处理游戏所需的时间也不算在内。bg是循环的背景声音,我正在停止和启动它,如果这是一种不好的方法,还有什么更好的方法?我正在使用的这本书谈到了你如何需要一个gameloop什么是更好的方法?那家伙是对的,每秒60帧。“有没有一种方法可以让我停止线程,然后开始一个新的线程?”JeremySayers抱歉,我以为你在试图用睡眠做其他事情。至于线程,仍然不确定我的想法是否正确,但gameLoop多久调用一次?它的名字意味着它将被重复called@JeremySayers使某些东西线程安全是复杂的,您可能应该阅读一些关于线程安全的教程。如果不需要,最简单的方法就是避免线程。有多种方法可以使某个线程安全,但归根结底,就是看线程在哪里可以交错,并检查如果语句按一定顺序运行,一个线程是否可以使另一个线程的假设无效。例如,在你的更新播放器中,你调用敌人.remove(),如果paint()在敌人中循环,当这种情况发生时,你会得到一个ConcurrentModificationException。
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();
        }
    }
                try {
                    Thread.sleep(1000/60);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }