FPS goes crazy after manualy restarting the game

Hi,

I’m having an fps issue when i restart my game manualy. It goes insane! hitting 5000 fps?

Normaly I hit 95 on level1
going to 110 when the level increase…

I looked at all my vars and they all get reset.
The function that does the restart is used with the button and with the r key

The button only can restart if the game has ended.

the r key can be pushed anytime.
I first set quit = true so that the loop stops if it was still running then startGame()

you can download the game @ http://www.kwbbz.be/Downloads/start.jnlp and see for yourself
what can be the cause of this?

The code involved:

  public synchronized void startGame() {
    eventHandler.fireGameEvent(GameEvent.Status.RUNNING);
    if( pauzed ) {
      pauzed = false;
    }
    else {
      System.out.println("Restart!");
      GameThread = null;
      board.clearBoard();
      quit = false;
      score = 0;
      level = 0;
      update_Timer = 0;
      move_Timer = 0;
      moveDelay = NORMAL_MOVE_DELAY;
      updateDelay = NORMAL_UPDATE_DELAY;
      sleepDelay = NORMAL_GAME_SLEEP_DELAY;
      curBlock = null;
      nextBlock = null;
      left = false;
      right = false;
      up = false;
      down = false;
      spaceBar = false;
      pauzed = false;
      startThread();
    }
  }

  private void startThread() {
    /* Initialize the game thread. */
    GameThread = new GameThread();
    GameThread.start();
  }

  private class GameThread extends Thread {
    public void run() {
      runGame();
    }
  }

This seems to be a ThreadStack overflow you make when restarting with “R” key. You should add a GameThread member to the Main class so that you can interrupt the previous running Thread before to start again. This is as easy.

BTW your jnlp file is ok, but you filled it somehow to make it working at all, didn’t you ? You may change the tag jnlp and add the original start.jnlp stored on the server then if you make change to the jnlp (if the description changes or the icon etc.), JWS will update directly from the base jnlp. That be :


<jnlp spec="1.0+"
  codebase="http://www.kwbbz.be/Downloads/" href="start.jnlp"
>(...)</jnlp>

However, I love to play Tetris… :smiley:

broumbroum, I don’t understand your first sentence. If you mean placing the Thread in the first Main object i make, then i don’t see how I could do that… I never use the Main object as a reference anywhere. so i can’t call the function startThread…
when I run the function startGame with the r key somethimes parts of blocks remain on the screen???

and yes i followed a tut on how to make a jnlp file and it seems to be doing what it is intented to do, so i rather not change it ;D
Thanks for checking the game it out :wink:

btw insert to toggle fps on or off.

ok bear with me i’m trying to understand what’s going on when I restart.

  1. Start Game, Start GameThread
  2. Game is looping
  3. User pushed button => added to Swing event Thread
  4. actionEvent handles the action and asks the game to restart(acording to the game state ofcourse)
  5. public synchronized void restart() {
    System.out.println(“restart!”);
    quit = true;
    startGame();
    }
  6. that means that we wait until we can lock the object? and then set quit to true, and then start the game again with the default values
    or does restart get called somewhere in the middle of the loop?

OK ! The correct operations are :

  1. Start Game, Start GameThread
  2. Game is looping
  3. User pushed button => added to Swing event Thread
  4. actionEvent handles the action and asks the game to restart(acording to the game state ofcourse)
  5. public synchronized void restart() {
    System.out.println(“restart!”);
    quit = true;
    startGame();
    }
    4.a) started the gameThread with startGame(), the next call to startGame() cannot launch the same Thread, right ?
    4.b) make a new Thread when the first one exited or caught interruption: that is, to make the running Thread with the current game stop and start the new Thread for a clean restart().
    4.c) next time I’ll wait on the lock…
  6. that means that we wait until we can lock the object? and then set quit to true, and then start the game again with the default values
    or does restart get called somewhere in the middle of the loop?

There’s the (Thread).interrupt() method to get one Thread interrupted. That Thread will then return false to (Thread).isAlive(). Then you can restart a new one for the game, that’s fair enough for the game reset switch. :smiley: do you understand ?

