游戏里的画面并不是战斗本身

人和 AI 一起做游戏 · 第 4 篇

游戏里的画面并不是战斗本身:《人和 AI 一起做游戏》第 4 篇,背景为 Kibble Street TD 文中开发阶段的真实战斗画面。

本篇依据截至 2026 年 8 月 1 日的开发记录,回顾 2026 年 6—7 月的战斗表现实现;画面、HUD 与刷新方式对应当时版本。

第 3 篇里,我们讨论了第一场战斗如何从规则运行到胜负。这一篇继续追踪下一次交接:规则怎样成为玩家看到的画面、操作和反馈。

暂停《Kibble Street TD》的战斗画面,可以看到角色、建筑、血条、伤害数字、单位卡片和能量槽。它们共同构成了玩家对“正在战斗”的全部感受,但没有任何一张图片真正决定谁受到伤害,也没有任何一个按钮可以直接创造单位。

战斗本身运行在另一层:时间走到了哪里,玩家还剩多少能量,单位位于什么位置,当前目标是谁,攻击是否命中,建筑还有多少生命,以及胜负是否已经出现。画面只是把这些状态翻译成玩家能够理解的形状、动作和声音。

这一区分不是为了使用更复杂的术语,而是为了避免一个常见问题:如果规则和画面彼此代替对方做决定,任何动画、界面或帧率变化都可能意外改变战斗结果。

同一个战斗时刻,实际有四个层次

本文记录阶段的《Kibble Street TD》的一帧战斗,可以拆成四个连续但职责不同的层次。

同一战斗时刻的四个层次
同一战斗时刻的四个层次

第一层是规则计算。它推进能量、位置、目标、攻击、伤害和胜负,是战斗事实的唯一来源。

第二层是一份“当前战况清单”,把此刻的时间、单位、建筑、飞行物、命中事件和结果整理出来。

第三层是场景表现。它根据清单创建或移除角色,摆放建筑,选择动画,绘制飞行物、命中特效和伤害数字。

第四层是操作与反馈:HUD 展示生命、时间、能量和冷却,按钮把玩家意图送回规则层,音效和镜头震动则让结果更容易被感知。

四层共同工作,玩家才会看到一场完整战斗。但它们并不拥有同一种权力:规则决定发生了什么,表现决定玩家怎样看见它,操作层只能提出请求。

点击单位卡,并不会直接把角色放进场景

召唤是最容易看清这条边界的操作。玩家点击一张单位卡时,界面先读取当前能量、冷却和可用状态。如果还在冷却,点击不会继续;如果只是能量不足,成本数字会给出抖动反馈;只有条件满足时,界面才向战斗系统发出召唤请求。

一次召唤怎样从按钮回到画面
一次召唤怎样从按钮回到画面

请求进入规则层后还会再次检查:战斗是否已经开始,是否已经结束,这个单位是否在当前编队中,能量是否足够,冷却是否完成。全部通过后,系统才创建单位状态、扣除能量并写入下一次可召唤时间。

随后,新的战况清单立即产生。战场看到新增的单位状态,创建对应角色并播放动作;HUD 看到能量和冷却变化,更新卡片与能量槽;控制层确认召唤成功后,播放召唤音效。

这个往返说明了一条重要原则:按钮是请求入口,不是规则裁判。 界面提前检查,是为了让反馈更及时;规则层再次检查,是为了保证无论请求从哪里进入,结果都遵守同一套条件。

“当前战况清单”是规则和画面的合同

在《Kibble Street TD》中,这份清单包含时间、玩家能量、双方单位、建筑、伤害事件、飞行物、命中特效、预警、宝箱和胜负结果。画面不需要重新推测谁活着、谁正在攻击,也不需要自己计算伤害。

一份战况清单同时驱动画面、HUD 和反馈
一份战况清单同时驱动画面、HUD 和反馈

战场表现从中读取单位和建筑,HUD 从中读取时间、生命和能量,音频观察其中的战斗事件,结算流程等待唯一的胜负结果。它们看到的是同一个战斗时刻,因此不会各自维护一套互相矛盾的答案。

