Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've seen in some other simple 2D games that a "tick" method is used to sync game logic and graphics rendering. My main reason for using this is due to my collision detection malfunctioning, since the player entity will completely pass through solid objects unless I tap the controls almost pixel-by-pixel to collide the rectangles.

I figure a tick method will slow the games rapid updating enough to pick up these slight collision detections.

How do I create such a method? I've tried the code you can see below, however, it is causing the entire game to freeze:

The update method:

 @Override
    public void update(float deltaTime) {
        List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
            long lastTime = 0;
            long currentTime = 0;

        if (state == GameState.Ready) {
            updateReady(touchEvents);
        }
        while (state == GameState.Running) {
                lastTime = currentTime;
                currentTime = System.currentTimeMillis();
                deltaTime = currentTime - lastTime;

                player.update(touchEvents, deltaTime);
                repaint(deltaTime);
        }
        if (state == GameState.Paused) {
            updatePaused(touchEvents);
        }
        if (state == GameState.GameOver) {
            updateGameOver(touchEvents);
        }
    }

The repaint method, which is updated while the regular paint method does nothing. I've tried the while loop with both, doesn't seem to stop freezing:

public void repaint(float deltaTime) {
        Graphics g = game.getGraphics();

        if(deltaTime >= 60) {
            g.drawRect(0, 0, 805, 485, color.black);
            map.loadMap(getXScroll(), getYScroll(), g, game);
            map.loadEntities(getXScroll(), getYScroll(), g, game, map);
            g.drawImage(Assets.bitSoldier, 448, 256);
            g.drawImage(Assets.dpad, 0, 280);

            // Secondly, draw the UI above the game elements.
            if (state == GameState.Ready)
                drawReadyUI();
            if (state == GameState.Running)
                drawRunningUI();
            if (state == GameState.Paused)
                drawPausedUI();
            if (state == GameState.GameOver)
                drawGameOverUI();
        }
    }
share|improve this question
    
    
You're sleeping for 100 ms between simulations, I'd recommend from personal experience that the maximal you should sleep for is 40ms. –  Shaun Wild Jun 7 '13 at 3:39
1  
Ideally, you shouldn't sleep at all - update your logic as often as possible (smaller time steps also lower the chance of such ghosting). Assume you're intentionally sleeping for 40ms, your rendering/updating takes 10ms - you're at 50 ms per cycle, which might essentially limit you to 20 frames per second without any significant reason. –  Mario Jun 7 '13 at 11:53

1 Answer 1

up vote 6 down vote accepted

In general, there are two ways to make game logic "tick":

  • Fixed time steps run a fixed number of times per second, for example 100 times or maybe even 1000 times.
  • Dynamic time steps run the game logic whenever possible, considering the time passed since the last update.

Both approaches got their advantages and disadvantages, depending on what you're trying to achieve.

For movement and such, dynamic timesteps might be better, but for things such as animating pixel graphics, fixed timesteps might be more interesting. You can mix and match both as you like.

In general, as I mentioned in the comments, you should never let your program sleep in the game loop. This slows down the game without any reason and might even create stutter despite the computer being powerful enough to actually run the game without slowdowns.

Your generic game loop should look a bit like this (pseudo code):

function mainloop() {
    double time_passed = 0;
    double delta_time = 0;

    while (running) { // keep running

        // update game logic based on time passed
        updateDynamicStep(delta_time);

        // update game logic once for every tick passed
        while (time_passed >= time_per_timestep) {
            updateFixedStep();
            time_passed -= time_per_timestep;
            // You might limit the number of iterations here (like 10)
            // to not get stuck due to processing taking too long (and time adding up)
        }

        // draw screen content
        drawStuff(delta_time);

        // update timing
        delta_time = getTimePassedAndResetTimer();
        time_passed += delta_time;
    }
}

Doing it that way - no matter whether you use fixed time steps or not - has the advantage that your game will always run at the same speed, no matter whether you're running at 60 fps, 100 fps, 5000 fps, or only 15 fps.

The only reason to force sleeps could be to save battery (e.g. mobile games), but again I wouldn't sleep for fixed time, just sleep based on the time this iteration took and the time you planned for one frame. For example, if updating your game and drawing takes 10 ms and you plan on running at 60 frames per second, sleep for 5 ms (15ms total; perfect time would be 16.67ms, but you're leaving some space for other stuff like context switches and the like).

share|improve this answer
    
I especially liked the bit about mobile games since I'm designing an android app game. However, I'm not the best at deciphering pseudo-code-where would the variable time_per_timestep derive from? –  A13X Jun 7 '13 at 21:24
    
That's something you define, essentially it depends on your timer resolution, i.e. it's the time between update calls. For example, let's assume the timer represents milliseconds and you want 100 updates per second, you'd use time_per_timestep = 1000.0 / 100;. –  Mario Jun 8 '13 at 8:55
    
Here's another predicament...the while loop seems to freeze the game and it doesn't repaint the screen or allow any interaction. Perhaps it has to do with the mobile platform and the way I am using the Activity or something that its blocking out important processes always running during the app? –  A13X Jun 9 '13 at 0:01
    
-Check the original post for more info on this problem. –  A13X Jun 9 '13 at 0:19
2  
You misunderstood the framework calling update() and repaint(). These essentially work already in such a way I described in my example (these are essentially updateDynamicStep() and drawStuff()). You're essentially trying to nest a main loop in a main loop, which won't work. You have to leave update() for the framework to redraw and accept events. –  Mario Jun 9 '13 at 9:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.