HarmonyOS应用开发实战:猫猫大作战-setInterval 定时器、100ms 物理周期、主循环与 ArkUI 帧的协同、暂停时短路返回
前言游戏和静态 UI 的本质区别是——UI 是事件驱动的用户点击才更新游戏是时间驱动的每帧更新物理无论用户是否交互。ArkUI 没有内置「游戏循环」需要开发者用setInterval自己搭主循环——每隔固定周期触发一次物理更新。本篇以「猫猫大作战」100ms 主循环为锚点把setInterval 定时器、100ms 物理周期、主循环与 ArkUI 帧的协同、暂停时短路返回四大要点讲透。提示本系列不讲 ArkTS 础语法与环境搭建假设你已跟完第 1–32 篇。本篇是阶段二第三篇。一、场景拆解游戏主循环回顾「猫猫大作战」主循环第 31 篇// 来源entry/src/main/ets/pages/Index.ets startGame() this.gameLoopTimer setInterval(() { if (this.gameState ! GameState.PLAYING) return; // ← 暂停时短路返回 this.cats this.gameEngine.updateCats(); // 物理更新 this.score this.gameEngine.getScore(); // 同步得分 this.combo this.gameEngine.getCombo(); // 同步连击 if (this.gameEngine.isGameOver()) { this.endGame(); } }, 100); // ← 100ms 周期核心问题为什么用setInterval而不是 ArkUI 的requestAnimationFrame为什么是 100ms改成 16ms60 FPS会怎样暂停时定时器还在跑怎么处理二、setInterval 定时器2.1 基本用法const timerId: number setInterval(() { console.info(每 100ms 触发一次); }, 100); // 停止 clearInterval(timerId);API 说明API作用setInterval(callback, delay)周期性触发回调返回 timer idclearInterval(timerId)停止定时器2.2 setInterval vs setTimeoutAPI触发适合setInterval(cb, 100)每 100ms 一次周期游戏主循环setTimeout(cb, 100)100ms 后一次单次倒计时、延迟动画实战经验主循环用 setInterval一次性延迟用 setTimeout。本系列第 35 篇会讲 spawnTimer也用 setInterval因为要周期生成猫咪。2.3 setInterval 的误差setInterval(callback, 100)的100ms是「最短间隔」不是「精确间隔」——如果回调执行耗 20ms下一帧间隔就是 120ms 而非 100ms。回调耗时实际周期误差1ms101ms1%20ms120ms20%100ms200ms100%关键经验回调内别做重计算——耗时超过周期会拖慢整个循环。本系列第 144 篇会专讲 TaskPool 并发把重计算丢到后台线程。三、100ms 物理周期的选择3.1 为什么是 100ms游戏主循环周期决定物理粒度——周期越短猫咪下落越平滑但 CPU 开销越大。周期帧率猫咪下落视觉CPU 开销适合16ms60 FPS极平滑高FPS 游戏33ms30 FPS平滑中ARPG100ms10 FPS格子跳跃本项目低消除/回合200ms5 FPS明显卡顿极低慢节奏策略本项目选 100ms 的原因消除类游戏节奏慢——猫咪每 100ms 下落一格玩家来得及反应。格子跳跃即原生视觉——猫咪本就是按格子摆放不需要 60 FPS 平滑过渡第 16 篇 position 动画做了 100ms 过渡补偿。CPU 开销低——10 FPS 更新引擎省电。3.2 改成 60 FPS 会怎样// 假设改成 16ms60 FPS this.gameLoopTimer setInterval(() { this.cats this.gameEngine.updateCats(); // 每 16ms 调一次 // ... }, 16);问题引擎按格子算物理——updateCats()每次cat.y 116ms 调一次 60 格/秒下落太快玩家看不清。CPU 浪费——引擎内部物理只支持「一格一格跳」60 FPS 调用 60 次但只产生 10 次实际位移50 次空跑。关键经验主循环周期要匹配物理粒度——格子游戏用 100ms连续物理用 16ms。3.3 position 动画补偿// 来源entry/src/main/ets/pages/Index.ets GameView() 猫咪层 ForEach(this.cats, (cat: Cat) { Column() { /* ... */ } .position({ x: ..., y: ... }) .animation({ duration: 100, curve: Curve.Linear }) // ← 100ms 动画 }, (cat: Cat) cat.id)协同机制主循环 100ms 改cat.y→ position 重新计算。.animation({ duration: 100 })让 position 从旧值平滑过渡到新值耗时 100ms。下一帧主循环再改cat.y→ 新的 100ms 动画开始。视觉上猫咪每 100ms 平滑下落一格而不是「瞬移」。关键经验主循环周期 position 动画时长——视觉最连贯。本系列第 55、56 篇会专讲 animateTo 与 animation 属性动画。四、暂停时短路返回4.1 短路守卫this.gameLoopTimer setInterval(() { if (this.gameState ! GameState.PLAYING) return; // ← 短路返回 this.cats this.gameEngine.updateCats(); this.score this.gameEngine.getScore(); this.combo this.gameEngine.getCombo(); if (this.gameEngine.isGameOver()) { this.endGame(); } }, 100);为什么不用 clearInterval 暂停方案优点缺点短路返回本项目续期无缝、代码简单定时器一直跑微量 CPUclearInterval 暂停CPU 零开销续期要重建定时器代码复杂实战经验短停暂停用短路返回长停结束用 clearInterval——暂停要能无缝续期结束要彻底清理。4.2 三种状态的短路行为gameState主循环行为spawnTimer 行为timeTimer 行为IDLE短路返回短路返回短路返回PLAYING正常执行正常执行正常执行PAUSED短路返回短路返回短路返回不计时间GAME_OVER短路返回短路返回短路返回关键经验所有定时器都先检查gameState PLAYING——暂停/结束时统一短路避免状态错乱。4.3 暂停后恢复pauseGame() { if (this.gameState GameState.PLAYING) { this.gameState GameState.PAUSED; } } resumeGame() { if (this.gameState GameState.PAUSED) { this.gameState GameState.PLAYING; } } **恢复流程** 1. resumeGame() 把 gameState 切回 PLAYING。 2. 下一个 100ms 主循环触发短路守卫通过**正常执行物理更新**。 3. **无需重建定时器**——定时器一直在跑只是暂停期被短路。 ## 五、完整主循环代码 ts // 来源entry/src/main/ets/pages/Index.ets Entry Component struct Index { State gameState: GameState GameState.IDLE; State score: number 0; State cats: Cat[] []; State combo: ComboInfo { count: 0, multiplier: 1, lastMergeTime: 0 }; State nextCatLevel: CatLevel CatLevel.SMALL; State highScore: number 0; State gameTime: number 0; private gameEngine: GameEngine new GameEngine(); private gameLoopTimer: number -1; private spawnTimer: number -1; private timeTimer: number -1; startGame() { this.clearTimers(); this.gameEngine.reset(); this.gameState GameState.PLAYING; this.score 0; this.cats []; this.gameTime 0; this.combo { count: 0, multiplier: 1, lastMergeTime: 0 }; this.nextCatLevel this.gameEngine.getNextCatLevel(); // 游戏主循环 - 100ms 更新物理本篇重点 this.gameLoopTimer setInterval(() { if (this.gameState ! GameState.PLAYING) return; // 短路守卫 this.cats this.gameEngine.updateCats(); // 物理更新 this.score this.gameEngine.getScore(); // 同步得分 this.combo this.gameEngine.getCombo(); // 同步连击 if (this.gameEngine.isGameOver()) { this.endGame(); } }, 100); // 自动生成猫咪第 35 篇专讲 this.spawnTimer setInterval(() { if (this.gameState ! GameState.PLAYING) return; if (this.gameEngine.getCatCount() GameConfig.MAX_CATS) { this.gameEngine.autoSpawnCat(); this.cats this.gameEngine.getAllCats(); this.nextCatLevel this.gameEngine.getNextCatLevel(); } }, GameConfig.SPAWN_RATE); // 计时器第 34 篇专讲 this.timeTimer setInterval(() { if (this.gameState GameState.PLAYING) { this.gameTime; } }, 1000); } pauseGame() { if (this.gameState GameState.PLAYING) { this.gameState GameState.PAUSED; } } resumeGame() { if (this.gameState GameState.PAUSED) { this.gameState GameState.PLAYING; } } endGame() { this.gameState GameState.GAME_OVER; this.maxCombo this.gameEngine.getMaxCombo(); this.mergeCount this.gameEngine.getMergeCount(); this.highestLevel this.gameEngine.getHighestLevel(); if (this.score this.highScore) { this.highScore this.score; } this.clearTimers(); } clearTimers() { if (this.gameLoopTimer ! -1) { clearInterval(this.gameLoopTimer); this.gameLoopTimer -1; } if (this.spawnTimer ! -1) { clearInterval(this.spawnTimer); this.spawnTimer -1; } if (this.timeTimer ! -1) { clearInterval(this.timeTimer); this.timeTimer -1; } } }六、踩坑提示6.1 忘记 clearTimers 导致定时器泄漏// ❌ 错误重新开始没清旧定时器 Button(重新开始).onClick(() { this.startGame(); // 旧的 gameLoopTimer 还在跑 }) // ✅ 正确startGame 内首行 clearTimers startGame() { this.clearTimers(); // 先清旧定时器 /* ... */ }后果不清旧定时器新游戏开始后有两套主循环并行——猫「闪现」两个循环都改 cats、得分「跳变」两个都改 score。6.2 timer id 用 string 而非 number// ❌ 错误setInterval 返回 number却声明 string private gameLoopTimer: string ; // ✅ 正确声明 number初始 -1 表示无定时器 private gameLoopTimer: number -1;6.3 暂停时 clearInterval 而非短路// ⚠️ 可以但繁琐暂停就 clearInterval恢复再 setInterval pauseGame() { clearInterval(this.gameLoopTimer); this.gameLoopTimer -1; } resumeGame() { this.gameLoopTimer setInterval(() { /* ... */ }, 100); // 要重建定时器 } // ✅ 推荐短路返回定时器一直在跑 pauseGame() { this.gameState GameState.PAUSED; // 主循环内 if 短路 } resumeGame() { this.gameState GameState.PLAYING; // 主循环自动续期 }6.4 回调内改 state 丢 this// ❌ 错误普通函数 this 不指向组件 setInterval(function () { this.cats this.gameEngine.updateCats(); // this 不是 Index }, 100); // ✅ 正确箭头函数保留外层 this setInterval(() { this.cats this.gameEngine.updateCats(); }, 100);本系列第 38 篇会专讲箭头函数 this 绑定。七、调试技巧console.info打周期主循环里 logDate.now()两次 log 差就是实际周期看误差。定时器泄漏排查DevEco Profiler 看 timer 数量正常游戏时 3 个重新开始后还是 3 个不是 6 个。暂停无效排查检查gameState是否真的切到PAUSED检查主循环短路守卫。猫闪现排查DevEco Profiler 看 timer 数量闪现说明有重复定时器。八、性能与最佳实践主循环周期匹配物理粒度——格子游戏 100ms连续物理 16ms。暂停用短路返回——比 clearInterval 重建更简洁无缝续期。结束用 clearInterval——彻底清理避免泄漏。startGame 首行 clearTimers——避免新旧定时器并行。回调内别做重计算——耗时超周期会拖慢循环重计算丢 TaskPool第 144 篇。回调用箭头函数保留 this——普通函数 this 不指向组件。总结本篇我们从 setInterval 主循环切入掌握了setInterval 定时器 API、100ms 物理周期的选择依据、主循环与 position 动画的协同、暂停时短路返回四大要点并给出了完整主循环代码。核心要点周期匹配物理粒度暂停短路不 clearIntervalstartGame 首行 clearTimers 防泄漏。下一篇我们将拆解计时器——秒级 gameTime 递增。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源「猫猫大作战」项目源码本仓库entry/src/main/ets/pages/Index.etssetInterval/clearInterval 官方文档HarmonyOS 定时器 API 参考ArkUI 动画与定时器协同最佳实践开源鸿蒙跨平台社区HarmonyOS 开发者官方文档首页系列索引本仓库articles/INDEX.md

