View Full Version : TTimer
Delphi Kid
30-04-2004, 07:49 PM
Hi, I made a realtime game on a timer with interval 10ms.
I tested this game on the same computer but on 3 different OS.
Windows XP pro - 10ms 100%
Windows XP home - 15,5ms 64%
Windows 98 - 50ms 20%
WTF!!. This is weird. Obviously there is some setting in the OS that manipulate the Timer.
Also gettickcount seems to work on those rates, I used a ping method with gettickcount and on 98 I get only pings of 0-50-100-etc
Does anyone know how I can change those settings?
thx in advance
noeska
30-04-2004, 08:31 PM
I am using the threaded timer from http://www.carlosb.com now. This solved the timing problem with my openal modplayer.
TheLion
01-05-2004, 06:16 PM
NEVER EVER use TTimer object for a game! ;) hehe
It's really the most unreliable timer object I know! ;)
GetTickCount is quite accurate, however you can set the accuracy/resolution for this timer, which will also make it run sync on each system...
// Initialization
DWORD TickResolution;
TIMECAPS TimeCaps;
if (timeGetDevCaps(&TimeCaps, sizeof(TIMECAPS)) == TIMERR_NOERROR)
{
TickResolution = min(max(TimeCaps.wPeriodMin, 1U), TimeCaps.wPeriodMax);
timeBeginPeriod(TickResolution);
}
... // All game stuff
// Cleanup
timeEndPeriod(TickResolution);
(and yes the code above is C++, taken from here:
http://www.intheoryforum.com/viewtopic.php?t=43&start=0&postdays=0&postorder=asc&highlight=)
Delphi Kid
02-05-2004, 11:42 AM
Thanks lion. But can you convert that to delphi for me? or assembler?
TheLion
02-05-2004, 01:37 PM
Well... because you asked so nicely! ;)
var Form1: TForm1;
TickResolution : DWORD;
TimeCaps : TTIMECAPS;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
Begin
If ( TimeGetDevCaps(@TimeCaps, sizeof(TIMECAPS)) = TIMERR_NOERROR ) Then
Begin
// 1 ms = Accuracy, change the 1 in Max(TimeCaps.wPeriodMin, 1) for a different accuracy! :)
TickResolution := Min( Max(TimeCaps.wPeriodMin, 1), TimeCaps.wPeriodMax);
TimeBeginPeriod(TickResolution);
End;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// Cleanup
TimeEndPeriod(TickResolution);
End;
NOTE: You'll have to include the MMSystem and the Math unit in your application, however you could leave out the math unit and write your own Min/Max function! ;) This example sets the accuracy of the timer to 1 ms, but you could set the accuracy to whatever you want! :)
Delphi Kid
02-05-2004, 11:59 PM
Thanks for your effort! but ....
Well I added the code, unfortunately it is still skipping ~15 ms on my Win XP. I added a button that checks the gettickcount until 50ms passed. and gettickcount ends with 63 instead of 50.
Maybe I am doing something wrong :/
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, MMSystem , math, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
TickResolution : DWORD;
TimeCaps : TTIMECAPS;
i,number:integer;
implementation
{$R *.dfm}
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
TimeEndPeriod(TickResolution);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
If ( TimeGetDevCaps(@TimeCaps, sizeof(TIMECAPS)) = TIMERR_NOERROR ) Then
Begin
TickResolution := Min( Max(TimeCaps.wPeriodMin, 1), TimeCaps.wPeriodMax);
TimeBeginPeriod(TickResolution);
End;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
i:=gettickcount;
while i+50 > gettickcount do begin
number:=gettickcount-i;
end;
showmessage(inttostr(number));
end;
end.
edit: btw the comparison in oncreate procedure does return TIMERR_NOERROR, so thats not the problem
Useless Hacker
03-05-2004, 10:02 AM
You should be using timeGetTime (declared in MMSystem.pas) instead of GetTickCount.
noeska
04-05-2004, 05:28 PM
Try using the threaded timer component. It should do the trick.
TheLion
05-05-2004, 08:53 AM
Well in you ask the GetTickCount twice when calculating with it, so it allready passed the 50 when you calculate with it, however I didn't claim GetTickCount would be accurate! ;)
i:=gettickcount;
while i+50 > gettickcount do begin
// Here you ask the new GetTickCount, which is allready higher than the one in the while function...
number:=gettickcount-i;
end;
showmessage(inttostr(number));
end;
GetTickCount, will never be accurate, but you didn't ask for an accurate timer, you asked for a timer that would work approx. the same on all machines, don't forget you are using a loop and a few statements, all those things take time. But what do you need it for? If you want to make a sprite move timed over the screen then there is no need for perfect accuracy! :)
If you want a faster more accurate timer use the timeGetTime function Useless Hacker suggested or you could write or use a third-party threaded-timer, however most threaded-timers I've seen use GetTickCount or timeGetTime in combination with a sleep internally! :)
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.