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/7/28 2:32:36 阅读更多 →
如何让数字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/7/28 2:32:35 阅读更多 →
视觉SLAM核心技术实战:从稀疏特征到稠密建图的完整工程方案

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

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

2026/7/28 2:31:35 阅读更多 →

最新新闻

嵌入式音频开发实战:I2S协议详解与STM32驱动设计

嵌入式音频开发实战:I2S协议详解与STM32驱动设计

1. 项目概述:从“听个响”到专业音频的桥梁刚接触嵌入式开发,尤其是涉及到音频播放或录音功能时,很多朋友会卡在第一步:怎么让我的开发板“说话”或者“听声”?你可能试过用普通的GPIO口模拟PWM来驱动蜂鸣器&#xff0…

2026/7/28 2:49:41 阅读更多 →
图形化编程与开源硬件:Mind+与PinPong库的协同开发实践

图形化编程与开源硬件:Mind+与PinPong库的协同开发实践

1. 项目概述:当图形化编程遇上开源硬件 如果你是一位对Arduino、micro:bit这类开源硬件感兴趣的创客或教育者,但又对传统的代码编程(比如C、Python)感到头疼,那么“用Mind玩转PinPong库”这个组合,可能就是…

2026/7/28 2:49:41 阅读更多 →
自适应控制算法在多智能体编队中的应用与Matlab实现

自适应控制算法在多智能体编队中的应用与Matlab实现

1. 项目概述这个仿真项目实现了一种基于自适应控制的多智能体系统编队控制算法,特别针对有向拓扑网络下的时变编队场景。我在实际工程中多次遇到这类需求——当无人机集群需要动态变换队形穿越复杂环境时,传统的固定编队控制往往难以应对突发扰动。而自适…

2026/7/28 2:49:41 阅读更多 →
给 AI 程序员开「外挂」?这个仓库装了 63 个

给 AI 程序员开「外挂」?这个仓库装了 63 个

给 AI 程序员开「外挂」?这个仓库装了 63 个 如果你是一名 AI 程序员,肯定经常遇到这样的场景:想快速调个 API,却要翻半天文档;想做个数据增强,结果得从零写一堆代码;想评估模型效果&#xff0c…

2026/7/28 2:49:41 阅读更多 →
FastAPI+JWT+OAuth2.0 权限体系:实现多级角色校验与请求防篡改

FastAPI+JWT+OAuth2.0 权限体系:实现多级角色校验与请求防篡改

很多开发小伙伴在用 FastAPI 开发后台管理、业务接口时,鉴权实现都比较简陋:仅仅简单校验 Token 是否存在,完全没有角色分级控制,更没有考虑请求参数篡改、接口越权访问等安全风险。上线之后很容易出现普通用户访问管理员接口、前…

2026/7/28 2:49:41 阅读更多 →
用Micro:bit与纸板制作红外感应击掌机器人:从传感器原理到动手实践

用Micro:bit与纸板制作红外感应击掌机器人:从传感器原理到动手实践

1. 项目概述:当纸板遇上代码,一个“击掌”机器人的诞生如果你手头有一块Micro:bit,又恰好攒了几个快递纸箱,别急着扔掉。今天我想分享的,就是如何用这些看似普通的材料,制作一个能和你“击掌”的互动机器人…

2026/7/28 2:48:41 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/27 6:31:56 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