这也允许不同部分按不同节奏刷新。本文记录阶段的战场画面以接近每秒 30 次的节奏接收状态,HUD 以较低频率刷新,并在能量整数、建筑生命或结果等关键信息变化时立即更新。能量和生命仍由规则连续推进,只是没有必要让每一段文字都在每一帧重新计算布局。

对开发来说,这份清单还是排查问题的分界线。如果清单里的生命值已经错误,问题在规则侧;如果清单正确而血条显示错误,问题在表现侧。两类问题不再混在一起猜测。

动画是状态的翻译,不是状态本身

一个单位向前移动时,画面选择奔跑动画;进入攻击状态时,切换攻击动画;生命进入死亡阶段时,播放死亡动作;战斗结束后的存活单位则可以进入胜利表现。

单位状态怎样被翻译成动画与反馈
单位状态怎样被翻译成动画与反馈

但“正在攻击”可能持续多个攻击周期,只看这个状态并不足以判断何时重新播放动作。因此系统还会记录每一次新攻击的变化标记。标记更新时,表现层才从头播放一次攻击动画,避免角色停在攻击状态时不断错误重启。

受击反馈采用类似方式。伤害发生后会产生带唯一编号的事件,画面据此播放闪白、回弹、数字或震动,并记录哪些事件已经显示过。这样,即使同一份短期状态被读取多次,同一次伤害也不会重复弹出多组数字。

动画可以更换,播放速度可以调整,角色图也可以重做;只要状态含义和交接格式不变,这些修改就不应该改变战斗结果。

反馈比规则丰富,但不能改写规则

本文记录阶段的画面中,一次命中,玩家可能同时看到生命减少、伤害数字、抓痕或爆炸、角色回弹和镜头震动,并听到对应音效。它们都在表达同一件已经发生的事。

一次伤害由规则结果扩展成多层反馈
一次伤害由规则结果扩展成多层反馈

其中,伤害数值和命中时间属于规则结果;数字样式、闪光强度、震动幅度和音效属于表现选择。重型攻击可以使用更明显的震动,普通攻击可以更克制,但表现层不能因为某个特效播放较慢就自行再扣一次生命。

两层分开后,也能更准确地描述质量问题。生命已经正确减少但没有声音和受击动作,是反馈缺失;数字出现两次但生命只减少一次,是事件重复显示;飞行物还没到达目标就提前扣血,则是规则时机与视觉时机没有对齐。这些现象看起来相似,根因却完全不同。

HUD 是仪表盘,不是另一套战斗系统

战斗顶部显示双方基地和防御塔生命、关卡、时间、宝箱与控制按钮;底部显示道具、四类单位、成本、冷却和能量。它们信息很多,但都应当来自已有战况,而不是在界面内部保存另一份“真实数据”。

HUD 读取状态,并把操作送回规则层
HUD 读取状态,并把操作送回规则层

例如,单位卡是否可召唤由规则计算出的命令状态决定。战前准备、引导、暂停或结算期间,控制层可以统一锁定交互;这只是阻止玩家继续发出请求,不会偷偷修改能量或单位状态。

随着表现内容增加,《Kibble Street TD》也调整过组织方式。早期战场渲染集中在一个场景模块,HUD 也承担了大量布局和交互。后来它们分别拆成背景、建筑、单位、特效、机制、掉落,以及顶栏、命令区、战前准备和结算等部分。这个变化没有重写战斗规则,只是让每种表现对自己的职责负责。

这个环节由谁负责

人负责决定玩家需要看见什么:哪种变化必须立即反馈,哪些信息应该留在 HUD,攻击、受伤和胜负需要怎样的节奏,以及画面是否准确表达了规则。

AI 负责检查完整链路,把状态与表现逐项对应,完成事件映射和重复验证,并在出现异常时判断问题位于输入、规则、交接还是显示环节。

引擎负责稳定地绘制节点、动画和界面,但它不会替开发者定义什么才是正确的战斗结果。

如果准备建立自己的表现层

先确定一份唯一的战斗状态,再让所有界面只读取它;把按钮定义为请求,不让它直接修改角色或资源;为移动、攻击、死亡和胜负建立清晰的表现映射;为一次性反馈提供可识别的事件;最后分别验证规则结果和玩家看到的结果。

这套结构在原型阶段看起来多了一次交接,有助于减少后续动画、UI 和机制增加时的相互干扰。