HUD 组件:血条、能量、分数、波次显示

举报
yd_296221794 发表于 2026/10/04 09:55:52 2026/10/04
【摘要】 > 109 行代码,把"状态"变成了"视觉信息"。## 组件概览`HUD` 是 NEON RUNNER 2077 里最"务实"的 UI 组件。它不搞花哨的故障效果,不做扫描线动画——它只做一件事:**把游戏状态实时显示在屏幕上**。```ts// src/ui/HUD.tsexport class HUD {  private healthBar: Phaser.GameObjects.Re...

> 109 行代码,把"状态"变成了"视觉信息"。


## 组件概览


`HUD` 是 NEON RUNNER 2077 里最"务实"的 UI 组件。它不搞花哨的故障效果,不做扫描线动画——它只做一件事:**把游戏状态实时显示在屏幕上**。


```ts

// src/ui/HUD.ts

export class HUD {

  private healthBar: Phaser.GameObjects.Rectangle;

  private healthBg: Phaser.GameObjects.Rectangle;

  private energyBar: Phaser.GameObjects.Rectangle;

  private energyBg: Phaser.GameObjects.Rectangle;

  private scoreText: Phaser.GameObjects.Text;

  private waveText: Phaser.GameObjects.Text;

  private healthLabel: Phaser.GameObjects.Text;

  private energyLabel: Phaser.GameObjects.Text;

```


## 布局:左上 + 右上


HUD 的布局非常对称:


- **左上角**:HP(血条)+ EN(能量条)

- **右上角**:SCORE(分数)+ WAVE(波次)


```ts

// 左上:HP

this.healthLabel = scene.add.text(40, 28, 'HP', {

  fontFamily: FONTS.MONO, fontSize: '16px', color: '#00ff9d',

}).setDepth(100);


this.healthBg = scene.add.rectangle(80, 32, 220, 14, COLORS.DARK_LINE, 0.9)

  .setOrigin(0, 0.5).setDepth(100).setStrokeStyle(1, COLORS.NEON_GREEN, 0.8);


this.healthBar = scene.add.rectangle(80, 32, 220, 14, COLORS.NEON_GREEN, 1)

  .setOrigin(0, 0.5).setDepth(101);

```


注意 `healthBg` 和 `healthBar` 的位置完全重合,但 `healthBar` 的 `setDepth(101)` 比 `healthBg` 的 `setDepth(100)` 高一层——所以血条会覆盖在背景条之上。


## 血条:颜色随血量变化


```ts

setHealth(ratio: number): void {

  const clamped = Phaser.Math.Clamp(ratio, 0, 1);

  this.healthBar.width = 220 * clamped;

  const color = clamped > 0.5

    ? COLORS.NEON_GREEN

    : clamped > 0.25

      ? COLORS.NEON_ORANGE

      : COLORS.NEON_MAGENTA;

  this.healthBar.fillColor = color;

}

```


这是 HUD 里最有"信息量"的方法。血量变化时,不仅条的长度变化,**颜色也变化**:


- > 50%:绿色(安全)

- 25%-50%:橙色(警告)

- < 25%:品红(危险)


这个颜色变化是**无文字的状态提示**——玩家不需要看数字,一眼就知道自己还剩多少血。


## 能量条:只有长度变化


```ts

setEnergy(ratio: number): void {

  const clamped = Phaser.Math.Clamp(ratio, 0, 1);

  this.energyBar.width = 220 * clamped;

}

```


能量条比血条简单——只有长度变化,没有颜色变化。因为能量是"可恢复的"(`GameScene` 里每 1500ms 增加 0.04),不需要"警告"语义。


## 分数:六位零填充


```ts

setScore(score: number): void {

  this.scoreText.setText(`SCORE ${String(score).padStart(6, '0')}`);

}

```


`String(score).padStart(6, '0')` 把分数格式化为 6 位数字,不足的前面补零。`SCORE 000000` → `SCORE 000123` → `SCORE 004567`。


这个"零填充"不是为了好看,而是**防止文字宽度抖动**。如果不用 `padStart`,`SCORE 123` 和 `SCORE 12345` 的宽度不同,会导致 `scoreText` 的 `setOrigin(1, 0)`(右对齐)位置偏移。


## 波次:两位零填充


```ts

setWave(wave: number): void {

  this.waveText.setText(`WAVE ${String(wave).padStart(2, '0')}`);

}

```


同理,`WAVE 01`、`WAVE 02`、`WAVE 10`——两位数保证宽度一致。


## 销毁:清理所有对象


```ts

destroy(): void {

  [

    this.healthBar, this.healthBg, this.energyBar, this.energyBg,

    this.scoreText, this.waveText, this.healthLabel, this.energyLabel,

  ].forEach((obj) => obj.destroy());

}

```


`GameScene` 的 `shutdown()` 里调用 `this.hud?.destroy()`。这个销毁是必要的——如果玩家从 `GameScene` 切回 `MenuScene` 再切回来,HUD 会被重新创建,如果不销毁旧的,屏幕上会有两套 HUD。


## 在 GameScene 中的初始化


```ts

this.hud = new HUD(this);

this.hud.setHealth(this.health);

this.hud.setEnergy(this.energy);

this.hud.setScore(this.score);

this.hud.setWave(this.wave);

```


HUD 在 `GameScene` 的 `create()` 里初始化,然后立即用当前状态(health=1, energy=0, score=0, wave=1)填充。


## 下一章预告


HUD 讲完了,但 NEON RUNNER 2077 的视觉风格真正爆发的地方是 `GameScene` 的 arena 背景。那个紫色网格 + 青色边框的背景是怎么画的?下一章我会拆解这个 122 行的场景。


> HUD 设计的核心原则:**信息密度 > 视觉花哨**。HUD 是"工具",不是"装饰"。玩家在战斗中不会去欣赏 HUD,只会用它读状态。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。