文档删除弃用的部分, 准备更新文档

This commit is contained in:
小李xl 2023-09-06 15:34:28 +08:00
parent 3b9a538aed
commit e218eb4744
2 changed files with 12 additions and 199 deletions

View File

@ -1,6 +1,6 @@
---
### 2023-09-05
### 2023-09-06
经过两个月漫长的开发, 新版地牢编辑器初版已经开发完成, 目的为了更加方便开发者和玩家制作地图, 新版地牢编辑器提供功能如下:
* 地牢项目管理功能, 可以管理地牢组和房间, 支持房间预览, 支持显示异常房间, 房间支持配置权重
* 绘制Tile功能, 并且支持验证Tile是否绘制异常, 自动生成地牢导航网格

View File

@ -1,48 +1,9 @@
前言: 该文档仅针对`DungeonShooting_Godot`目录下的Godot工程
第一次编写日期: 2023-04-01
**注意:** 该文档版本比较老, 已经有很多接口和操作方式被更改但是为同步文档, 请谨慎阅读!
**注意:** 新版文档编写中...
目录:
<!-- TOC -->
* [1.启动项目](#1启动项目)
* [2.项目资源](#2项目资源)
* [2.1.目录结构](#21目录结构)
* [2.2.脚本获取资源](#22脚本获取资源)
* [2.3.重新生成ResourcePath](#23重新生成resourcepath)
* [3.游戏框架](#3游戏框架)
* [3.1.简述](#31简述)
* [3.2.游戏核心系统](#32游戏核心系统)
* [3.2.1.什么是ActivityObject](#321什么是activityobject)
* [3.2.2.什么是Activity模板场景](#322什么是activity模板场景)
* [3.2.3.如何创建ActivityObject](#323如何创建activityobject)
* [第一步, 创建模板场景:](#第一步-创建模板场景-)
* [第二步, 创建脚本:](#第二步-创建脚本-)
* [实例化ActivityObject](#实例化activityobject)
* [3.2.4.自定义RegisterActivity](#324自定义registeractivity)
* [3.2.5.ActivityObject常用功能](#325activityobject常用功能)
* [自定义组件](#自定义组件)
* [运动控制](#运动控制)
* [垂直方向运动](#垂直方向运动)
* [协程](#协程)
* [3.3.地牢](#33地牢)
* [3.3.1.地牢概述](#331地牢概述)
* [3.3.2.创建模板房间](#332创建模板房间)
* [创建模板房间](#创建模板房间)
* [绘制房间](#绘制房间)
* [配置房间门生成位置](#配置房间门生成位置)
* [ActivityMark标记](#activitymark标记)
* [扩展ActivityMark标记](#扩展activitymark标记)
* [3.4.UI系统](#34ui系统)
* [3.4.1.UI系统概述](#341ui系统概述)
* [3.4.2.UI代码生器](#342ui代码生器)
* [创建UI](#创建ui)
* [打开UI](#打开ui)
* [3.4.3.常用功能](#343常用功能)
* [生命周期](#生命周期)
* [包裹UI节点的IUiNode](#包裹ui节点的iuinode)
<!-- TOC -->
---
## 1.启动项目
@ -91,7 +52,8 @@ var resource = ResourceManager.Load<Theme>(ResourcePath.resource_theme_mainTheme
**游戏核心系统**: 以游戏玩法为中心的逻辑代码, 包括玩家, 敌人, 武器, 被动, 道具, 地牢生成, 房间规则, 存档逻辑等
**UI模块系统**: 用户操作界面的逻辑代码
**代码生成系统**: 自动生成便于开发的资源的逻辑代码, 包括生成UI模板, 生成地牢模板, 生成代码等
**代码生成系统**: 自动生成便于开发的资源的逻辑代码
**编辑器系统**: 用于用于自定义游戏内容
### 3.2.游戏核心系统
@ -116,77 +78,8 @@ var resource = ResourceManager.Load<Theme>(ResourcePath.resource_theme_mainTheme
通过下面这张图可以了解游戏中的物体与`ActivityObject`的关系 (注意: 该图为早期开发版本的继承关系图, 后面开发可能会有修改)
![](文档资源/2023-03-26_030144.png)
#### 3.2.2.什么是Activity模板场景
定义: `Activity模板场景`是指可以可以被实例化出`ActivityObject`对象的场景, 但是场景根节点必须是`ActivityObjectTemplate`节点
上面定义看起来有矛盾: `ActivityObjectTemplate`没有继承`ActivityObject`, 为啥以它为根节点的场景却能实例化出`ActivityObject`?
这就得提到一个概念: **场景与脚本分离**, 顾名思义, 场景中的节点与`ActivityObject`的脚本是完全分离的, 场景中的节点并没有挂载`ActivityObject`脚本, 在编辑器中它们是两互不干涉的.
游戏运行中, 如果需要实例化`ActivityObject`, 那么就先需要在`ActivityObject`脚本代码中指定该物体的模板场景, 实例化过程中游戏会先实例化出模板场景, 再用`ActivityObject`的实例顶替掉模板场景的根节点, 因此就能打到最终的效果.
为什么要这么做? 原因很简单, 因为我们的游戏是一个Roguelite游戏, 因此游戏中肯定会有大量的武器道具和敌人来填充内容, 但是总会有类似功能或者类似场景结构的物体, 这样就没有必要每一个物体都新建一个单独的场景, 而是让功能让这些类似功能或者结构的物体使用同一个场景, 但为了因对有不同行为逻辑的物体, 我们就设计了一套**场景与脚本分离**的设计模式来因对上述情况
总结: `Activity模板场景`是不挂载逻辑脚本的, 但是`ActivityObject`必须包含使用的模板场景, 并由统一的Api来实例化`ActivityObject`对象, 至于`ActivityObject`如何绑定模板场景, 请看: 3.2.3.如何创建一个`ActivityObject`
通过下面这张图可以更好的立即`Activity模板场景`和`ActivityObject`的关系
(缺张图...)
#### 3.2.3.如何创建ActivityObject
这里的创建分为两步:
##### 第一步, 创建模板场景:
创建一个空场景, 并且添加`ActivityObjectTemplate`节点
![](文档资源/image_4.png)
创建完成后编辑器会自动创建必要的子节点
![](文档资源/image_5.png)
此时就可以随意添加子节点和重命名更节点了, 最后记得保存到`./prefab`文件夹下
**注意**: `ShadowSprite`,`AnimatedSprite`,`Collision`这三个节点不能改名, 但是可以修改属性和添加子节点
##### 第二步, 创建脚本:
创建脚本放到在`./src/game`下, 脚本必须继直接或间接承`ActivityObject`, 并且需要在类上加`[RegisterActivity(id, path)]`标记用于注册对象, `物体id`必须唯一
源代码: [RegisterActivity.cs](../DungeonShooting_Godot/src/framework/activity/RegisterActivity.cs)
参考代码如下:
```csharp
using Godot;
[RegisterActivity("物体唯一Id", "模板场景路径")]
public partial class YourActivity : ActivityObject
{
}
```
为了方便区分物体类型, 可以使用`ActivityIdPrefix`类中的常量来添加`id`前缀, 目前支持的类型如下:
* **Role**: 角色
* **Enemy**: 敌人
* **Weapon**: 武器
* **Bullet**: 子弹
* **Shell**: 弹壳
* **Other**: 其他类型, 例如门, 箱子等
* **Test**: 测试物体
例如我们创建一个敌人, 那么`[RegisterActivity()]`就可以这么写:
```csharp
[RegisterActivity(ActivityIdPrefix.Enemy + "0001", ResourcePath.prefab_role_Enemy_tscn)]
```
##### 实例化ActivityObject
可通过`ActivityObject.Create(id)`创建物体, 这个`id`可以结合`ActivityIdPrefix`, 那么创建敌人最终可以这样写
```csharp
var enemy = ActivityObject.Create<Enemy>(ActivityIdPrefix.Enemy + "0001");
```
#### 3.2.4.自定义RegisterActivity
某些情况下需要更改`RegisterActivity`的参数, 或者需要对实例化出来的`ActivityInstance`进行统一的操作, 那么就需要我们自己写一个子类来继承`RegisterActivity`.
操作`ActivityInstance`需要重写:
```csharp
/// <summary>
/// 该函数在物体实例化后调用, 可用于一些自定义操作, 参数为实例对象
/// </summary>
public virtual void CustomHandler(ActivityObject instance)
{
}
```
例子: 注册武器, [RegisterWeapon.cs](../DungeonShooting_Godot/src/game/item/weapon/RegisterWeapon.cs)
由于创建武器必须指定武器属性数据, 那么原来的`[RegisterActivity()]`就不适用了, `RegisterWeapon`重写了构造函数, 改变了初始化参数, 并且重写`CustomHandler()`, 对`ActivityInstance`进行初始化属性操作
#### 3.2.5.ActivityObject常用功能
#### 3.2.2.ActivityObject常用功能
##### 自定义组件
这个功能类似于`Unity`的`MonoBehaviour`, 组件必须继承`Component`类, 组件的作用是拆分功能代码, 开发者可以将相同功能的代码放入同一个组件中, 与`Godot`的`Node`不同的是, 挂载到`ActivityObject`上的组件并不会生成一个`Node`节点, 它相比于`Node`更加轻量
@ -364,90 +257,6 @@ private IEnumerator StartRotation()
* **商店**: 玩家买卖道具装备的房间
* **事件房间**: 触发剧情或者解锁NPC的房间
#### 3.3.2.创建模板房间
图块层级概述(后续补上, 先默认使用`resource/map/tileset/TileSet1.tres`)
##### 创建模板房间
项目提供了一套创建模板房间的工具, 点击`tools`页签, 找到`创建地牢房间`这一项, 输入模板房间名称(注意房间名称不能重复), 即可创建房间, 创建房间完成后会创建房间配置数据, 路径为`resource/map/tiledata/xxx.json`, 并将配置数据注册到`resource/map/RoomConfig.json`中
![](文档资源/image_7.png)
##### 绘制房间
创建好的房间会自动在编辑器中打开, 为场景的根节点选好`TileSet`后就可以画房间了
![](文档资源/image_8.png)
编辑器会自动计算出房间位置轮廓(绿色线)和导航区域(红色和黄色线), 并绘制出来, 按下`ctrs`+`s`, 编辑器就会将位置轮廓和导航信息存入`resource/map/tiledata/xxx.json`下
注意, 为了避免Ai运动时卡墙角, 所以计算导航轮廓时特意与墙预留了半个格子的距离, 也就是说如果存在单格的道路, 导航计算就会出错, 所以在画道路时必须为两格以上的宽度, 像下面这两种情况就是不被允许的, 编辑器会绘制出错误的格子
![](文档资源/image_9.png)
![](文档资源/image_10.png)
如果计算导航网格出错, 那么编辑器将不会保存房间配置信息
##### 配置房间门生成位置
如果某些模板房间需要在指定区域内生成门, 那么就需要设置房间门生成区域
在模板场景中选中根节点, 再勾选`Enable Edit`
![](文档资源/image_11.png)
此时将鼠标放置在房间轮廓的绿线上就会显示生成区域
![](文档资源/image_12.png)
点击鼠标左键即可创建门区域, 如果悬停时显示红色方块, 则表示不能在此处创建门区域
创建门生成区域的约束: 区域不能重叠, 且两个区域的间距至少为4格, 每个区域至少4格宽度
![](文档资源/gif_1.gif)
新建的区域默认为4格宽度, 如果需要调整宽度, 可以拖拽区域两侧的点来调整范围
![](文档资源/gif_2.gif)
如果需要删除区域, 则悬停到区域两侧任意一个点上, 按下鼠标中建即可删除
![](文档资源/gif_3.gif)
门区域需要对齐地面地砖
![](文档资源/image_13.png)
注意:
* 如果一个模板房间不设置门生成区域, 则默认四边任何位置都可能生成门
* 配置好一个房间的门生成区域后, 如果绘制房间时改变了房间的大小或者位置, 则编辑器会清空配置的门区域
* 编辑门区域功能属于扩展编辑器功能, 因此单纯改变门区域数据不会在场景页签上标`*`(编辑器不会认为该资源有修改), 修改后需要及时按下`ctrl`+`s`保存, 以免造成数据丢失
##### ActivityMark标记
`ActivityMark`用于模板房间中创建`ActivityObject`对象, 并支配置指定的物体, 第几波生成该物体以及生成物体延时时间
源代码: [ActivityMark.cs](../DungeonShooting_Godot/src/framework/map/mark/ActivityMark.cs)
在房间根节点中创建`ActivityMark`对象
![](文档资源/image_18.png)
创建完成后可以看到地图上多了一个`X`, 这个叉就是生成物体的位置, 可自由调整位置
![](文档资源/image_19.png)
然后就可以在编辑器中设置`ActivityMark`数据了, `ActivityMark`有以下可以导出的属性:
```csharp
/// <summary>
/// 物体类型
/// </summary>
[Export]
public ActivityIdPrefix.ActivityPrefixType Type = ActivityIdPrefix.ActivityPrefixType.NonePrefix;
/// <summary>
/// 物体id
/// </summary>
[Export]
public string ItemId;
/// <summary>
/// 所在层级
/// </summary>
[Export]
public RoomLayerEnum Layer = RoomLayerEnum.NormalLayer;
/// <summary>
/// 该标记在第几波调用 BeReady
/// 一个房间内所以敌人清完即可进入下一波
/// </summary>
[Export]
public int WaveNumber = 1;
/// <summary>
/// 延时执行时间,单位:秒
/// </summary>
[Export]
public float DelayTime = 0;
```
###### 扩展ActivityMark标记
项目中提供了以下几个扩展`ActivityMark`属性的节点:
* [WeaponMark](../DungeonShooting_Godot/src/framework/map/mark/WeaponMark.cs): 创建武器设置弹药等
* [EnemyMark](../DungeonShooting_Godot/src/framework/map/mark/EnemyMark.cs): 创建敌人并设置武器和弹药
### 3.4.UI系统
@ -513,17 +322,21 @@ public virtual void OnCreateUi()
/// <summary>
/// 当前ui显示时调用
/// </summary>
public abstract void OnShowUi();
public virtual void OnShowUi()
{
}
/// <summary>
/// 当前ui隐藏时调用
/// </summary>
public abstract void OnHideUi();
public virtual void OnHideUi()
{
}
/// <summary>
/// 销毁当前ui时调用
/// </summary>
public virtual void OnDisposeUi()
public virtual void OnDestroy()
{
}
```