This little lib is used to keep track of time using the low resolution timer provided by the OS (in Windows “GetTickCount”). The goal of this type of library is to encapsulate timing actions. It was originally designed for game development in mind but needless to say you can use it and adapt it to your own needs.
Basically you define a time interval as you create the “timelapse” instance. Every time you call the update function a simple check determines whether the time was reached or not. This is trivial, but encapsulating it makes sense. Specially if you plan to create an animation system in the future!
The code:
EnableExplicit Prototype.i TimeLapse_Callback( *this.i ) Structure TIMELAPSE old_time.i ; Stores the "old" time value. new_time.i ; Stores the "new" time value. time_out.i ; Time period for the TimeLapse , in ms. *callback.TimeLapse_Callback ; User callback. userdata.i ; User data. EndStructure CompilerSelect #PB_Compiler_OS CompilerCase #PB_OS_Windows Macro _time() : timeGetTime_() : EndMacro CompilerDefault Macro _time() : ElapsedMilliseconds() : EndMacro CompilerEndSelect Procedure.i TimeLapseCreate( Timeout.i, *Callback.TimeLapse_Callback = #Null, UserData.i = #Null ) Define.TimeLapse *this = AllocateMemory( SizeOf(TimeLapse ) ) If *this With *this \new_time = _time() \old_time = *this\new_time \time_out = Timeout \callback = *Callback \userdata = UserData EndWith ProcedureReturn *this EndIf EndProcedure Procedure.i TimeLapseDestroy( *this.TIMELAPSE ) If *this FreeMemory(*this) *this = #Null ProcedureReturn *this EndIf EndProcedure Procedure.i TimeLapseUpdate( *this.TIMELAPSE ) If *this *this\new_time = _time() If ((*this\new_time - *this\old_time) => *this\time_out) *this\old_time = *this\new_time If *this\callback ProcedureReturn *this\callback( *this ) EndIf ProcedureReturn #True EndIf EndIf EndProcedure ; Helper routines Procedure.i TimeLapseSet( *this.TIMELAPSE , Timeout.i ) If Timeout > 0 *this\time_out = Timeout EndIf EndProcedure Procedure.i TimeLapseGet( *this.TIMELAPSE ) ProcedureReturn *this\time_out EndProcedure
Example:
If OpenConsole() Define.TIMELAPSE *test_timer = TimeLapseCreate( 500 ) Repeat If TimeLapseUpdate( *test_timer ) PrintN(" Timer says hi!" ) EndIf Delay(10) Until Inkey() = Chr(27) CloseConsole() EndIf End
The nice thing about this library is the ability to use callbacks. Whenever a callback is defined, once the timer reaches the maximum allowed time-lapse, it’ll return by executing the callback.
In the callback you can do anything you want; From simple event triggering to manipulating another timer depending on XYZ conditions: it’s up to you!.
Just keep in mind: Always return “true” unless you want to invalidate the update call.
Here is a more advanced example with a callback, user data and multiple timers:
Procedure.i MyCallback( *this.TIMELAPSE ) ; It's imperative that you return #true (1) in your callbacks if you want the "Update" calls to pass once the timeout is reached. ; This is a design choice for flexibility and nothing else. ConsoleColor(Random(15), Random(15)) PrintN(" Hi from the callback! ") PrintN( " The other timer is set to: " + Str( TimeLapseGet( *this\userdata ) ) + "ms" ) PrintN( " ...Reducing the time interval down by 50 ms... " ) TimeLapseSet( *this\userdata, TimeLapseGet( *this\userdata ) - 50 ) ConsoleColor(15, 0) ProcedureReturn #True EndProcedure Define.TIMELAPSE *timer_one = TimeLapseCreate( 500 ) ; The first TimeLapse , nothing special. Define.TIMELAPSE *timer_two = TimeLapseCreate( 2000, @MyCallback(), *timer_one ) ; The second TimeLapse , it manipulates the first one through a callback. Define.TIMELAPSE *timer_three = TimeLapseCreate( 20*1000 ) ; This TimeLapse will simply let us exit the example after the set time. If OpenConsole() EnableGraphicalConsole(1) ConsoleColor(15, 0) Define.i quit = #False Repeat If TimeLapseUpdate( *timer_three ) quit = #True Else If TimeLapseUpdate( *timer_one ) PrintN("timer_one: " + Str(*timer_one\time_out) + "ms reached.") EndIf If TimeLapseUpdate( *timer_two ) PrintN("timer_two: " + Str(*timer_two\time_out) + "ms reached.") EndIf EndIf Delay(10) Until Inkey() = Chr(27) Or quit PrintN( "timer_three: The example finished." ) TimeLapseDestroy(*timer_one) TimeLapseDestroy(*timer_two) TimeLapseDestroy(*timer_three) Input() CloseConsole() EndIf End
The examples are crude, but they show every function in the library.
Should you have any questions, feel free to ask.
I’ll soon post the “Animation” lib that depends on “TimeLapse”.
Cheers.
Updated the base code, added the _time() macro. ( Internally ElapsedMilliseconds() resolves to GetTickCount() in Windows, this has a resolution of ~10ms which isn’t enough in some cases )
I found no need to manually set the minimum resolution for timeGetTime() but if you want to make sure you can always add the timeBeginPeriod / timeEndPeriod block with the desired minimum resolution. Just don’t do this on every iteration of your code.
[...] on the time-lapse lib, the animation code provides you with several count methods to manipulate your animations in an [...]