在 如何设计一个背包的控制逻辑 中我们实现了背包的所有处理逻辑下面需要绑定 ui 了,ui 上逻辑就比较简单了,我们需要简单的做一个数据流程图去思考一下怎么实现数据的流转。
我选择将 ui 层分为 4 块功能:
- BagContainer 这个是需要被导出为自定义 node 的节点,用来标记 bag 显示在哪里,随后 bag 会自动显示在目标位置,并适配其宽高
- BagInnerContainer 处理具体的背包逻辑
- ItemSlot 用来实现显示 ItemSlot 的功能
- MouseSlot 用来显示被鼠标拿住的物品,这个阶段先不实现
注意 BagContainer 和 BagInnerContainer 本身没有较大的界限,我个人比较喜欢分开但是实际上,是实现在一起会更方便一点。
背包功能逻辑
然后我们就可以简单的画出上面这个图,对于整个 GUI 组件而言,对于 BagContainer 并不关心里面存放的内容,他只需要设定背包的大小(从 godot 编辑器里面拖拽),设定行、列,随后设置一个全局唯一的 BagName 即可。
BagInnerContainer 是一个活比较重的组件,他需要初始化 ItemSlot,设定宽高等等。
最后是 ItemSlot 他是一个核心组件,用于显示背包的数量和图标,当然未来还有拖拽事件,所以还需要绑定一些复杂的事件。
扩展实现 BagResourceManager
我们使用 单例 来实现,之前 我们也写过类似的方案:
扩展 BagItem
为了方便使用,我们在 BagItem 中扩展一个字段用来获取他对应的 resource 数据, 他还可以帮助我们获取目标的 Texture,可能算一种变异的 享元模式
实际上这可能并不是一个好的选择,因为当你可以获得 BagItem 的时候,你已经可以通过 Name 变相的从 BagResourceManager 中获取 Item 的元信息了,这样做可以完全的分离相互间的耦合性。
实现 ItemSlot
我们从下层逐渐向上实现是比较好的组织方式,首先 ItemSlot 的组织架构大致如下:
这里我只修改了CountLabel 的名字其余都一致样子大致是这样的,会有一个默认的 margin。
下面我需要编写对应的代码:
这样就完成 ItemSlot 的基本逻辑,下面要通过 BagInnerContainer 创建 ItemSlot
BagInnerContainer
BagInnerContainer 他的 UI 和代码逻辑都很简单的,具体的组件只有三个用来控制宽度的外层、滚动的 scroll container、还有 Grid:
我们只需要简单的 scroll container 设置为下面这样就可以了,这样当高度不够的时候他就会转换为滚动来显示 ui:
下面我们要开始编写代码部分:
我们需要对外暴露一个 InitBagGrid 的方法,并向内添加对应的格子这里实现上并不难做,初始化以后调用 AddItem 即可在内部已经实现了。
BagContainer
BagContainer 组件虽然逻辑复杂一点,但是组件上反而是更简单了,他只有用来标记大小的 ColorRect 组件。
随便拖拽一个大小即可。
下面是代码部分:
实验一下
下面我们简单的建一个背包实验一下:
效果还不错,下面需要实现拖拽系统。