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:
glscene's timer code: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 (msg.message <> WM_QUIT) do begin if PeekMessage(msg, 0, 0, 0, PM_REMOVE) then begin TranslateMessage(msg); DispatchMessage(msg); end else begin Console.OnProcess; end; end;
GreetingsCode:unit AsyncTimer; interface {$i GLScene.inc} uses Classes; const cDEFAULT_TIMER_INTERVAL = 1000; {$IFDEF UNIX} type TThreadPriority = integer; {$ENDIF} type // TAsyncTimer // {: Asynchronous timer component (actual 1 ms resolution, if CPU fast enough).<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 (that's why it's "asynchronous").<p> This component is based on ThreadedTimer by Carlos Barbosa. } TAsyncTimer = class(TComponent) private FEnabled: Boolean; FOnTimer: TNotifyEvent; FTimerThread: TThread; protected procedure SetEnabled(Value: Boolean); function GetInterval: Word; procedure SetInterval(Value: Word); function GetThreadPriority: TThreadPriority; procedure SetThreadPriority(Value: TThreadPriority); procedure DoTimer; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property Enabled: Boolean read FEnabled write SetEnabled default False; property Interval: Word read GetInterval write SetInterval default cDEFAULT_TIMER_INTERVAL; property OnTimer: TNotifyEvent read FOnTimer write FOnTimer; property ThreadPriority: TThreadPriority read GetThreadPriority write SetThreadPriority {$IFDEF WINDOWS} default tpTimeCritical{$ENDIF}; end; // ------------------------------------------------------------------ // ------------------------------------------------------------------ // ------------------------------------------------------------------ implementation // ------------------------------------------------------------------ // ------------------------------------------------------------------ // ------------------------------------------------------------------ uses SysUtils, GLCrossPlatform; type // TTimerThread // TTimerThread = class(TThread) private FOwner: TAsyncTimer; FInterval: Word; protected constructor Create(CreateSuspended: Boolean); virtual; procedure Execute; override; end; // Create // constructor TTimerThread.Create(CreateSuspended: Boolean); begin inherited Create(CreateSuspended); end; // Execute // procedure TTimerThread.Execute; var lastTick, nextTick, curTick, perfFreq : Int64; begin QueryPerformanceFrequency(perfFreq); QueryPerformanceCounter(lastTick); nextTick:=lastTick+(FInterval*perfFreq) div 1000; while not Terminated do begin while not Terminated do begin QueryPerformanceCounter(lastTick); if lastTick>=nextTick then break; Sleep(1); end; if not Terminated then begin // if time elapsed run user-event Synchronize(FOwner.DoTimer); QueryPerformanceCounter(curTick); nextTick:=lastTick+(FInterval*perfFreq) div 1000; if nextTick<=curTick then begin // CPU too slow... delay to avoid monopolizing what's left nextTick:=curTick+(FInterval*perfFreq) div 1000; end; end; end; end; { TAsyncTimer } // Create // constructor TAsyncTimer.Create(AOwner: TComponent); begin inherited Create(AOwner); // create timer thread FTimerThread:=TTimerThread.Create(True); with TTimerThread(FTimerThread) do begin FOwner:=Self; FreeOnTerminate:=False; {$IFDEF WINDOWS} Priority:=tpTimeCritical;{$ENDIF} FInterval:=cDEFAULT_TIMER_INTERVAL; end; end; // Destroy // destructor TAsyncTimer.Destroy; begin Enabled:=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(FOnTimer) then FOnTimer(self); end; // SetEnabled // procedure TAsyncTimer.SetEnabled(Value: Boolean); begin if Value <FEnabled> 0 then begin FTimerThread.Resume; end; end else // suspend thread FTimerThread.Suspend; end; end; function TAsyncTimer.GetInterval: Word; begin Result:=TTimerThread(FTimerThread).FInterval; end; procedure TAsyncTimer.SetInterval(Value: Word); begin if Value<>TTimerThread(FTimerThread).FInterval then begin TTimerThread(FTimerThread).FInterval:=Value; end; end; function TAsyncTimer.GetThreadPriority: TThreadPriority; begin Result:=FTimerThread.Priority; end; procedure TAsyncTimer.SetThreadPriority(Value: TThreadPriority); begin FTimerThread.Priority:=Value; end; end.




Reply With Quote
). 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. 