第十一章 地图动作与地图事件(Map Action and Map Event)
我们已经有了剧本,而且可以运行剧本,但我们还缺少对地图的操作控制。
我们这一章来完成地图上的操作,地图的操作将全部由MapAction
控制。
七 地图事件的结果(Result of Map Event)
地图事件是我们地图中所发生的事情,包括:
-
触发条件;
-
触发结果。
它也比较常见,例如:
条件 | 结果 | FE4中实例 |
---|---|---|
地图开始 | 创建各种地图对象 | 战斗开始时的剧情,然后创建地图对象 |
角色到达某个地点 | 获取物品 | 第一章时斧骑士到达海边获取二回攻击斧 |
某回合开始 | 创建各种地图对象 | 某些剧情需要 |
对应角色对话 | 获取物品、提升属性等 | 某些章节对话 |
等等诸如此类的事件。
这一节,我们挑选一些典型的事件来说明。
1 结果类(Class Result)
和条件类似的,每个事件触发的结果可能是多种。
首先,我们先来归类一下结果类型:
创建一个枚举MapEventResultType
来表示结果类型(它们不是必须的,按需来):
using System;
namespace DR.Book.SRPG_Dev.ScriptManagement
{
[Serializable]
public enum MapEventResultType
{
NoneResult = 0,
/// <summary>
/// 剧本
/// </summary>
ScenarioResult,
/// <summary>
/// 创建MapObject
/// </summary>
CreateObjectResult,
/// <summary>
/// 传送位置
/// </summary>
PositionResult,
/// <summary>
/// 增加/减少属性
/// </summary>
PropertyResult,
/// <summary>
/// 获得/遗失物品
/// </summary>
ItemResult,
/// <summary>
/// 战斗胜利
/// </summary>
WinResult,
/// <summary>
/// 战斗失败
/// </summary>
LoseResult
}
}
这些结果,我们规定:
-
NoneResult
:没有任何结果; -
ScenarioResult
:剧本结果,触发剧情; -
CreateObjectResult
:创建对象结果,创建地图障碍物或角色等(你也可以添加一个变量,判断是创建还是消除,我在这里只是创建); -
PositionResult
:位置结果,它用来表示将角色传送到的位置; -
ItemResult
:物品结果,获取或遗失某些物品; -
WinResult
:战斗胜利结果; -
LoseResult
:战斗失败结果。 -
其它:包含移动角色,摄像机等,这些我并没有写,你可以添加。
这些结果需要返回一个布尔类型,来表示是否运行成功。
创建类:
[Serializable]
public class Result
{
[XmlIgnore]
public virtual MapEventResultType type
{
get {
return MapEventResultType.NoneResult; }
}
public virtual bool Trigger(MapAction action)
{
return true;
}
}
2 剧本结果(Scenario Result)
剧本的结果,是用来触发某些剧情的,自然要使用MapScenarioAction
。
而触发哪段剧情,需要用到剧情标识符。
[Serializable]
public class ScenarioResult : Result
{
[XmlAttribute]
public string flag;
[XmlIgnore]
public override MapEventResultType type
{
get {
return MapEventResultType.ScenarioResult; }
}
public override bool Trigger(MapAction action)
{
return action.ScenarioCommand(flag);
}
}
3 创建对象结果(Create Object Result)
我们要在地图创建的对象包含:
-
地图障碍物(MapObstacle)
-
地图职业(MapClass)
- 独有角色
- 杂兵角色
所以,我们要先有其对应的方法才可以。
3.1 创建地图障碍物(Create Map Obstacle)
在MapAction
中,我们创建方法:
protected readonly HashSet<MapObstacle> m_Obstacles =
new HashSet<MapObstacle>();
/// <summary>
/// 创建Obstacle
/// </summary>
/// <param name="prefab"></param>
/// <param name="position"></param>
/// <param name="cmdError"></param>
/// <returns></returns>
public ActionStatus ObjectCommandCreateObstacle(
string prefab,
Vector3Int position,
out string cmdError)
{
// TODO
cmdError = null;
return ActionStatus.Continue;
}
提示:这些方法是在地图事件之前完成的,所以返回值使用了ActionStatus
,这里使用bool
也可以,下同。
首先,我们应该检测其合法性:
-
位置必须在地图内;
-
位置网格中不能存在其它地图对象;
-
创建的
prefab
必须是障碍物。
CellData cellData = map.GetCellData(position);
if (cellData == null)
{
cmdError = string.Format(
"{0} Create Obstacle -> position `{1}` is out of range. prefab: {2}",
"ObjectExecutor",
position.ToString(),
prefab);
return ActionStatus.Error;
}
if (cellData.hasMapObject)
{
cmdError = string.Format(
"{0} Create Obstacle -> the object in position `{1}` is already exist. prefab: {2}",
"ObjectExecutor",
position.ToString(),
prefab);
return ActionStatus.Error;
}
MapObject mapObject = map.CreateMapObject(prefab, position);
if (mapObject == null || mapObject.mapObjectType != MapObjectType.Obstacle)
{
cmdError = string.Format(
"{0} Create Obstacle -> create map object error. prefab: {1}",
"ObjectExecutor",
prefab);
if (mapObject != null)
{
ObjectPool.DespawnUnsafe(mapObject.gameObject, true);
}
return ActionStatus.Error;
}
最后,将它添加到我们的集合中,并返回结果:
m_Obstacles.Add(mapObject as MapObstacle);
cellData.mapObject = mapObject;
cmdError = null;
return ActionStatus.Continue;
3.2 创建地图职业(Create Map Class)
在创建地图职业时,我们需知:
-
关于等级与物品,在独有角色时我们放在了
CharacterInfoConfig
中,而杂兵角色我们将放在这里; -
独有角色时,
id
表示角色id,而在杂兵角色时,它是指职业id; -
玩家阵营不应出现杂兵角色。
创建方法:
/// <summary>
/// 创建MapClass
/// </summary>
/// <param name="attitudeTowards"></param>
/// <param name="roleType"></param>
/// <param name="id"></param>
/// <param name="position"></param>
/// <param name="level"></param>
/// <param name="items"></param>
/// <param name="cmdError"></param>
/// <returns></returns>
public