网络游戏战斗系统之buff系统具体设计实现

    在网络游戏中的战斗形式多种多样,不同游戏的战斗逻辑也有很大的差异。但是一般都会涉及技能系统和buff系统,两种之间相互关联,技能可以产生buff作用在目标上,影响目标。同时buff也会影响技能的释放效果,两者都可以算得上游戏战斗系统最重要的元素。

    在游戏战斗中有许多各种各样复杂的buff和技能,这些buff和技能是由基础的buff和技能效果机制组合形成的。通过基础的机制效果的组合,形成各种各样的复杂的buff和技能。这些基础的buff效果机制和技能效果机制支持策划通过配置表配置数据,来影响这些buff和技能的实际效果。

    不同类型的游戏的战斗可能多种多样,但是只要把握核心要素,相同buff系统和技能系统可以适应不同类型的游戏。

    下面介绍我对于buff系统的理解,算是抛砖引玉吧。

    buff的来源可能是战斗单元释放的技能,可能是buff效果产生新的buff,可能是战斗一开始因为佩戴某件装备。

    buff产生的效果各种各样例如,增加\降低属性值,一定时间内流失/恢复生命、魔法等,眩晕,沉默,护盾,嘲讽,反伤,攻击时攻击增伤、受击时减伤,死亡时造成对手造成伤,击杀目标时回血等等。同一个战斗单元可以有多个buff。

    为了增加buff系统的可用性和灵活性,我们可以把一个buff拆分成一到多个基础的buff效果,通过实现基础的buff效果,灵活组合形成多种多样的buff。例如给英雄施加一个buff效果是护盾同时在buff移除时恢复英雄10%的血量,这一个buff就有两个基础效果,一个是护盾,另一个是buff移除时回复血量,一个buff可以有一到多个buff效果,而一个英雄有多个buff。

    为了管理战斗单元存在的诸多buff,需要一个buff管理器管理buff的添加、生效、移除等整个生命周期,供外部使用的接口也只能是buffManger,比如添加buff,发送buff列表,检查buff效果状态,在触发点调用来执行buff效果等等。buff基础效果、buff、buff管理器关系如下:

 

    具体实现需要设计一个buff效果的基类,其中成员变量有buff效果编号以及buff效果实现的虚函数。所有buff机制效果需要继承基类,根据具体buff效果实现void perform(unsigned char buffStep)函数,每一个buff效果编号,用于区分所属buff效果,这样便于buff管理包含的buff效果。

struct basePerform
{
	eBuffPerfrom perfromType;//可以定义一个枚举
Buff* owner;				//所属buff
	basePerform(eBuffPerfrom _perfromType, Buff* _owner):perfromType(_perfromType),owner(_owner)
	{}
virtual void perform(unsigned char buffStep)=0;//buff效果具体执行
	virtual ~basePerform(){}
};

    buff管理着一到多个继承自basePerform的子类对象。效果编号决定执行那个buff基础效果。buff中还有记录着释放buff者战斗单元的指针、buffManger的指针、buff叠加层数、buff配置数据,buff生成时间、buff类型、buff移除标志等数据。

class Buff
{
public:
	Buff(FightUnit* _attacker,buffManger* _manger,  const cBuffCfg* _cfg, eBuffType _buffType, DWORD _putTime);
	virtual ~Buff();
//一些函数实现,诸如buff效果的实现,buff初始化,标记移除等等
public:
	FightUnit* attacker;     //产生buff的FightUnit
buffManger* _manger;
	const cBuffCfg* _cfg;	   // buff配置表数据
	unsigned long putTime;    //buff的产生时间
	unsigned short overlay;   //叠加层数
	eBuffType buffType; 		//buff类型
	bool bRemove; 			//移除标记
unsigned char buffStep; 	//buff执行步骤
	std::vector<basePerform*> vecBuffPerform;//buff的所有效果
}

buffManger保存这一组buff,buffManger所属的战斗单元等数据。控制着buff的整个生命周期

class buffManger
{
public:
	buffManger(FightUnit* _owner);
	virtual ~buffManger();
//一些函数实现,比如添加/移除buff函数,timetick函数,buff触发函数,检查buff效果函数等等
privet:
	FightUnit* owner;
	std::vector<Buff*> vecBuffs;
unsigned short buffPerformStatus[eBuffPerfrom_Max];
}

buff效果多种多样,buff效果可能是某种状态,比如眩晕,在战斗单元行动或释放技能时,检查战斗单元的buffManger遍历所有的vecBuffs下所有buff的buff效果是否有眩晕效果,如果有不能行动或者释放技能。也可能是加属性值的,添加或者移除buff时根据buff效果重新计算战斗单元的属性值。或者是触发式,比如流失对于回合制的便可能是每回合造成减血,对于非回合制的可能是每秒造成减血。触发有很多点会导致触发,比如死亡时,攻击时,受击时,暴击时,格挡时等等,这样每次到触发点,要遍历所有buff的所以机制找到符合条件的执行buff效果。

为了减少遍历次数,可以在buffManger中添加buffPerformStatus数组变量,模仿只能指针做一个计数。每一个成员代表这个buffManger的buff效果的计数,如果没有相应的buff效果计数值为零,添加buff时如果有相应的buff效果,计数加一,buff移除相应buff效果也移除,计数减一。这样我们在检查某种buff状态,比如眩晕,就不需要遍历说有的buff了。触发时如果有相应的buff效果再去遍历。

这样这个buff系统模型可以适合大部分战斗,稍微改改不同的战斗都可以使用。

猜你喜欢

转载自blog.csdn.net/qq_19825249/article/details/108291738
今日推荐