相关新闻

魔兽争霸3终极兼容性修复工具:WarcraftHelper让你的经典游戏焕然新生

魔兽争霸3终极兼容性修复工具:WarcraftHelper让你的经典游戏焕然新生

魔兽争霸3终极兼容性修复工具:WarcraftHelper让你的经典游戏焕然新生 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为魔兽争霸3在现…

2026/10/3 21:16:41 阅读更多 →
如何让数字PDF拥有真实扫描质感:3分钟快速解决方案

如何让数字PDF拥有真实扫描质感:3分钟快速解决方案

如何让数字PDF拥有真实扫描质感:3分钟快速解决方案 【免费下载链接】lookscanned.io 📚 LookScanned.io - Make your PDFs look scanned 项目地址: https://gitcode.com/gh_mirrors/lo/lookscanned.io 你是否曾为数字生成的PDF文档太过"完美…

2026/10/16 7:29:40 阅读更多 →
视觉SLAM核心技术实战:从稀疏特征到稠密建图的完整工程方案

视觉SLAM核心技术实战:从稀疏特征到稠密建图的完整工程方案

视觉SLAM核心技术实战:从稀疏特征到稠密建图的完整工程方案 【免费下载链接】slambook2 edition 2 of the slambook 项目地址: https://gitcode.com/gh_mirrors/sl/slambook2 在自动驾驶、机器人导航和增强现实等前沿技术领域,如何让机器仅凭视觉…

