avm2: Fix handling of completed timers
It's possible to call 'start()' on a timer that has currentCount >= repeatCount. This will cause the timer to tick exactly once, and then stop agian. We were incorrectly reporting 'timer.running' in such a scenario: 'running' should be reported as 'true' up until just before the 'TimerEvent.TIMER_COMPLETE' is fired. This fixes gaining money from bloon popping / level completion in BTD5.
This commit is contained in:
parent
92776645b8
commit
b27bcf367c
|
@ -49,7 +49,7 @@ package flash.utils {
|
|||
}
|
||||
|
||||
public function get running(): Boolean {
|
||||
return this._timerId != -1 && (this.repeatCount == 0 || this._currentCount < this._repeatCount);
|
||||
return this._timerId != -1;
|
||||
}
|
||||
|
||||
public function reset():void {
|
||||
|
@ -65,6 +65,8 @@ package flash.utils {
|
|||
this._currentCount += 1;
|
||||
this.dispatchEvent(new TimerEvent(TimerEvent.TIMER, false, false));
|
||||
if (this.repeatCount != 0 && this._currentCount >= this._repeatCount) {
|
||||
// This will make 'running' return false in a TIMER_COMPLETE event handler
|
||||
this._timerId = -1;
|
||||
this.dispatchEvent(new TimerEvent(TimerEvent.TIMER_COMPLETE, false, false));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,9 @@ pub fn start<'gc>(
|
|||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
// Note - we deliberately do *not* check if currentCount is less than repeatCount.
|
||||
// Calling 'start' on a timer that has currentCount >= repeatCount will tick exactly
|
||||
// once, and then stop immediately. This is handeld by Timer.onUpdate
|
||||
let id = activation.context.timers.add_timer(
|
||||
TimerCallback::Avm2Callback {
|
||||
closure: on_update,
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package {
|
||||
import flash.events.TimerEvent;
|
||||
import flash.utils.Timer;
|
||||
import flash.utils.setTimeout;
|
||||
|
||||
public class Test {
|
||||
public function Test() {
|
||||
var timer = new Timer(100, 2);
|
||||
timer.addEventListener(TimerEvent.TIMER, function(e) {
|
||||
trace("TimerEvent.TIMER: timer.running=" + timer.running + " timer.currentCount=" + timer.currentCount + " timer.repeatCount=" + timer.repeatCount);
|
||||
});
|
||||
timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(e) {
|
||||
trace("TimerEvent.TIMER_COMPLETE: timer.running=" + timer.running + " timer.currentCount=" + timer.currentCount + " timer.repeatCount=" + timer.repeatCount);
|
||||
})
|
||||
timer.start();
|
||||
|
||||
setTimeout(function() {
|
||||
trace("After 300ms: timer.running=" + timer.running + " timer.currentCount=" + timer.currentCount + " timer.repeatCount=" + timer.repeatCount);
|
||||
trace("Starting timer again");
|
||||
timer.start();
|
||||
|
||||
setTimeout(function() {
|
||||
trace("After 200ms: timer.running=" + timer.running + " timer.currentCount=" + timer.currentCount + " timer.repeatCount=" + timer.repeatCount);
|
||||
trace("Stopping/Starting timer again");
|
||||
timer.stop();
|
||||
timer.start();
|
||||
}, 200);
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
TimerEvent.TIMER: timer.running=true timer.currentCount=1 timer.repeatCount=2
|
||||
TimerEvent.TIMER: timer.running=true timer.currentCount=2 timer.repeatCount=2
|
||||
TimerEvent.TIMER_COMPLETE: timer.running=false timer.currentCount=2 timer.repeatCount=2
|
||||
After 300ms: timer.running=false timer.currentCount=2 timer.repeatCount=2
|
||||
Starting timer again
|
||||
TimerEvent.TIMER: timer.running=true timer.currentCount=3 timer.repeatCount=2
|
||||
TimerEvent.TIMER_COMPLETE: timer.running=false timer.currentCount=3 timer.repeatCount=2
|
||||
After 200ms: timer.running=false timer.currentCount=3 timer.repeatCount=2
|
||||
Stopping/Starting timer again
|
||||
TimerEvent.TIMER: timer.running=true timer.currentCount=4 timer.repeatCount=2
|
||||
TimerEvent.TIMER_COMPLETE: timer.running=false timer.currentCount=4 timer.repeatCount=2
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
num_frames = 16
|
Loading…
Reference in New Issue