所以对于我正在创建的游戏,我意识到我的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();
}
}
那么,为什么每次循环停止并再次启动时,它都会以一半的速度运行呢?谢谢!
2条答案
按热度按时间zc0qhyus1#
看起来你正在为每个游戏循环启动一个新线程;这意味着每次gameloop运行时,都有另一个线程供javavm处理。这是非常低效的,因为最终会有1000个线程运行,造成巨大的延迟。你有没有办法不用线程来重写你的代码?
还有,这是怎么回事?
你为什么要做1000/60?a:为什么不用16呢?b:看来你是想说别的,但不知道是什么意思
另外,您在数据库中引用的bg变量是什么
start()
以及stop()
方法?kcrjzv8t2#
看起来您正在尝试使用gamerunning布尔值来停止线程。如果这不是易变的,那么游戏循环可能不会注意到gui线程的更改,而gui线程将其设置为false并将永远运行。即使它是易变的,如果在游戏线程注意到stop命令之前再次调用start,您也有一个争用条件。
相反,您应该在创建的线程中存储一个引用,并在stop方法中中断它。
另外,对于paint方法,所有的更新方法都是线程安全的。updateplayer看起来不是线程安全的,而且您不知道何时调用paint,因此它可能与update方法同时发生。即使paint方法不写入共享数据,由于缺少内存屏障,它仍然可以看到不一致的数据。
我建议在gui线程中进行所有更新,除非它非常慢并且需要多线程处理。看看如何使用swing中的计时器来启动更新逻辑。