在一篇文章中,我更多的是从游戏理论的角度,讨论了战斗的系统的设计。这篇文章中,我将从程序的角度,以一款航海类游戏为例,实现战斗系统。
在航海类游戏中,战斗角色是出海的船只,一次出海的船只的数量有限定,船只可以装配火炮,护甲,船帆等装备,船只还可以通过装配船长来获取技能。技能的发动是有概率的。战斗规则是,在20个回合内,如果把对方所有的船只击沉,即赢得战斗胜利,否则未平局。
战斗流程大致是这样:
这个开炮的具体的算法,我会在后面详细的贴出代码。
当我们了解了战斗的大致情况,并把所有的准备工作做好之后 (选择了参战的船只, 船只搭配了装备,选择了船长),还需要考虑的事情有如下几点:
对手:在航海类游戏中,对手有几种:常规玩家,常规NPC, 世界BOSS,海盗等。不同的对手有某些细微的差别,例如,和玩家对战的时候,需要检测玩家的参战条件,和NPC对战的时候不需要。
技能:技能的类型可能有多种,每一种技能都需要考虑到技能的释放对象,技能的影响,判断技能是否发动成功等。
战斗的核心行为:设置攻击者,防御者,执行伤害程序等。
战斗的辅助操作:寻找舰队中目前存活的第一艘船,获取舰队中现在还存活船只的数目等。
战斗奖赏:处理每次战斗的奖赏。
战斗结算:不同的对手,结算的方式不同,最后提示的信息也不同。
单次战斗记录:需要记录战斗的信息,便于前端解析这些信息,呈现战斗动画
战斗观察员:记录整场战斗的信息,便于战斗的回放。
前端表现:解析战斗信息,播放战斗动画。
针对以上的需要考虑的事情,我们可以做出多个类,每个类都有特定的职责,实现这些类中方法的思维过程就是把一个复杂的战斗动作拆分成各种小动作。这是一种组合类的设计方式。由于这个类图画的过于大,无法贴图,只有做出链接。
在战斗模型父类里面,主要实现的战斗的初始化工作和战斗的具体实现流程。
/**
* 战斗进行(外观模式)
*
* @return const
*/
public function process()
{
// 悬赏战初始化
if ($this->_inBounty) {
$this->_initBounty();
}
// 创建战斗记录器
$th