第九章 战斗系统(Combat System)
在SRPG中,大多数情况是指角色与角色之间的战斗。而这种战斗一般有两种模式:
-
地图中直接战斗;
-
有专门的战斗场景。
这两种模式的战斗在数据上没有任何区别,只有战斗动画的区别。
就像之前描述的,SRPG也是RPG,所以战斗方式和回合制RPG的战斗几乎是相同的。主要区别是RPG每个回合需要手动操作(也有自动战斗的),直到战斗结束;而SRPG是自动战斗,且多数情况只有一个回合(额外回合也是由于技能、物品或剧情需要)。且RPG多数是多人战斗,而SRPG多数是每边就一个。
我们这一章就来写一个战斗系统。
文章目录
二 计算战斗数据(Calculate Combat Data)
在计算战斗数据时,我们应该知道每一个回合需要可能改变的属性:
-
生命值(受到伤害,是否死亡);
-
魔法值(使用技能);
-
耐久度(使用武器);
除了这些,我们在战斗中还应该知道一些信息:
-
角色是否可攻击;
-
角色是否行动过;
-
角色攻击是否爆击。
当然,为了之后播放动画还应该知道:
- 播放哪个动画。
以上所提到的都可能在每次行动时改变。
而播放动画,我们用一个枚举来判断:
namespace DR.Book.SRPG_Dev.CombatManagement
{
public enum CombatAnimaType
{
Unknow,
Prepare, // 准备
Attack, // 攻击
Heal, //治疗
Evade, // 躲闪
Damage, // 受到攻击
Dead // 死亡
// 其它自定义
}
}
基于以上,我们来创建一个计算数据的类。
1 角色战斗变量(Role Combat Variable)
这里要建立的变量,就是每一个回合每个角色可能改变的变量。其中,position
是不变的,代表位置。
创建战斗变量CombatVariable
:
using System;
namespace DR.Book.SRPG_Dev.CombatManagement
{
[Serializable]
public struct CombatVariable
{
/// <summary>
/// 位置
/// </summary>
public int position;
/// <summary>
/// 生命值
/// </summary>
public int hp;
/// <summary>
/// 魔法值
/// </summary>
public int mp;
/// <summary>
/// 是否可攻击
/// </summary>
public bool canAtk;
/// <summary>
/// FE4武器耐久度(机器人大战技能数量)
/// </summary>
public int durability;
/// <summary>
/// 动画类型
/// </summary>
public CombatAnimaType animaType;
/// <summary>
/// 是否爆击
/// </summary>
public bool crit;
/// <summary>
/// 是否行动过
/// </summary>
public bool action;
/// <summary>
/// 是否已经死亡
/// </summary>
public bool isDead
{
get {
return hp <= 0; }
}
public CombatVariable(int position, int hp, int mp, bool canAtk, CombatAnimaType animaType)
{
this.position = position;
this.hp = hp;
this.mp = mp;
this.canAtk = canAtk;
this.durability = 0;
this.animaType = animaType;
this.crit = false;
this.action = false;
}
public CombatVariable(int position, int hp, int mp, bool canAtk, int durability, CombatAnimaType animaType)
{
this.position = position;
this.hp = hp;
this.mp = mp;
this.canAtk = canAtk;
this.durability = durability;
this.animaType = animaType;
this.crit = false;
this.action = false;
}
}
}
这里变量并没有考虑声音问题,还应有一个变量指代使用哪个音频,武器的声音可能是不同的。
2 战斗每一步(Combat Step)
我们的战斗不是只有一个角色,且为了播放动画每一次行动都要被记录,也就是说每一次行动后的结果也要被记录。
创建战斗每一步结果CombatStep
:
using UnityEngine;
namespace DR.Book.SRPG_Dev.CombatManagement
{
/// <summary>
/// 战斗每一步结果
/// </summary>
public class CombatStep
{
/// <summary>
/// 当前进攻方
/// </summary>
public CombatVariable atkVal {
get; private set; }
/// <summary>
/// 当前防守方
/// </summary>
public CombatVariable defVal {
get; private set; }
public CombatStep(CombatVariable atker, CombatVariable defer)
{
this.atkVal = atker;
this.defVal = defer;
}
/// <summary>
/// 根据位置获取战斗变量
/// </summary>
/// <param name="position"></param>
/// <returns></returns>
public CombatVariable GetCombatVariable(int position)
{
if (atkVal.position == position)
{
return atkVal;
}
if (defVal.position == position)
{
return defVal;
}
Debug.LogError("CombatStep -> position is out of range.");
return default