在Godot中除Node外另一个重要的数据类型是Resource,我尝试着用它来创建不同种类的单位。
我们要在游戏中创建各种不同种类的战斗单位,甚至其数量可能在设计之初是不确定的。
使用数据驱动的设计方法,不用一个一个类写出来,一个类生成的对象载入不同类型的数据便可产出不同单位。优缺点:不需要衍生出几十上百个子类,不需要写代码来生成新的计划外的品种;数据容易定义,行为不容易。
此外,使用这种结构设计游戏单位,还可以方便的在运行中通过变形功能变成另外一种类型的单位!(希望不是变成尸体。。。)
数据资源的载体是一个unit_scene。
什么?一个游戏单位也是场景?官方教程介绍说这种把游戏里什么东西都弄成个scene的设计理念是godot的设计语言(design language),是以此为基石构筑起的godot引擎区别于其他引擎的特征,巴拉巴拉……没接触过几款引擎的我也不管那么多,用就是了。
首先是类声明:(使用C++或是GDScript应该都能做类似的事,我因为要移植一些旧代码就直接用C++了)
class unit_scene : public Node2D { GDCLASS(unit_scene, Node2D); public: class unit_type_res : public Resource { GDCLASS(unit_type_res, Resource); public: const unit_type& get_type() { return _type; } protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; unit_type _type; }; shared_ptr<unit_data>& get_data() { return _data; } protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; private: unit_scene() :_data(new unit_data) {} Ref<unit_type_res> _type; shared_ptr<unit_data> _data; }; struct unit_type { string name; string icon; }; struct unit_data { int32_t id = -1; const unit_type* type = nullptr; bool is_enemy = false; uint32_t curr_strength = 10; };
(这里_get()_set()_get_property_list()三个函数是向编辑器输出属性(上一篇日志介绍过)的另一种实现方式)
在改属性的函数里,可以不仅仅是修改属性值,还可以做一些其他关联操作,比如在变更strength数值时同时更新标签显示、将文字翻译成不同语言、变更单位类型时自动变换单位图标等等:
bool unit_scene::_set(const StringName &p_name, const Variant &p_value) { if( p_name == "curr_strength" ) { _data->curr_strength = p_value; static_cast<Label*>(get_node(NodePath("Strength")))->set_text(p_value); } else return false; return true; }
有了这些我们便可以在godot编辑器中新建、编辑、保存不同单位种类数据资源:
创建unit_scene(正如之前所说,不管以后有几种不同类型的单位,我猜只做这么一个scene应该就够用了):
使用时只需在关卡场景中实例化一个单位场景,然后选择一个类型:
“Godot编辑器本身就是一个Godot游戏”,这是官方介绍说的另一个Godot的设计理念。
目前看来可以直接用godot编辑器作为游戏编辑器编辑关卡和单位属性,似乎能省去自己写个游戏编辑器的麻烦。
不仅仅如此,GDScript提供了个“tool”关键字,可以在编辑器里直接运行脚本代码,并且能加个判断使代码只在编辑器里运行不影响游戏本身,简直方便到哭!
tool extends unit_scene func _process(delta): if Engine.editor_hint: position.x -= position.x as int % 96 # magic number position.x += 64 # magic number var y: int = position.y if (position.x as int / 96) & 1: # magic number y -= 56 # magic number position.y -= y as int % 112 # magic number position.y += 56 # magic number
如上述所示,给unit_scene附上这么一段GDScript的话,在编辑关卡时,可以拖动单位到任意位置,而最后都设置它的位置属性自动对齐到网格。
最终效果如图所示:
在接下来的日志里,大概会简单记录一下我用godot引擎制作以下这些方面内容的过程(实际上过了入门阶段后面就没太多东西了)
第四篇:单位行动控制指令
第五篇:实施行动的结果
第六篇:动作对周边的影响
第七篇:环境对动作和对象的影响
第八篇:目标与障碍
第九篇:突破障碍的技能
第十篇:从今往后
暂无关于此日志的评论。