You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AS3 TimerEvent延迟问题求助:调试器时间与真实时钟不同步

AS3国际象棋计时器延迟问题解决方案

问题根源

  1. Timer精度限制:AS3的Timer并非高精度计时工具,它的事件触发依赖Flash主线程的事件队列。如果主线程在处理渲染、其他脚本任务,Timer事件会被推迟执行,1000ms的间隔实际会产生偏差,累积后就会和真实时钟不同步。
  2. 错误计时逻辑:你用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();
}

关键修改点说明

  1. 添加初始时间戳记录:启动Timer时用new Date().getTime()记录当前毫秒数,作为计时起点。
  2. 基于时间差计算流逝时间:每次Timer触发时,用当前时间戳减去初始时间戳得到真实流逝毫秒数,再转换为总秒数,彻底摆脱Timer计数的误差。
  3. 修正时分秒计算逻辑:通过总秒数直接计算时、分、秒,无需重置Timer,保证计时连续准确。
  4. 简化补零逻辑:统一用字符串长度判断补零,代码更简洁。
  5. 移除不必要的Timer重置:不再需要在60秒时重置Timer,避免打断计时节奏。

这样修改后,即使Timer事件有延迟,显示的时间也会和真实时钟保持一致,因为每次都是基于系统时间计算的。

内容的提问来源于stack exchange,提问作者tatactic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:10:29