Recent

Author Topic: Game loop input/logic timing  (Read 7025 times)

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Game loop input/logic timing
« on: January 17, 2018, 04:49:01 pm »
I have my main game loop set up with a timer that calls the rendering routine at the required rate (fps), calls the game logic routine and the input routine. It works fine as an empty framework but I wonder if I should I have separate timers for logic and input as well or maybe just pass them the elapsed time?

I'm familiar with the idea of delta time (dt) from using a couple of different game frameworks that use this concept. I'd like to get some feedback before going any further and having to restructure everything! :D


Handoko

  • Hero Member
  • *****
  • Posts: 5129
  • My goal: build my own game engine using Lazarus
Re: Game loop input/logic timing
« Reply #1 on: January 17, 2018, 05:03:58 pm »
I might be wrong. But I don't think using several timers is a good idea. It will make the code harder to debug, I frequent see beginners have problems handling multiple processes running at the same time. But, I know you're an experienced programmer, it won't be any problem for you.

http://gameprogrammingpatterns.com/game-loop.html

Any reasons to use more than 1 timer for game loop?

Handoko

  • Hero Member
  • *****
  • Posts: 5129
  • My goal: build my own game engine using Lazarus
Re: Game loop input/logic timing
« Reply #2 on: January 17, 2018, 05:15:31 pm »
I forgot to say, on Allegro5 you can use al_wait_for_event for the game loop:
https://www.allegro.cc/manual/5/al_wait_for_event

This is my game loop on my previous game demo "Furious Paladin":
Code: Pascal  [Select][+][-]
  1. var
  2.   Timer: ALLEGRO_TIMERptr;
  3. procedure ProcessInit;
  4. begin
  5.  
  6.   //...
  7.  
  8.   // Enable timer for fixed fps
  9.   Timer := al_create_timer(1 / 60); // we use 60 fps
  10.   EventQueue := al_create_event_queue;
  11.   al_register_event_source(EventQueue, al_get_timer_event_source(timer));
  12.   al_start_timer(Timer);
  13.  
  14.   // Start the game
  15.   GameIsRunning := True;
  16.  
  17. end;  
  18.  
  19. { Game Loop }
  20. var
  21.   Event: ALLEGRO_EVENT;
  22. begin
  23.   ProcessInit;
  24.   Start(Intro1);
  25.   while (GameIsRunning) do begin
  26.     al_wait_for_event(EventQueue, Event);
  27.     ProcessUserInput;
  28.     ProcessUpdate;
  29.     ProcessDrawing;
  30.   end;
  31.   ProcessShutdown;
  32. end.
« Last Edit: January 17, 2018, 05:45:12 pm by Handoko »

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Re: Game loop input/logic timing
« Reply #3 on: January 17, 2018, 06:46:24 pm »
I forgot to say, on Allegro5 you can use al_wait_for_event for the game loop:

Thanks for the reply. I'm doing pretty much the same thing at the minute but wonder whether they should be separated further? If the drawing or logic can't complete before the next timer event, everything will slow down. I don't plan of putting great demands on either routine so it probably won't be an issue but might as well take it into account now rather than later :D

Code: [Select]
    procedure playUpdate();
    begin
        repeat
            //ignore window events for now
            al_wait_for_event(gameEventQueue, gameEvent);
            if gameEvent._type = ALLEGRO_EVENT_TIMER then
                playDraw();
               
            if gameEvent._type = ALLEGRO_EVENT_KEY_DOWN then   
                playInput();
               
        until gameState <> TGameState.PLAY;
    end;
    // cleanup resources

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1186
    • Burdjia
Re: Game loop input/logic timing
« Reply #4 on: January 17, 2018, 07:22:49 pm »
Code: [Select]
    procedure playUpdate();
    begin
        repeat
            //ignore window events for now
            al_wait_for_event(gameEventQueue, gameEvent);
            if gameEvent._type = ALLEGRO_EVENT_TIMER then
                playDraw();
               
            if gameEvent._type = ALLEGRO_EVENT_KEY_DOWN then   
                playInput();
               
        until gameState <> TGameState.PLAY;
    end;
    // cleanup resources
That game loop isn't as good as it should be.  Don't use a timer to know when to draw but when to update your game logic and draw only when no events are waiting.  For example:
Code: Pascal  [Select][+][-]
  1.   PROCEDURE GameLoopExample;
  2.   VAR
  3.     Event: ALLEGRO_EVENT; { Not sure if it is better if this is local or not. }
  4.     NeedRender: BOOLEAN;
  5.   BEGIN
  6.     NeedRender := FALSE;
  7.     WHILE GameState = TGameState.PLAY DO { Avoiding inverse logic if possible. }
  8.     BEGIN
  9.       al_wait_for_event (GameEventQueue, Event);
  10.       CASE Event._type OF
  11.       ALLEGRO_EVENT_TIMER:
  12.         BEGIN
  13.           UpdateGameLogic;
  14.           NeedRender := TRUE
  15.         END;
  16.       ALLEGRO_EVENT_KEY_DOWN, ALLEGRO_EVENT_KEY_UP:
  17.         PlayInput (Event);
  18.       END;
  19.     { Render if needed and no events are waiting.
  20.        This way it will skip frames if game is slow(ed). }
  21.       IF NeedRender AND al_is_event_queue_empty (GameEventQueue) THEN
  22.       BEGIN
  23.         RenderGame;
  24.         NeedRender := FALSE
  25.       END
  26.     END
  27.   END;
  28.  
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Re: Game loop input/logic timing
« Reply #5 on: January 17, 2018, 07:47:12 pm »
That game loop isn't as good as it should be.  Don't use a timer to know when to draw but when to update your game logic and draw only when no events are waiting.
Thanks for that, understood. I didn't have any mention of game logic in my code as there isn't any yet ;D But yes, I'll add only rendering when necessary and when no other events are pending. My ALLEGRO_EVENT variable gameEvent is global (as are all the other game-wide things such as display, event queue, timer etc). It means I can use essentially the same code in the 'menu' and 'options' states as well as 'play'.

 

TinyPortal © 2005-2018