i’m trying to understand it broum, I used interupt and this is the code i got now, and… it works 90% of the time.
See the System output at the end of this post.

  public synchronized void startGame() {
    eventHandler.fireGameEvent(GameEvent.Status.RUNNING);
    if( pauzed ) {
      pauzed = false;
    }

    if( GameThread == null) {
      createThread(ThreadNumber++);
    }
    else{
      if( GameThread.isInterrupted() ) {
        createThread(ThreadNumber++);
      }
      else
        System.out.println("GameThread " + GameThread.getName() +" is not interupted? yet..." );
      }
  }
  private void createThread(int threatNumb) {
    /* Initialize the game thread. */
    GameThread = new GameThread();
    GameThread.setName("GameThread " + threatNumb);
    GameThread.start();
    System.out.println(GameThread.getName() + " Started");
  }

  private class GameThread extends Thread {
    public void run() {
      System.out.println("starting game.runGame()");
      runGame();
    }
  }

Note: skipped logic

  public void runGame() {
    boolean gameRunning = true;
    while (gameRunning) {
      /* Exits the game,
      * Placed above the other functions Because we need to draw one last String */
      if( quit ) {
        gameRunning = false;
        eventHandler.fireGameEvent(GameEvent.Status.END);
      }

      // sleep
      try {
        Thread.sleep(sleepDelay);
      } catch (InterruptedException e) {
        System.out.println("InterruptedException: " + e.getMessage());
        gameRunning = false;
      }
    }
    System.out.println("This Game has ended!");
  }
  public void restart() {
    System.out.println("RESTARTED!");
    if( GameThread != null && !pauzed) {
      GameThread.interrupt();
      startGame();
    }
    else
      System.out.println("Cannot Restart!");
  }

The console prints:

GameThread 15 Started InterruptedException: sleep interrupted This Game has ended! starting game.runGame() Create 2 Random Blocks: New Random Block 5 Starts at java.awt.Point[x=5,y=0] New Random Block 2 Starts at java.awt.Point[x=3,y=0] RESTARTED! GameThread 16 Started InterruptedException: sleep interrupted This Game has ended! starting game.runGame() Create 2 Random Blocks: New Random Block 7 Starts at java.awt.Point[x=4,y=0] New Random Block 7 Starts at java.awt.Point[x=7,y=0] RESTARTED! GameThread 17 Started InterruptedException: sleep interrupted This Game has ended! starting game.runGame() Create 2 Random Blocks: New Random Block 6 Starts at java.awt.Point[x=5,y=0] New Random Block 6 Starts at java.awt.Point[x=4,y=0] RESTARTED! InterruptedException: sleep interrupted This Game has ended! [b]GameThread GameThread 17 is not interupted? yet...[/b]

if I use isalive in

if( GameThread.isInterrupted() ) {
        createThread(ThreadNumber++);
      }

then I have to push 2 times before it detects that it is not alive anymore.

GameThread 0 Started starting game.runGame() Create 2 Random Blocks: New Random Block 5 Starts at java.awt.Point[x=5,y=0] New Random Block 5 Starts at java.awt.Point[x=5,y=0] RESTARTED! [b]GameThread GameThread 0 is still alive. InterruptedException: sleep interrupted[/b] This Game has ended! RESTARTED! GameThread 1 Started starting game.runGame() Create 2 Random Blocks: New Random Block 3 Starts at java.awt.Point[x=5,y=0] New Random Block 7 Starts at java.awt.Point[x=2,y=0] RESTARTED! GameThread GameThread 1 is still alive. InterruptedException: sleep interrupted This Game has ended! RESTARTED! GameThread 2 Started starting game.runGame() Create 2 Random Blocks: New Random Block 5 Starts at java.awt.Point[x=5,y=0] New Random Block 4 Starts at java.awt.Point[x=4,y=0] RESTARTED! GameThread GameThread 2 is still alive. InterruptedException: sleep interrupted This Game has ended!

