And just for historical purposes, here's a version of GameTimer.pas that I'm using just now. I think I've got rid of the dependencies, but if not it should be easy enough anyway:
[pascal]unit GameTimer;
interface
const
TIME_AVERAGES_LENGTH = 8;
type
TGameTimer = class
private
FLastTimes: array[0..TIME_AVERAGES_LENGTH - 1] of Double;
FThisTime: Cardinal; // index in above array for current time
FLastTick: Int64;
FElapsedTime: Double;
protected
public
constructor Create;
destructor Destroy; override;
procedure Reset;
procedure Update;
property ElapsedTime: Double read FElapsedTime;
class function UsingHighPerformance: Boolean;
class function GetTimeFactor: Double;
end;
procedure InitGameTimer;
procedure KillGameTimer;
implementation
uses
//misc,
Windows,
MMSystem;
//------------------------------------------------------------------------------
var
FUseTimeGetTime: Boolean = False;
FTimeFactor : Double;
//------------------------------------------------------------------------------
class function TGameTimer.UsingHighPerformance: Boolean;
begin
Result := FUseTimeGetTime;
end;
//------------------------------------------------------------------------------
class function TGameTimer.GetTimeFactor: Double;
begin
Result := FTimeFactor;
end;
//------------------------------------------------------------------------------
constructor TGameTimer.Create;
begin
inherited;
Reset;
end;
//------------------------------------------------------------------------------
destructor TGameTimer.Destroy;
begin
inherited;
end;
//------------------------------------------------------------------------------
procedure TGameTimer.Reset;
var
i: Integer;
begin
FThisTime := 0;
for i := Low(FLastTimes) to High(FLastTimes) do
FLastTimes[i] := 0;
FElapsedTime := 0;
if FUseTimeGetTime then
FLastTick := TimeGetTime
else
QueryPerformanceCounter(FLastTick);
end;
//------------------------------------------------------------------------------
procedure TGameTimer.Update;
var
ThisTick: Int64;
i: Cardinal;
RunningCount: Double;
begin
if FUseTimeGetTime then
begin
ThisTick := TimeGetTime;
end
else
begin
// use high performance timer
QueryPerformanceCounter(ThisTick);
end;
FLastTimes[FThisTime] := (ThisTick - FLastTick) * FTimeFactor;
FLastTick := ThisTick;
FThisTime := (FThisTime + 1) and (TIME_AVERAGES_LENGTH - 1);
RunningCount := FLastTimes[0];
for i := 1 to High(FLastTimes) do
begin
RunningCount := RunningCount + FLastTimes[i];
end;
FElapsedTime := RunningCount / TIME_AVERAGES_LENGTH;
end;
//------------------------------------------------------------------------------
var
TicksPerSecond: Int64;
DevCaps: TTimeCaps;
procedure InitGameTimer;
begin
FUseTimeGetTime := (QueryPerformanceFrequency(TicksPerSecond) = False);
// if we're using timeGetTime, we need to set its resolution to the best
// possible - if we don't, it will be jerky on NT-based systems
if FUseTimeGetTime then
begin
FTimeFactor := 0.001;
FillChar(DevCaps, SizeOf(DevCaps), 0);
TimeGetDevCaps(@DevCaps, SizeOf(DevCaps));
TimeBeginPeriod(DevCaps.wPeriodMin);
end
else
begin
FTimeFactor := 1 / TicksPerSecond;
end;
// if FUseTimeGetTime then WriteLog('** Using low performance timer! **')
// else WriteLog('** Using high performance timer! **');
end;
//------------------------------------------------------------------------------
procedure KillGameTimer;
begin
if FUseTimeGetTime then
TimeEndPeriod(DevCaps.wPeriodMin);
end;
//------------------------------------------------------------------------------
end.[/pascal]
Bookmarks