Welcome Guest ( Log In | Register )

欢迎访问本站。游客仅能浏览首页新闻、版块主题、维基条目与资源信息,需登录后方可获得内容发布、话题讨论、维基编辑与资源下载等权限。若无账号请先完成注册流程。
 
Reply to this topicStart new topic
> 《斧头人(Axe Man)》十二月开发日志
Bozar
2019-12-24, 12:59
Post #1


GEEKs will Eventually Evolve into Kryptonians. | All my jokes are cries for help.
Group Icon
 1249
   73

Group: Avatar
Posts: 1109
Joined: 2008-05-18
Member No.: 21346




QUOTE
让世界暂停⑨秒,给我看看计算姬的秘☆密。

## 游戏简介

《斧头人(Axe Man)》([Github 页面](https://github.com/Bozar/AxeMan),[英文博客](https://github.com/Bozar/DevBlog/wiki/Latest))是一款正在开发的单人回合制 Unity Roguelike 游戏,最新版本是 [0.0.2](https://github.com/Bozar/AxeMan/releases/tag/0.0.2)。[上个月](https://trow.cc/board/showtopic=48790) 以来改进了两个系统:游戏模式系统和输入系统,另外正在做 Nand2Tetris 的课后题。因为外观没有变化,所以本文继续沿用十一月的演示动画。

» Click to show Spoiler - click again to hide... «

图 1:演示动画,十一月。

## 学习 Nand2Tetris

The Elements of Computing Systems 这本计算机教材分为十二章,带领读者从最基础的逻辑门(Nand gate)开始,逐步搭建出能够运行俄罗斯方块(Tetris)的操作系统,所以又被称为 Nand2Tetris。列举几个相关的链接:

* [课程官网](https://www.nand2tetris.org/)
* [公开课视频](https://www.bilibili.com/video/av16778784)
* [我的习题解答](https://github.com/Bozar/Nand2Tetris)
* [学习论坛](http://nand2tetris-questions-and-answers-forum.32033.n3.nabble.com)

我建议先看一遍视频,然后读书、做笔记、写课后题。做笔记有两个目的。第一,梳理知识点之间的逻辑关系:包括不同章节的,以及每个章节内部各个节点的联系。第二,在笔记中写下关键词,要求几周后看到关键词时,依然能回忆起或者快速找到书中对应的内容。详见图 2。

» Click to show Spoiler - click again to hide... «

图 2:Nand2Tetris 读书笔记。

我已经做完前四章习题。ALU、PC(Program Counter)和写汇编做乘法有点麻烦,其余题目只要理解课本知识、读懂题意,做起来都挺简单的。最后特别感谢讲授公开课的两位老师:万磁王爷爷和胡子叔叔。他们讲得很认真、很清楚,耐心鼓励初学者迈出信仰之跃,像草薙素子那样潜入计算机之海,然后浮出水面,看见满天繁星。

» Click to show Spoiler - click again to hide... «

图 3:谢谢你,日式面包王。

## 游戏模式系统

本节翻译自这篇文章:[How To Add A GameModeManager To Your Game](https://github.com/Bozar/DevBlog/wiki/Program_GameMode),涉及到以下脚本:

* [GameModeManager.cs](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/GameModeManager.cs)
* [Canvas_Message.cs](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/Canvas_Message.cs)

一个游戏模式对映着一套特定的 UI 布局和按键绑定。比方说玩家打开物品栏进入 `InventoryMode` 之后,屏幕上显示一排物品名称,按 `下方向键` 高亮列表中的下一个物品。但是在 `NormalMode` 里,物品栏被隐藏了,只有地下城是可见的,按 `下方向键` 将移动玩家人物。`GameModeManager`帮助我们方便地切换 UI 和输入方式。

首先,我们使用 `enum` 类型的数据标签来定义游戏模式。比方说,`GameModeTag.NormalMode`,`GameModeTag.ExamineMode` 和 `GameModeTag.StartMode`。接下来我们定义接口 `IGameModeManager`:

» Click to show Spoiler - click again to hide... «

图 4:`GameModeManager`。

我们在 `GameModeManager` 内部设置 `CurrentGameMode` 的初始值。使用 `SwitchGameMode()` 发布两个事件(`SwitchingGameMode` 和 `SwitchedGameMode`)通知其它游戏组件,然后改变 `CurrentGameMode`。`SwitchGameModeEventArgs` 这个事件参数包括三个只读属性:`LeaveMode` 和 `EnterMode`是必需的属性,前者是当前游戏模式,后者是改动后的新模式;`CommandTag` 是可选的,有时候除了新旧游戏模式,我们还想知道模式改变时玩家按了什么键。

某个 UI 组件订阅了上述两个事件并修改自身状态。比方说,我们为了让 `Canvas_Message` 仅仅在 `NormalMode` 里在屏幕右下角显示最新的战斗日志,让它订阅了 `SwitchingGameMode`:

» Click to show Spoiler - click again to hide... «

图 5:订阅 `SwitchingGameMode` 事件。

如何根据游戏模式改变按键绑定?这个问题留到下一节讨论。

## 输入系统

本节翻译自这篇文章:[Redesign Input System In Unity](https://github.com/Bozar/DevBlog/wiki/Program_InputWithGameMode),涉及到以下脚本:

* [InputManager.cs](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/InputManager.cs)
* [MovementInput.cs](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/MovementInput.cs)
* [PCInputManager.cs](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/PCInputManager.cs)

输入系统监听玩家输入;把输入转化成 `enum` 类型的自定义命令,比如 `CommandTag.Confirm`,`CommandTag.Left` 或者 `CommandTag.SkillQ`;最后发布事件通知其它游戏组件。首先看一下输出部分。我们使用 `InputManager.Update()` 不断发布事件 `PlayerInputting`。

» Click to show Spoiler - click again to hide... «

图 6:发布命令。

现在还剩下三个问题。首先,怎样实现 `InputManager.ConvertInput()`?其次,如何让两个输入(比如 `左方向键` 和 `h`)输出同一个命令(`CommandTag.Left`)?最后,怎样让多个游戏模式回应同一个命令,怎样在某个游戏模式里禁用特定命令?比方说,如何使得 `CommandTag.Left` 在 `NormalMode` 和 `InventoryMode` 里都有效,但是只允许 `InventoryMode` 响应 `空格键`?

“输入-命令”转换系统包含两个部分:输入转换器和基于模式的输入管理器。转换器统一命名为 `XInput`,实现了接口 `IConvertInput`。每个转换器接受玩家输入,输出一组彼此关联的命令——`LogInput` 输出和浏览日志有关的命令,`MovementInput` 输出和移动方向有关的命令。在以下代码里,请注意多个输入被转化成同一个输出,由此解决了第二个问题。另外,`CommandTag.INVALID` 是所有转换器默认的输出命令。

» Click to show Spoiler - click again to hide... «

图 7:输入转换器。

基于模式的输入管理器统一命名为 `XInputManager`,实现了接口 `IInputManager`,负责按特定顺序组合多个转换器。

» Click to show Spoiler - click again to hide... «

图 8:输入管理器。

先来实现 `InputManager.ConvertInput()`。接下来,如果整个游戏中只用到一个输入管理器 `PCInputManager`,我们可以这样修改 `InputManager.Update()`。

» Click to show Spoiler - click again to hide... «

图 9:把输入转换成命令。

但实际情况是,我们在 `NormalMode` 里使用 `PCInputManager`,在 `AimMode` 里使用 `AimMarkerInputManager`。因此,我们给 `InputManager` 添加 `private Dictionary<GameModeTag, IInputManager> modeInputDict`,这个字典把游戏模式和输入管理器对应起来。`InputManager.Update()` 的最终版本如下。

» Click to show Spoiler - click again to hide... «

图 10:`InputManager.Update()`。

上述代码已经解决了前文的第三个问题,这里再解释一下。只要给 `NormalModeInputManager` 和 `InventoryModeInputManager` 添加 `MovementInput`,两个输入管理器都能响应方向键。另一方面,假如 `ConfirmInput` 能够把 `空格键` 转换成确认命令,并且 `NormalMode` 和 `NormalModeInputManager` 相关联,那么只要不给 `NormalModeInputManager` 添加 `ConfirmInput`,在 `NormalMode` 里按 `空格键` 是无效的。

最后留一道思考题。

» Click to show Spoiler - click again to hide... «

图 11:学姐:你说这个谁懂啊?!

* 凯瑞甘:什么是 `____`?
* 修格斯:什么是 `____`?
* 巴麻美:什么是 `____`?
* 初流乃:什么是 `____`?



This post has been edited by Bozar: 2019-12-24, 13:12
TOP
Fast ReplyReply to this topicStart new topic
 


Time is now: 2020-01-23, 06:18