2026/10/16 16:36:39 阅读更多 →

最新新闻

基于NLP的检索式聊天机器人实战:语义相似度与向量化实现

基于NLP的检索式聊天机器人实战:语义相似度与向量化实现

做了几年NLP应用开发,手里过过不少聊天机器人项目,但我发现最容易被低估、又在实际落地中最实用的,恰恰是检索式聊天机器人。很多人一上来就奔着生成式大模型去,觉得能自动组织语言才叫智能,结果卡在算力、幻觉和成本上…

2026/10/17 2:29:36 阅读更多 →
园区能源监测数据采集网关:核心功能、部署与选型实战指南

园区能源监测数据采集网关:核心功能、部署与选型实战指南

在智慧园区的能源管理项目里,数据采集网关是个特别容易被低估的角色。不少甲方和刚入行的工程师觉得它就是个“传数据的盒子”,把电表、水表、气表的数据送到服务器就完事了。但真正落地过园区能源监测系统的人心里都清楚,网关选得好不好、配…

2026/10/17 2:29:36 阅读更多 →
如何快速上手Qwen3.8-Flash-Next-Quark-MXFP4-PLEFP8:新手10分钟跑通首次推理的完全指南

如何快速上手Qwen3.8-Flash-Next-Quark-MXFP4-PLEFP8:新手10分钟跑通首次推理的完全指南

