AS3 TimerEvent延迟问题求助:调试器时间与真实时钟不同步
AS3国际象棋计时器延迟问题解决方案
问题根源
- Timer精度限制:AS3的
Timer并非高精度计时工具,它的事件触发依赖Flash主线程的事件队列。如果主线程在处理渲染、其他脚本任务,Timer事件会被推迟执行,1000ms的间隔实际会产生偏差,累积后就会和真实时钟不同步。 - 错误计时逻辑:你用
timer.currentCount作为秒数依据,相当于把每次Timer的延迟都累积到计时里,偏差只会越来越大。另外currentCount>59时重置Timer的逻辑也不合理,会打断计时连续性。
修复方案
核心思路是基于系统真实时间戳计算流逝时间,而非依赖Timer的计数。具体步骤:
- 记录计时器启动时的初始时间戳(毫秒)
- 每次Timer触发时,用当前时间戳减去初始时间戳,得到真实流逝的毫秒数
- 将流逝毫秒数转换为时分秒,更新显示
修改后的完整代码
import flash.utils.Timer; import flash.events.TimerEvent; import flash.text.TextFormat; import flash.text.TextField; import flash.display.Stage; import flash.display.Sprite; import flash.display.Graphics; var container1:Sprite = new Sprite(); var container2:Sprite = new Sprite(); var margin1:uint = 20 var display1: TextField = new TextField(); var tFormat:TextFormat = new TextFormat(); // 保持1000ms间隔的Timer用于触发更新 var timer:Timer = new Timer(1000); // 记录初始时间戳(毫秒) var startTime:Number; var seconds:String; var minutes:String; var hours:String; dateInit(); display1Init(); timer.addEventListener(TimerEvent.TIMER, updateTimerDisplay); timer.start(); // 启动时记录初始时间 startTime = new Date().getTime(); function dateInit() { createContainer(container1); createContainer(container2) } function createContainer(aSprite:Sprite) { addChild(aSprite); } function display1Init() { container1.addChild(display1); drawContainer1(); drawContainer2(); display1.width = 140; display1.height = 80; display1.background = true; display1.x = container1.width/2+ margin1/2 - display1.width/2 ; display1.y = 100; tFormat.size = 26; tFormat.leftMargin = 35; tFormat.rightMargin = 35; tFormat.bold = true display1.border = true; // 初始显示00.00.00 display1.text=("\n00.00.00\n\n"); display1.setTextFormat(tFormat); } function drawContainer1():void { var g:Graphics = container1.graphics g.lineStyle(1,0x000000); g.beginFill(0x996666) g.drawRoundRect(margin1,margin1,(stage.stageWidth/2)-margin1*2,(stage.stageHeight)-margin1*2,30,30); g.endFill(); } function drawContainer2():void { var g:Graphics = container2.graphics g.lineStyle(1,0x000000); g.beginFill(0x996666) g.drawRoundRect(container1.width+margin1,margin1,container1.width,(stage.stageHeight)-margin1*2,30,30); g.endFill(); } function formatTime(totalSeconds:uint):void { // 计算时、分、秒 hours = String(Math.floor(totalSeconds / 3600)); minutes = String(Math.floor((totalSeconds % 3600) / 60)); seconds = String(totalSeconds % 60); // 补零处理 hours = hours.length < 2 ? "0" + hours : hours; minutes = minutes.length < 2 ? "0" + minutes : minutes; seconds = seconds.length < 2 ? "0" + seconds : seconds; } function updateTimerDisplay(e:TimerEvent):void { // 计算真实流逝的总秒数 var currentTime:Number = new Date().getTime(); var elapsedMs:Number = currentTime - startTime; var totalSeconds:uint = Math.floor(elapsedMs / 1000); formatTime(totalSeconds); display1.text=("\n" + hours + "." + minutes + "." + seconds + "\n\n"); display1.setTextFormat(tFormat); // 确保界面及时更新(一次即可) e.updateAfterEvent(); }
关键修改点说明
- 添加初始时间戳记录:启动Timer时用
new Date().getTime()记录当前毫秒数,作为计时起点。 - 基于时间差计算流逝时间:每次Timer触发时,用当前时间戳减去初始时间戳得到真实流逝毫秒数,再转换为总秒数,彻底摆脱Timer计数的误差。
- 修正时分秒计算逻辑:通过总秒数直接计算时、分、秒,无需重置Timer,保证计时连续准确。
- 简化补零逻辑:统一用字符串长度判断补零,代码更简洁。
- 移除不必要的Timer重置:不再需要在60秒时重置Timer,避免打断计时节奏。
这样修改后,即使Timer事件有延迟,显示的时间也会和真实时钟保持一致,因为每次都是基于系统时间计算的。
内容的提问来源于stack exchange,提问作者tatactic
相关产品推荐
相关产品推荐