Thank you for reporting! This is right, then your game doesn’t crash on restart, does it ? Now I’d simply change the sleep() function to a more accurate GameThread.wait(delay) to release the Thread lock. :smiley:

Despite the recorded framerate you’re getting a lot of flicker and the pad is very unresponsive. Not sure what you’re doing there, and sometimes it does not respond at all. Are you updating the game regularly?

I think this might be the problem:

    /* Default Action: Move the Block Down */
    update_Timer++;
    if( update_Timer % updateDelay == 0 ) {
      curBlock.move(Block.MOVE_DOWN);
      update_Timer = 0;
      step = true;
      moved = true;
    }

    /* Let the Player Move the Block in a Direction */
    move_Timer++;
    if( move_Timer % moveDelay == 0 ) {
      playerMove();
      move_Timer = 0;
      moved = true;
    }

I put this inside my game loop, i don’t know how to do it on another way.
alsoo the frames are counted for every loop, but not when a move occurs ::slight_smile:
and if you need more info I uploaded all my classes to http://www.kwbbz.be/Downloads/src2/be/JTetris/model/ since if I keep on posting code this topic is going to grow too big…

Well first of all try to keep the game speed as constant as you can. The gameboy Tetris runs at 60fps without fail, within this loop you check for the pad input and update the frame accordingly before generating the frame for output. Also consult the Tetris Concept wiki and forum for Tetris related topics, etc.

See the StrollDriver.java for how I manage keyboard input in Stroll. I have all of the code available on line at k:one labs.org. Generally if you stick to a typical game loop and try to work within common working practices you will find that things “just work”.

ok now I have fixed fps (not realy it floats around 40 - 60)
and after looking into my code I think I found where it goes wrong.

Note: moved = true means i do a repaint()

When a block get’s added to a board i set moved = true
When a block moves i set moved =true

But not for every loop only when the block actualy moved or when the player moved it…
alsoo blocks shouldn’t be falling straight to the buttom so this gives me this code inside the game logic.

    /* Default Action: Move the Block Down */
    update_Timer++;
    if( update_Timer % updateDelay == 0 ) {
      curBlock.move(Block.MOVE_DOWN);
      update_Timer = 0;
      step = true;
      moved = true;
    }

    /* Let the Player Move the Block in a Direction */
    move_Timer++;
    if( move_Timer % moveDelay == 0 ) {
      playerMove();
      move_Timer = 0;
      moved = true;
    }

When running with that code I get: http://www.kwbbz.be/Downloads/JTetris.jar
if I remove all the timing around playerMove() I get this: http://www.kwbbz.be/Downloads/JTetris1.1.jar
Can you please report back if you see a difference in flicker?
and if you do, when should I be repainting at another interval?

It is still missing frames, also your input is over sampling some how. I am still seeing flicker. As for the input problem, you need to sort out the delayed auto shift

ok, is it better to removed the playermove function out of my loop? and move Blocks directly?

I’m alsoo going to use the canvas instead of the JPanel. I’ll just start again from nothing.

I’ll see if I can look over your code on Saturday. But one thing to note is that Tetris, though simple, features many - if not most - elements present in a typical game. In something like Windows I go for the approach of having a “virtual pad”, and the keyboard input just toggles that. That way my game logic is simplistic and I can write boolean statements, such as:

int pressed_keys = ~last_keys & current_keys;

You might be doing that already, and your problems may be somewhere where you least expect it. For all you know it could be something as trivial as incorrectly managing the state and just not updating it as often as you think you are - and believe me, you’d be surprised how often things like that happen. That is not really a bug, more of a flaw; so in general try to pre-empt flaws and make them become big-bugs as soon as you can, because at least with a big-bug you see it right away.

I found the bug ;D

I was so focused on my loop that I didn’t even think it might be somwhere else.
In the board the updateblock function was sending events to update the board for every square in one Tetris piece Hence the flickering :o and moving slowness :confused:
Alsoo seperating the keyboard inputs from the game loop was a good thing to do i think.

Now I only have blocks falling down too fast on fast cpu’s because I use a counter instead of a time but that’s another story :smiley:

thx for the help guys.