在这里插入图片描述

网罗开发 (小红书、快手、视频号同名)

  大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。


引言

当项目从 Demo 变成“稍微像个游戏”的时候:

文件开始变多
逻辑开始混乱
状态开始失控

今天我们主要讲:

把一个“完整但简单”的鸿蒙小游戏,彻底拆开讲清楚

目标是让你真正理解:

一个 ArkUI 游戏项目,到底应该怎么组织

一、我们要实现什么?

游戏目标:简单战斗点击游戏

规则:

点击攻击 → 敌人掉血
敌人自动攻击 → 玩家掉血
血量为 0 → 游戏结束

核心元素:

玩家 HP
敌人 HP
攻击行为
游戏状态(进行中 / 结束)

二、最终结构

我们先看“正确结构”,再逐层拆:

/game
 ├── store/
 │    └── GameStore.ts
 ├── system/
 │    └── BattleSystem.ts
 ├── ui/
 │    └── GamePage.ets
 └── main.ets

核心思想:

状态(store)
逻辑(system)
UI(ui)
入口(main)

这四层,缺一不可。

三、第一层:状态层

为什么必须有 Store?

如果你把所有状态写在 UI 里:

@State hp
@State enemyHp

结果就是:

页面 = 状态中心 = 逻辑中心

直接爆炸。

正确写法

// store/GameStore.ts
export class GameStore {
  playerHp: number = 100
  enemyHp: number = 100
  isGameOver: boolean = false

  attackEnemy() {
    if (this.isGameOver) return

    this.enemyHp -= 10

    if (this.enemyHp <= 0) {
      this.enemyHp = 0
      this.isGameOver = true
    }
  }

  takeDamage() {
    if (this.isGameOver) return

    this.playerHp -= 5

    if (this.playerHp <= 0) {
      this.playerHp = 0
      this.isGameOver = true
    }
  }

  reset() {
    this.playerHp = 100
    this.enemyHp = 100
    this.isGameOver = false
  }
}

export const store = new GameStore()

这一层解决什么问题?

状态集中
逻辑内聚
可复用
可跨设备(未来)

一句话总结:

Store = 游戏的“唯一真实世界”

四、第二层:系统层

很多人会问:

Store 已经有逻辑了,为什么还要 System?

因为:

Store → 状态 + 基本操作
System → 游戏规则 / 调度 / 循环

示例:战斗系统

// system/BattleSystem.ts
import { GameStore } from '../store/GameStore'

export class BattleSystem {

  start(store: GameStore) {
    setInterval(() => {
      this.update(store)
    }, 1000)
  }

  update(store: GameStore) {
    if (store.isGameOver) return

    store.takeDamage()
  }

}

这一层的意义

把“游戏运行机制”抽出来
避免 UI / Store 变复杂

你可以继续扩展:

AI 系统
掉落系统
关卡系统

五、第三层:UI 层

终于到 ArkUI 的核心了。

但注意一个原则:

UI 不写复杂逻辑,只做“状态展示 + 触发行为”

页面代码

// ui/GamePage.ets
import { store } from '../store/GameStore'

@Entry
@Component
struct GamePage {

  build() {
    Column() {

      Text(`玩家 HP: ${store.playerHp}`)
        .fontSize(20)

      Text(`敌人 HP: ${store.enemyHp}`)
        .fontSize(20)

      if (store.isGameOver) {
        Text("游戏结束")
          .fontSize(30)
      }

      Button("攻击")
        .onClick(() => {
          store.attackEnemy()
        })

      Button("重开")
        .onClick(() => {
          store.reset()
        })

    }
  }
}

关键理解

这里没有:

手动刷新 UI
render()
draw()

因为:

ArkUI 自动根据状态更新 UI

你只做一件事:

改状态

六、第四层:入口

// main.ets
import { BattleSystem } from './system/BattleSystem'
import { store } from './store/GameStore'

const battleSystem = new BattleSystem()
battleSystem.start(store)

这里做了什么?

启动游戏循环
连接 Store 和 System

七、完整运行流程

把整个链路串起来:

点击按钮
   ↓
store.attackEnemy()
   ↓
状态变化(enemyHp)
   ↓
ArkUI 自动刷新 UI

同时:

BattleSystem 定时执行
   ↓
store.takeDamage()
   ↓
状态变化(playerHp)
   ↓
UI 自动更新

八、这个结构解决了什么问题?

1、不会再“写乱”

因为:

UI ≠ 状态 ≠ 系统

2、可以扩展

你可以轻松加:

关卡系统
装备系统
技能系统

3、支持多端

因为:

状态在 Store
UI 可多份

天然支持:

手机 + TV 同步

九、常见错误对比

错误写法

@State hp
@State enemyHp

setInterval(...)
onClick(...)

问题:

页面膨胀
逻辑混乱
无法扩展

正确写法

Store → 状态
System → 规则
UI → 展示

十、你现在应该建立的“脑模型”

写鸿蒙游戏时,你脑子里应该是:

1、有一个“世界”(Store)
2、有一套“规则”(System)
3、有多个“观察者”(UI)

而不是:

我在写一个页面

总结

一个简单鸿蒙游戏的完整结构,本质是:

状态中心(Store)
+ 规则系统(System)
+ UI 渲染(ArkUI)

你真正写的不是:

一个页面

而是:

一个“可被 UI 渲染的状态系统”

结合前几篇的所有结论:

状态驱动
多端协同
无设备边界

最终统一成一句话:

鸿蒙游戏开发,本质是在构建一个“跨设备的状态系统 + UI 映射层”。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