Reputation: 637
so for the game I'm creating I realized I mist have done something wrong with my gameLoop because the first time I play through my game it runs great, but the second time or anything after that, it slows down by about half. Even if I minimize the game (Because that stops the gameLoop, and then bringing it up again starts it back up) here is the gameLoop code:
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();
}
I start it for the first time in the init() just with
gameLoop();
And then I also have:
public void stop(){
bg.stop();
gameRunning = false;
}
public void start(){
bg.start();
gameRunning = true;
gameLoop();
}
And finally the playerUpdate also stops the loop with (The Thread inside of player is to allow for some effects to finish after the player dies):
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;
}
}
}
}
And then it is restarted with in the keyPressed event:
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();
}
}
So why is it that whenever the loop is stopped and started again, it runs at half the speed? Thanks!
Upvotes: 0
Views: 482
Reputation: 2656
It looks like you are trying to stop the thread by using the gameRunning boolean. If this is not volatile, then the game loop may not notice changes from the GUI thread that sets it to false and will run forever. Even if it is volatile, you have a race condition if start is called again before the game thread notices the stop command.
You should instead store a reference the the created thread and interrupt it in your stop method.
Also are all your update methods thread safe with respect to the paint method. updatePlayer doesn't look thread safe, and you don't know when paint will be called so it could happen at the same time as your update method. Even if the paint method doesn't write to the shared data, it could still see inconsistent data due to lack of a memory barrier.
I'd suggest doing all the updates in the GUI thread unless it is very slow and you need the multithreading. Look at using a Timer from Swing to to initiate your update logic.
Upvotes: 0
Reputation: 7326
It looks like you're starting a new thread for each gameloop; this means each time the gameloop runs, you've got another thread for the Java VM to handle. This is extremely inefficient, as eventually you'll have 1000 threads running, causing HUGE lag. Is there any way you could rewrite your code without threading there?
Also, what is this supposed to do?
try {
Thread.sleep(1000/60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Why would you do 1000/60? A: Why not just use 16? B: It seems like you meant something else here, not sure what though
Also, what is the bg variable your reference in your start()
and stop()
methods?
Upvotes: 1