Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: time based movement and WinAPI + DirectX

  1. #1

    time based movement and WinAPI + DirectX

    Hello

    I'm trying fix the movement using WinAPI and DirectX...

    My friend called me patrick showed a code of glscene that seems useful,

    My code of rendering need be in main loop and the movement of sprites must be at on timer event to stay working properly on all machines?

    loop program source:
    Code:
    
    procedure TConsole.OnProcess;
    begin
    
      Keyboard.Refresh();
    
      Device.Render(0,0,255);
    
    end;
    
    procedure TConsole.DoMove();
    begin
    
      if (Keyboard.Key[200]) then
      begin
    
                 Sprite.X := Sprite.X - 3;
    
                 Sprite.DoAnim(True, 0, 11, 0.5)
    
      end;
    
    end;
    
    procedure TConsole.OnRender(Sender: TObject);
    begin
    
      Sprite.Draw;
    
      DoMove();
    
    end;
    
      // Enter the message loop
          FillChar(msg, SizeOf(msg), 0);
          while &#40;msg.message <> WM_QUIT&#41; do
          begin
            if PeekMessage&#40;msg, 0, 0, 0, PM_REMOVE&#41; then
            begin
              TranslateMessage&#40;msg&#41;;
    
              DispatchMessage&#40;msg&#41;;
    
            end
          else
          begin
              Console.OnProcess;
          end;
          end;
    glscene's timer code:
    Code:
    unit AsyncTimer;
    
    interface
    
    &#123;$i GLScene.inc&#125;
    
    uses Classes;
    
    const
      cDEFAULT_TIMER_INTERVAL = 1000;
    
    &#123;$IFDEF UNIX&#125;
    type
      TThreadPriority = integer;
    &#123;$ENDIF&#125;
    
    type
       // TAsyncTimer
       //
       &#123;&#58; Asynchronous timer component &#40;actual 1 ms resolution, if CPU fast enough&#41;.<p>
          Keep in mind timer resolution is obtained <i>in-between</i> events, but
          events are not triggered every x ms. For instance if you set the interval to
          5 ms, and your Timer event takes 1 ms to complete, Timer events will actually
          be triggered every 5+1=6 ms &#40;that's why it's "asynchronous"&#41;.<p>
          This component is based on ThreadedTimer by Carlos Barbosa. &#125;
       TAsyncTimer = class&#40;TComponent&#41;
          private
             FEnabled&#58; Boolean;
             FOnTimer&#58; TNotifyEvent;
             FTimerThread&#58; TThread;
    
          protected
             procedure SetEnabled&#40;Value&#58; Boolean&#41;;
             function GetInterval&#58; Word;
             procedure SetInterval&#40;Value&#58; Word&#41;;
             function GetThreadPriority&#58; TThreadPriority;
             procedure SetThreadPriority&#40;Value&#58; TThreadPriority&#41;;
             procedure DoTimer;
    
          public
             constructor Create&#40;AOwner&#58; TComponent&#41;; override;
             destructor Destroy; override;
    
          published
             property Enabled&#58; Boolean read FEnabled write SetEnabled default False;
             property Interval&#58; Word read GetInterval write SetInterval  default cDEFAULT_TIMER_INTERVAL;
             property OnTimer&#58; TNotifyEvent read FOnTimer write FOnTimer;
             property ThreadPriority&#58; TThreadPriority read GetThreadPriority write SetThreadPriority &#123;$IFDEF WINDOWS&#125; default tpTimeCritical&#123;$ENDIF&#125;;
      end;
    
    // ------------------------------------------------------------------
    // ------------------------------------------------------------------
    // ------------------------------------------------------------------
    implementation
    // ------------------------------------------------------------------
    // ------------------------------------------------------------------
    // ------------------------------------------------------------------
    
    uses SysUtils, GLCrossPlatform;
    
    type
    
       // TTimerThread
       //
       TTimerThread = class&#40;TThread&#41;
          private
             FOwner&#58; TAsyncTimer;
             FInterval&#58; Word;
          protected
             constructor Create&#40;CreateSuspended&#58; Boolean&#41;; virtual;
             procedure Execute; override;
       end;
    
    // Create
    //
    constructor TTimerThread.Create&#40;CreateSuspended&#58; Boolean&#41;;
    begin
      inherited Create&#40;CreateSuspended&#41;;
    end;
    
    // Execute
    //
    procedure TTimerThread.Execute;
    var
       lastTick, nextTick, curTick, perfFreq &#58; Int64;
    begin
       QueryPerformanceFrequency&#40;perfFreq&#41;;
       QueryPerformanceCounter&#40;lastTick&#41;;
       nextTick&#58;=lastTick+&#40;FInterval*perfFreq&#41; div 1000;
       while not Terminated do begin
          while not Terminated do begin
             QueryPerformanceCounter&#40;lastTick&#41;;
             if lastTick>=nextTick then break;
             Sleep&#40;1&#41;;
          end;
          if not Terminated then begin
             // if time elapsed run user-event
             Synchronize&#40;FOwner.DoTimer&#41;;
             QueryPerformanceCounter&#40;curTick&#41;;
             nextTick&#58;=lastTick+&#40;FInterval*perfFreq&#41; div 1000;
             if nextTick<=curTick then begin
                // CPU too slow... delay to avoid monopolizing what's left
                nextTick&#58;=curTick+&#40;FInterval*perfFreq&#41; div 1000;
             end;
          end;
       end;
    end;
    
    &#123; TAsyncTimer &#125;
    
    // Create
    //
    constructor TAsyncTimer.Create&#40;AOwner&#58; TComponent&#41;;
    begin
       inherited Create&#40;AOwner&#41;;
       // create timer thread
       FTimerThread&#58;=TTimerThread.Create&#40;True&#41;;
       with TTimerThread&#40;FTimerThread&#41; do begin
          FOwner&#58;=Self;
          FreeOnTerminate&#58;=False;
          &#123;$IFDEF WINDOWS&#125; Priority&#58;=tpTimeCritical;&#123;$ENDIF&#125;
          FInterval&#58;=cDEFAULT_TIMER_INTERVAL;
       end;
    end;
    
    // Destroy
    //
    destructor TAsyncTimer.Destroy;
    begin
       Enabled&#58;=False;
       FTimerThread.Terminate;
       // if stopped, resume
       if FTimerThread.Suspended then
          FTimerThread.Resume;
       // wait & free
       FTimerThread.WaitFor;
       FTimerThread.Free;
       inherited Destroy;
    end;
    
    // DoTimer
    //
    procedure TAsyncTimer.DoTimer;
    begin
       if Enabled and Assigned&#40;FOnTimer&#41; then
          FOnTimer&#40;self&#41;;
    end;
    
    // SetEnabled
    //
    procedure TAsyncTimer.SetEnabled&#40;Value&#58; Boolean&#41;;
    begin
       if Value <FEnabled> 0 then begin
                FTimerThread.Resume;
             end;
          end
       else
          // suspend thread
          FTimerThread.Suspend;
       end;
    end;
    
    function TAsyncTimer.GetInterval&#58; Word;
    begin
      Result&#58;=TTimerThread&#40;FTimerThread&#41;.FInterval;
    end;
    
    procedure TAsyncTimer.SetInterval&#40;Value&#58; Word&#41;;
    begin
      if Value<>TTimerThread&#40;FTimerThread&#41;.FInterval then begin
        TTimerThread&#40;FTimerThread&#41;.FInterval&#58;=Value;
      end;
    end;
    
    function TAsyncTimer.GetThreadPriority&#58; TThreadPriority;
    begin
      Result&#58;=FTimerThread.Priority;
    end;
    
    procedure TAsyncTimer.SetThreadPriority&#40;Value&#58; TThreadPriority&#41;;
    begin
      FTimerThread.Priority&#58;=Value;
    end;
    
    end.
    Greetings
    Knowledge is power.

  2. #2

    time based movement and WinAPI + DirectX

    I use the TApplication.OnIdle event for my rendering. Every time this loop is executed, the FPS and the frametime are calculated. FrameTime is the time needed to render a frame. I use QueryPerformanceCounter and QueryPerformanceFrequency for this.

    And every time i move an object i do this:

    [pascal]
    Obj.x := Obj.x + 100*FrameTime;
    Obj.y := Obj.y + 100*FrameTime;
    [/pascal]

    So that the object is moved with respect to the time that passed. In my example, the object will move exactly 100 pixels to the right and 100 pixels to the bottom in one second.

    Hope this helps.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  3. #3

    time based movement and WinAPI + DirectX

    Quote Originally Posted by chronozphere
    I use the TApplication.OnIdle event for my rendering. Every time this loop is executed, the FPS and the frametime are calculated. FrameTime is the time needed to render a frame. I use QueryPerformanceCounter and QueryPerformanceFrequency for this.

    And every time i move an object i do this:

    [pascal]
    Obj.x := Obj.x + 100*FrameTime;
    Obj.y := Obj.y + 100*FrameTime;
    [/pascal]

    So that the object is moved with respect to the time that passed. In my example, the object will move exactly 100 pixels to the right and 100 pixels to the bottom in one second.

    Hope this helps.
    you need specify max FPS to use this? with low machines you need skip frames?
    Knowledge is power.

  4. #4

    time based movement and WinAPI + DirectX

    Nope i use this in my Engine and i didn't specify any max FPS. I should work for all FPSses, but when the FPS is really low, things might hitch a little. I don't know why you would skip frames :? ? I think you should not do that in any situation.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  5. #5

    time based movement and WinAPI + DirectX

    Quote Originally Posted by chronozphere
    Nope i use this in my Engine and i didn't specify any max FPS. I should work for all FPSses, but when the FPS is really low, things might hitch a little. I don't know why you would skip frames :? ? I think you should not do that in any situation.
    thanks for pointing your suggestion nathan,

    just more one question..

    what do u think if i put all render calls inside application.onidle and all movement inside my custom thread timer?
    Knowledge is power.

  6. #6

    time based movement and WinAPI + DirectX

    you cant avoid skipping frame (you can, but the game will run slower),

    you can use DetaTime (same as chronozphere suggested), the game will not run smother, but will run at the correct speed
    From brazil (:

    Pascal pownz!

  7. #7

    time based movement and WinAPI + DirectX

    what do u think if i put all render calls inside application.onidle and all movement inside my custom thread timer?
    You could do that, but i do think it has any advantages. You are running away from the actual problem, instead of solving it (check my sig ). I think it is better to make a decision. Use time-based movement with OnIdle and DeltaTime or FrameTime, or use a timer with a fixed interval. I would choose the first one.

    It is little harder to implement, but it is rewarding in the end.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  8. #8

    time based movement and WinAPI + DirectX

    You could do that, but i do think it has any advantages. You are running away from the actual problem, instead of solving it (check my sig ). I think it is better to make a decision. Use time-based movement with OnIdle and DeltaTime or FrameTime, or use a timer with a fixed interval. I would choose the first one.

    It is little harder to implement, but it is rewarding in the end.
    what is better? DeltaTime(FrameTime) or timer with fixed interval?

    These methods have large differences?
    Knowledge is power.

  9. #9

    time based movement and WinAPI + DirectX

    Quote Originally Posted by lordzero
    You could do that, but i do think it has any advantages. You are running away from the actual problem, instead of solving it (check my sig ). I think it is better to make a decision. Use time-based movement with OnIdle and DeltaTime or FrameTime, or use a timer with a fixed interval. I would choose the first one.

    It is little harder to implement, but it is rewarding in the end.
    what is better? DeltaTime(FrameTime) or timer with fixed interval?

    These methods have large differences?
    both will result in same, just pick what you find easier (probably a Timer)
    From brazil (:

    Pascal pownz!

  10. #10

    time based movement and WinAPI + DirectX

    Quote Originally Posted by arthurprs
    Quote Originally Posted by lordzero
    You could do that, but i do think it has any advantages. You are running away from the actual problem, instead of solving it (check my sig ). I think it is better to make a decision. Use time-based movement with OnIdle and DeltaTime or FrameTime, or use a timer with a fixed interval. I would choose the first one.

    It is little harder to implement, but it is rewarding in the end.
    what is better? DeltaTime(FrameTime) or timer with fixed interval?

    These methods have large differences?
    both will result in same, just pick what you find easier (probably a Timer)
    I suspected this... I will stay with the thread timer for a while

    If anyone has any suggestions post more ...

    Thanks arthur and nathan
    Knowledge is power.

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •