aboutsummaryrefslogtreecommitdiffstats
path: root/src/Classes/UTime.pas
blob: f8ae91c4b41a095d16f1968a68c76246b92dcfb3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
unit UTime;

interface

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

{$I switches.inc}

type
  TTime = class
    public
      constructor Create;
      function GetTime(): real;
  end;

  TRelativeTimer = class
    private
      AbsoluteTime: int64;      // system-clock reference time for calculation of CurrentTime
      RelativeTimeOffset: real;
      Paused: boolean;
      TriggerMode: boolean;
    public
      constructor Create(TriggerMode: boolean = false);
      procedure Pause();
      procedure Resume();
      function GetTime(): real;
      function GetAndResetTime(): real;
      procedure SetTime(Time: real; Trigger: boolean = true);
      procedure Reset();
  end;

procedure CountSkipTimeSet;
procedure CountSkipTime;
procedure CountMidTime;

var
  USTime      : TTime;
  VideoBGTimer: TRelativeTimer;

  TimeNew     : int64;
  TimeOld     : int64;
  TimeSkip    : real;
  TimeMid     : real;
  TimeMidTemp : int64;

implementation

uses
  sdl,
  ucommon;
  
const
  cSDLCorrectionRatio = 1000;

(*
BEST Option now ( after discussion with whiteshark ) seems to be to use SDL
timer functions...

SDL_delay
SDL_GetTicks
http://www.gamedev.net/community/forums/topic.asp?topic_id=466145&whichpage=1%EE%8D%B7
*)


procedure CountSkipTimeSet;
begin
  TimeNew     := SDL_GetTicks();
end;

procedure CountSkipTime;
begin
  TimeOld     := TimeNew;
  TimeNew     := SDL_GetTicks();
  TimeSkip    := (TimeNew-TimeOld) / cSDLCorrectionRatio;
end;

procedure CountMidTime;
begin
  TimeMidTemp := SDL_GetTicks();
  TimeMid     := (TimeMidTemp - TimeNew) / cSDLCorrectionRatio;
end;

{**
 * TTime
 **}

constructor TTime.Create;
begin
  inherited;
  CountSkipTimeSet;
end;

function TTime.GetTime: real;
begin
  Result := SDL_GetTicks() / cSDLCorrectionRatio;
end;

{**
 * TRelativeTimer
 **}

(*
 * Creates a new timer.
 * If TriggerMode is false (default), the timer
 * will immediately begin with counting.
 * If TriggerMode is true, it will wait until Get/SetTime() or Pause() is called
 * for the first time.
 *)
constructor TRelativeTimer.Create(TriggerMode: boolean);
begin
  inherited Create();
  Self.TriggerMode := TriggerMode;
  Reset();
  Paused := false;
end;

procedure TRelativeTimer.Pause();
begin
  RelativeTimeOffset := GetTime();
  Paused := true;
end;

procedure TRelativeTimer.Resume();
begin
  AbsoluteTime := SDL_GetTicks();
  Paused := false;
end;

(*
 * Returns the counter of the timer.
 * If in TriggerMode it will return 0 and start the counter on the first call.
 *)
function TRelativeTimer.GetTime: real;
begin
  // initialize absolute time on first call in triggered mode
  if (TriggerMode and (AbsoluteTime = 0)) then
  begin
    AbsoluteTime := SDL_GetTicks();
    Result := RelativeTimeOffset;
    Exit;
  end;

  if Paused then
    Result := RelativeTimeOffset
  else
    Result := RelativeTimeOffset + (SDL_GetTicks() - AbsoluteTime) / cSDLCorrectionRatio;
end;

(*
 * Returns the counter of the timer and resets the counter to 0 afterwards.
 * Note: In TriggerMode the counter will not be stopped as with Reset().
 *)
function TRelativeTimer.GetAndResetTime(): real;
begin
  Result := GetTime();
  SetTime(0);
end;

(*
 * Sets the timer to the given time. This will trigger in TriggerMode if
 * Trigger is set to true. Otherwise the counter's state will not change.
 *)
procedure TRelativeTimer.SetTime(Time: real; Trigger: boolean);
begin
  RelativeTimeOffset := Time;
  if ((not TriggerMode) or Trigger) then
    AbsoluteTime := SDL_GetTicks();
end;

(*
 * Resets the counter of the timer to 0.
 * If in TriggerMode the timer will not start counting until it is triggered again.
 *)
procedure TRelativeTimer.Reset();
begin
  RelativeTimeOffset := 0;
  if (TriggerMode) then
    AbsoluteTime := 0
  else
    AbsoluteTime := SDL_GetTicks();
end;

end.