From c90b25a55c9e3a454eb951f5e25f2555e582c238 Mon Sep 17 00:00:00 2001 From: George Kurelic Date: Fri, 23 Feb 2024 19:50:25 -0800 Subject: [PATCH] Add FlxTimer.wait and FlxTimer.loop (#3040) * add FlxTimer.wait * fix arg * remove loops from wait, take no arg in callback, add loop() * simplify wait * docs --- flixel/util/FlxTimer.hx | 39 ++++++++++++++++++---- tests/unit/src/flixel/util/FlxTimerTest.hx | 27 ++++++++++++++- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/flixel/util/FlxTimer.hx b/flixel/util/FlxTimer.hx index a7a4347d33..4495fc7d3a 100644 --- a/flixel/util/FlxTimer.hx +++ b/flixel/util/FlxTimer.hx @@ -21,6 +21,32 @@ import flixel.util.FlxDestroyUtil.IFlxDestroyable; */ class FlxTimer implements IFlxDestroyable { + /** + * Handy tool to create and start a `FlxTimer` + * @param time The duration of the timer, in seconds. If `0` then `onComplete` + * fires on the next game update. + * @param onComplete Triggered whenever the time runs out + * @return The `FlxTimer` instance + */ + public static inline function wait(time:Float, onComplete:()->Void) + { + return new FlxTimer().start(time, (_)->onComplete()); + } + + /** + * Handy tool to create and start a `FlxTimer` + * @param time The duration of the timer, in seconds. If `0` then `onComplete` + * fires on the next game update, and the `loops` argument is ignored. + * @param onComplete triggered whenever the time runs out, once for each loop. + * Should take a single `Int` arg representing the number of completed loops + * @param loops How many times the timer should go off. `0` means "looping forever". + * @return The `FlxTimer` instance + */ + public static inline function loop(time:Float, onComplete:(loop:Int)->Void, loops:Int) + { + return new FlxTimer().start(time, (t)->onComplete(t.elapsedLoops), loops); + } + /** * The global timer manager that handles global timers * @since 4.2.0 @@ -54,10 +80,9 @@ class FlxTimer implements IFlxDestroyable public var finished:Bool = false; /** - * Function that gets called when timer completes. - * Callback should be formed "onTimer(Timer:FlxTimer);" + * Called when timer completes. The function header should be `(timer:FlxTimer)` */ - public var onComplete:FlxTimer->Void; + public var onComplete:(FlxTimer)->Void; /** * Read-only: check how much time is left on the timer. @@ -115,14 +140,14 @@ class FlxTimer implements IFlxDestroyable /** * Starts the timer and adds the timer to the timer manager. * - * @param time How many seconds it takes for the timer to go off. - * If 0 then timer will fire OnComplete callback only once at the first call of update method (which means that Loops argument will be ignored). + * @param time The duration of the timer, in seconds. If `0` then `onComplete` + * fires on the next game update, and the `loops` argument is ignored. * @param onComplete Optional, triggered whenever the time runs out, once for each loop. - * Callback should be formed "onTimer(Timer:FlxTimer);" + * The function header should be `(timer:FlxTimer)` * @param loops How many times the timer should go off. 0 means "looping forever". * @return A reference to itself (handy for chaining or whatever). */ - public function start(time:Float = 1, ?onComplete:FlxTimer->Void, loops:Int = 1):FlxTimer + public function start(time:Float = 1, ?onComplete:(FlxTimer)->Void, loops:Int = 1):FlxTimer { if (manager != null && !_inManager) { diff --git a/tests/unit/src/flixel/util/FlxTimerTest.hx b/tests/unit/src/flixel/util/FlxTimerTest.hx index ab10d6495f..edc3519b2d 100644 --- a/tests/unit/src/flixel/util/FlxTimerTest.hx +++ b/tests/unit/src/flixel/util/FlxTimerTest.hx @@ -18,8 +18,9 @@ class FlxTimerTest extends FlxTest { var calledBack:Bool = false; timer.start(0, function(_) calledBack = true); + + Assert.isFalse(calledBack); step(); - Assert.isTrue(calledBack); } @@ -67,4 +68,28 @@ class FlxTimerTest extends FlxTest Assert.isTrue(timer2.progress > 0); Assert.isTrue(timer3.progress > 0); } + + @Test + function testWait() + { + var calledBack = false; + function onComplete() { calledBack = true; } + final timer1 = FlxTimer.wait(2/60, onComplete); + final timer2 = FlxTimer.wait(0.0001, timer1.cancel); + + step(3); + Assert.isTrue(timer1.finished && calledBack); + } + + @Test + function testLoop() + { + var calledBack = false; + function onComplete(n) { calledBack = true; } + final timer1 = FlxTimer.loop(2/60, onComplete, 0); + final timer2 = FlxTimer.loop(0.0001, (loop)->{ if (loop == 3) timer1.cancel(); }, 3); + + step(3); + Assert.isTrue(timer1.finished && calledBack); + } }