Forum > Games

Game loop input/logic timing

(1/2) > >>

mrguzgog:
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:
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:
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var  Timer: ALLEGRO_TIMERptr;procedure ProcessInit;begin   //...   // Enable timer for fixed fps  Timer := al_create_timer(1 / 60); // we use 60 fps  EventQueue := al_create_event_queue;  al_register_event_source(EventQueue, al_get_timer_event_source(timer));  al_start_timer(Timer);   // Start the game  GameIsRunning := True; end;   { Game Loop }var  Event: ALLEGRO_EVENT;begin  ProcessInit;  Start(Intro1);  while (GameIsRunning) do begin    al_wait_for_event(EventQueue, Event);    ProcessUserInput;    ProcessUpdate;    ProcessDrawing;  end;  ProcessShutdown;end.

mrguzgog:

--- Quote from: Handoko 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:

--- End quote ---

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: ---    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

--- End code ---

Ñuño_Martínez:

--- Quote from: mrguzgog on January 17, 2018, 06:46:24 pm ---
--- Code: ---    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

--- End code ---

--- End quote ---
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  PROCEDURE GameLoopExample;  VAR    Event: ALLEGRO_EVENT; { Not sure if it is better if this is local or not. }    NeedRender: BOOLEAN;  BEGIN    NeedRender := FALSE;    WHILE GameState = TGameState.PLAY DO { Avoiding inverse logic if possible. }    BEGIN      al_wait_for_event (GameEventQueue, Event);      CASE Event._type OF      ALLEGRO_EVENT_TIMER:        BEGIN          UpdateGameLogic;          NeedRender := TRUE        END;      ALLEGRO_EVENT_KEY_DOWN, ALLEGRO_EVENT_KEY_UP:        PlayInput (Event);      END;    { Render if needed and no events are waiting.       This way it will skip frames if game is slow(ed). }      IF NeedRender AND al_is_event_queue_empty (GameEventQueue) THEN      BEGIN        RenderGame;        NeedRender := FALSE      END    END  END; 

Navigation

[0] Message Index

[#] Next page

Go to full version