大模型模型量化模型优化多模态Qwen 【免费下载链接】Qwen3.8-Flash-Next-Quark-MXFP4-PLEFP8 项目地址: https://ai.gitcode.com/hf_mirrors/amd/Qwen3.8-Flash-Next-Quark-MXFP4-PLEFP8 点击查看 免费下载 Qwen3.8-Flash-Next-Quark-MXFP4-PLEFP8 是 AMD 面向 MI3…

2026/10/17 2:29:36 阅读更多 →
DBBackupPro 支持的数据库类型与版本清单

DBBackupPro 支持的数据库类型与版本清单

支持类型总览 真机实测记录 能力口径与注意事项DBBackupPro 项目组 | 2026 年 9 月 11 日 | 第十次更新版目录一、概述二、支持类型与版本总览三、真机实测记录四、能力口径与注意事项执行摘要DBBackupPro 当前版本共支持 8 类数据源(MySQL、MariaDB、SQL Server …

2026/10/17 2:29:36 阅读更多 →
WinPython 3.11.6.0dot 发布解读:64 位便携发行版的升级清单与 changelog 自动化生成机制

WinPython 3.11.6.0dot 发布解读:64 位便携发行版的升级清单与 changelog 自动化生成机制

开发工具构建工具CLI包管理器 【免费下载链接】winpython A free Python-distribution for Windows platform, including prebuilt packages for Scientific Python. 项目地址: https://gitcode.com/gh_mirrors/wi/winpython 点击查看 免费下载 导读 本文围绕 Win…

2026/10/17 2:29:36 阅读更多 →
sql-optimization-patterns - SKILL

sql-optimization-patterns - SKILL

name: sql-optimization-patterns description: “Transform slow database queries into lightning-fast operations through systematic optimization, proper indexing, and query plan analysis.” risk: safe source: community date_added: “2026-02-27” SQL 优化模式 …

2026/10/17 2:28:36 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →