战斗系统之操作策略篇
1.战斗中的条件满足条件后会运行对应的操作策略。
a.操作基础类:
public class VOper
{
public float DelayTime;
private int acId;
public int TargetBodyId;
public SVType Type = SVType.None;
public float OpValue;
public VOper(){ }
public void SetTargetBodyId(int pBodyId)
{
TargetBodyId = pBodyId;
}
public void SetOpValue(float pValue)
{
OpValue = pValue;
}
public void SetValueType(SVType pType)
{
Type = pType;
}
public void StartAction(float pTime)
{
if (DelayTime > 0)
{
acId = Word.Instance.runer.AddActioner(DelayTime, (time) =>
{
acId = 0;
OnAction(time);
});
}
else
{
OnAction(pTime);
}
}
public void StopAction()
{
if (acId > 0)
{
Word.Instance.runer.RemoveActioner(acId);
acId = 0;
}
OnStop();
}
protected virtual void OnStop(){ }
public SVBase GetValue()
{
var vBase = Word.Instance.GetValue(TargetBodyId, Type);
return vBase;
}
protected virtual void OnAction(float pTime){}
}
b.扩展待机操作:
public class VIdleOper : VOper
{
protected override void OnAction(float pTime)
{
var setX = new VSetDeltaOper();
setX.SetOpValue(0);
setX.SetTargetBodyId(TargetBodyId);
setX.SetValueType(SVType.PosX);
setX.StartAction(pTime);
var setY = new VSetDeltaOper();
setY.SetOpValue(0);
setY.SetTargetBodyId(TargetBodyId);
setY.SetValueType(SVType.PosY);
setY.StartAction(pTime);
}
}
c.扩展攻击操作:
public class VAtkOper : VOper
{
protected override void OnAction(float pTime)
{
var forcusBase = Word.Instance.GetForcusBody(TargetBodyId);
if (forcusBase != null)
{
var oper = new VAddOper();
oper.SetTargetBodyId(forcusBase.BodyId);
oper.SetValueType(SVType.Hp);
var atk = Word.Instance.GetValue(TargetBodyId, SVType.Atk);
oper.SetOpValue(-1* atk.curValue);
oper.StartAction(pTime);
}
}
}
2.条件满足了不一定就会马上执行必须经过策略决策当前应该执行哪个策略:
a.策略基础类:
public class VPolicy
{
public VTrigger trigger;
public VOperGroup operGroup;
public int BodyId;
public int Prox = 1;//策略的优先执行
private float cd = 1f;//策略执行操作的的内置cd
private bool enable = true;
private bool isLoad = false;
private System.Action<VPolicy, float> triggerCb;
public VPolicy() { }
public VPolicy(int pBodyId)
{
BodyId = pBodyId;
}
public bool IsAllPass(float pTime)//该策略是否能够执行
{
return trigger.IsAllPass(pTime);
}
public void SetProx(int pProx)
{
Prox = pProx;
}
public void SetCd(float pCD)
{
cd = pCD;
}
public void SetTriggerCb(System.Action<VPolicy, float> pTriggerCb)
{
triggerCb = pTriggerCb;
}
protected virtual void OnLoad(){ }
public void Load(){
if (isLoad)
return;
isLoad = true;
OnLoad();
operGroup.Load();
trigger.Load();
}
public void StartOp(float pTime)
{
if (!enable)
return;
//UnityEngine.Debug.LogError("pVPolicy" + Prox + "pVPolicy body id is :" + BodyId);
enable = false;
operGroup.StartAction(pTime);
Word.Instance.runer.AddActioner(cd, (oTime) => {
enable = true;
});
}
public void StopOp()
{
operGroup.StopAction();
}
}
b.扩展巡逻策略
public class VPatrolPolicy : VPolicy
{
public VPatrolPolicy(int pBodyId)
{
BodyId = pBodyId;
}
protected override void OnLoad()
{
trigger = new VPatrolTrigger(BodyId);
operGroup = new VPatrolOpGroup(BodyId);
}
}
c. 扩展追逐策略
public class FollowPolicy : VPolicy
{
private float range = 4;
public FollowPolicy(int pBodyId,int pRange)
{
BodyId = pBodyId;
range = pRange;
}
protected override void OnLoad()
{
trigger = new VFollowTrigger(BodyId, range);
operGroup = new VFollowOpGroup(BodyId);
}
}
3.策略组逻辑
一个实例肯定会绑定若干策略组,若干策略中到底哪个会优先执行必须有一个规则
a. 策略组基础类:
using System.Collections.Generic;
public class VPolicyGroup
{
public int BodyId;
private List<VPolicy> list = new List<VPolicy>();
private VPolicy runIngPolicy;
private int runAcId = 0;
public VPolicyGroup() { }
public VPolicyGroup(int pBodyId)
{
BodyId = pBodyId;
}
public void Load()
{
OnLoad();
}
protected virtual void OnLoad(){ }
public void AddPolicy(VPolicy pPolicy,int pProx)
{
list.Add(pPolicy);
//pPolicy.SetTriggerCb(OnOnePolicyTrigger);
pPolicy.SetProx(pProx);
pPolicy.Load();
list.Sort((l,r)=>{
if (l.Prox > r.Prox)
return -1;
else if (l.Prox == r.Prox)
return 0;
else
return 1;
});
}
private VPolicy GetMaxProlicy(float pTime)
{
var curRuningProx = 0;
if (runIngPolicy != null)
{
curRuningProx = runIngPolicy.Prox;
}
for (var i = 0; i < list.Count; i++)
{
if (list[i].IsAllPass(pTime))
{
return list[i];
}
}
return null;
}
public void StartRun(float pTime)
{
//StopRun(pTime);
runAcId = Word.Instance.runer.AddLoopActioner((oTime) => {
var policy = GetMaxProlicy(oTime);
OnOnePolicyTrigger(policy, oTime);
});
}
public void StopRun(float pTime)
{
if (runAcId > 0)
{
Word.Instance.runer.RemoveActioner(runAcId);
runAcId = 0;
}
}
public void OnOnePolicyTrigger(VPolicy pVPolicy,float pTime)
{
//UnityEngine.Debug.LogError("pVPolicy" + pVPolicy.Prox + "pVPolicy body id is :"+ pVPolicy.BodyId);
if (runIngPolicy == null)
{
runIngPolicy = pVPolicy;
runIngPolicy.StartOp(pTime);
}
else if (pVPolicy.Prox > runIngPolicy.Prox)
{
runIngPolicy.StopOp();
runIngPolicy = pVPolicy;
runIngPolicy.StartOp(pTime);
}
else if (runIngPolicy.IsAllPass(pTime) == false)
{
runIngPolicy.StopOp();
runIngPolicy = pVPolicy;
runIngPolicy.StartOp(pTime);
}
}
}
b.扩展普通策略组
public class NormalPolicyGroup : VPolicyGroup
{
public NormalPolicyGroup(int pBodyId)
{
BodyId = pBodyId;
}
protected override void OnLoad()
{
var idlePolicy = new IdlePolicy(BodyId);//待机
AddPolicy(idlePolicy,1);
idlePolicy.Load();
var patrolPolicy = new VPatrolPolicy(BodyId);//巡逻
AddPolicy(patrolPolicy,2);
patrolPolicy.Load();
var warningPolicy = new WarningPolicy(BodyId,8);//警戒
AddPolicy(warningPolicy, 3);
warningPolicy.Load();
var followPolicy = new FollowPolicy(BodyId, 8);//追敌
AddPolicy(followPolicy, 4);
followPolicy.SetCd(0.5f);
followPolicy.Load();
var atkPolicy = new AttackPolicy(BodyId,3,1);//攻击
AddPolicy(atkPolicy, 5);
atkPolicy.Load();
var deadPolicy = new DeadPolicy(BodyId);//死亡策略
AddPolicy(deadPolicy, 6);
deadPolicy.Load();
}
}
4.数值实例
a 数值实例基础类:
public class VBody
{
public SVGroup group;
public VPolicyGroup policys;
public int BodyId;
public VBody()
{ }
public VBody(int pBodyId)
{
BodyId = pBodyId;
}
public void StatRun(float pTime)
{
policys.StartRun(pTime);
}
public SVBase GetValue(SVType pType)
{
if (group != null)
{
return group.GetValue(pType);
}
return null;
}
public float GetDistance(VBody pTargetBody)
{
var selfX = GetValue( SVType.PosX).curValue;
var selfY = GetValue(SVType.PosY).curValue;
var targetX = pTargetBody.GetValue(SVType.PosX).curValue;
var targetY = pTargetBody.GetValue(SVType.PosY).curValue;
return (selfX - targetX) * (selfX - targetX) + (selfY - targetY) * (selfY - targetY);
}
public void Load()
{
OnLoad();
}
protected virtual void OnLoad()
{
}
public virtual void OnUnload()
{
}
}
b 扩展一个普通实例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VNormalBody : VBody
{
private CampType campTyp;
private Vector3 bornPosition;
private int hp_ = 1;
private int atk_ = 1;
private float speed_ = 2f;
private int model_ = 1;
public VNormalBody(int pBodyId, CampType pCampType,Vector3 pPos, int Hp,int Atk,int pSpeed = 2, int pModel = 1)
{
BodyId = pBodyId;
campTyp = pCampType;
bornPosition = pPos;
hp_ = Hp;
speed_ = pSpeed;
model_ = pModel;
atk_ = Atk;
}
protected override void OnLoad()
{
var _group = new VNormalGroup(BodyId, campTyp, hp_, atk_,speed_, model_);
_group.SetBornPosition(bornPosition);
group = _group;
group.Load();
policys = new NormalPolicyGroup(BodyId);
policys.Load();
}
}