Welcome Guest ( Log In | Register )

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


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

Group: Avatar
Posts: 1107
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 游戏。[上个月](https://trow.cc/board/showtopic=48641) 以来实现了大部分基本功能,发布了第一个试玩版 [0.0.1](https://github.com/Bozar/AxeMan/releases)。

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

图 1:演示动画,十月。

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

图 2:演示动画,八月。

十月份没有太大进展。月初通关了泰坦佛和大表哥,月末开始玩辐射三:天外世界(我的第三个人物,Jack Cooper,离开翡翠谷仅仅用了十七个小时)。这次谈两个话题,时间系统和读取 XML 文件系统,翻译自以下两篇文章:

* [A Turn-Based Scheduling System](https://github.com/Bozar/DevBlog/wiki/Program_SchedulingSystem)
* [How To Load Data From XML Files](https://github.com/Bozar/DevBlog/wiki/Program_LoadDataFromXML)

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

图 3:鬼灭左轮:黑水镇的亚瑟·摩根。

## 时间系统

如果把时间系统看作一个数据容器,它应当具备四个功能:

* 把游戏对象添加进容器,并按照指定顺序排列它们。
* 从容器中移除指定对象。
* 获取“指针”当前指向的对象。
* 让“指针”指向下一个对象。

此外,还有两个与数据容器密切相关的操作:

* 让其它游戏组件移动“指针”。
* 当“指针”移动时,提醒其它游戏组件。

那么首先,我们来看一下数据容器。[Schedule](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/Schedule.cs) 实现了 `ISchedule`,使用 `private List<GameObject> schedule` 存储游戏对象。

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

图 4:ISchedule。

实现 `ISchedule.GotoNext()` 和 `ISchedule.Remove()` 的时候,避免引用空对象。

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

图 5:Schedule。

我们使用 [TurnManager](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/TurnManager.cs) 移动数据容器“指针”。`TurnManager` 实现了接口 `ITurnManager`。

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

图 6:ITurnManager。

`StartTurn()` 和 `EndTurn()` 将发布多个事件通知其它游戏组件:某个游戏对象的回合开始或结束了,`NextActor()` 封装了多个公开方法:

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

图 7:NextActor()。

`TurnManager` 还订阅了事件 `CheckingSchedule`,隐式地调用 `NextActor()`。

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

图 8:CheckingSchedule。

游戏开始的时候,我们手动调用一次 `TurnManager.StartTurn()`。接下来,只要每个游戏对象在合适时机发布 `CheckingSchedule` 事件,时间系统就能自动运转起来了。

## 读取 XML 文件

我先前写过存储和读取游戏数据的[文章](https://trow.cc/board/showtopic=48445),这次做了少许改进,让同一套代码适用于不同结构的 XML 文件。如果我们把读取系统看作一个黑盒子,它需要接受文件路径和数据标签,输出特定类型的数据。我们不妨把这套系统拆解成两个组件:

* XML 文件 --> [读取文件] --> XElement
* XElement,数据标签 --> [读取特定的 XElement] --> 游戏数据

第一个组件 [SaveLoadXML](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/SaveLoadXML.cs) 封装了 `XElement.Load()`。

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

图 9:SaveLoadXML。

读取 `XElement` 的组件比较有趣。理想情况下,我们可以设计这样一个接口:

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

图 10:IGameData。

但是实际游戏中有两个问题。第一,数据标签的类型不止一个。第二,XML 文件的结构同样不止一种。

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

图 11:XML 文件。

为此,我们针对每种 XML 文件设计专门的接口。这些接口拥有类似的名字,比如 `ISettingData` 和 `IActorData`。它们的公用方法名字相同,比如 `GetIntData()` 和 `GetStringData()`,但是输入的参数不同。

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

图 12:读取 XElement 的接口。

[ActorData](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/ActorData.cs) 和 [SettingData](https://github.com/Bozar/AxeMan/blob/master/Assets/Scripts/SettingData.cs) 实现了上述两个接口。它们都有一个类似这样的私有方法:`bool TryGetData(DataTag dataTag, out XElement xElement)`。以 `SettingData` 为例,具体代码如下。

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

图 13:SettingData。

从外部看,我们调用 `SettingData.GetBoolData()` 或者 `ActorData.GetStringData()`的时候,只要输入特定的数据标签,就能得到需要的数据,不用考虑数据来自哪一份文件。


TOP
Fast ReplyReply to this topicStart new topic
 


Time is now: 2019-11-18, 01:52