卡牌游戏战斗系统的设计和实现(三)

来源:互联网 发布:上帝粒子知乎 编辑:程序博客网 时间:2024/06/05 07:51

上一篇文章,我主要是从全局的一个角度,架构了战斗系统,这里我将详细分析具体的实现细节。

这场战斗中,我们需要关注的点:战斗前期准备,单次战斗结算, 技能释放,战斗结算。

战斗前期

在航海类游戏中,参战的首要条件是,你必须是出海状态,然后检测你的参战资格,例如你的生命值不能低于25HP,然后初始化玩家对象,玩家的舰队,玩家的船长等。
具体的流程图如下:

这里需要注意的的有如下几点:
1 验证formHash,同时要把对方的ID加密,这样做都是为了恶意攻击。如果加密和验证,我记住了你的ID,我就不断的可以攻击你。最简单的外挂就是这样做的。
2 初始化舰队的时候,船只的实力是装备过装备的实力。
3 初始化战斗类型的时候,可以使用工厂模式。

战斗技能

技能发动是有某个装配了船长的船发动的,而且是有概率的。当船发动攻击的时候,我们会做出一个判断技能是否发动成功:
        // 如果攻船正处于“封印”状态,则不能发动技能        if (Model_Battle_InSkill::isSealed($attackerShip)) {            $skillId = 0;        }        // 否则可以触发攻船的战斗内技能        else {            // 返回0表示触发失败,触发成功则返回技能Id            $skillId = Model_Battle_InSkill::triggerSkill($attacker, $attackerShip);        }

如果技能触发成功了后,我就会实例化这个技能:
// 创建本次技能实例        $skill = Model_Battle_InSkill::factory($skillId);
创建了技能之后,我们就要明白技能到底是如何工作的。
作用对象:我的的舰队,或者敌方的舰队。
效果:
该buff持续回合数
该buff是良性or恶性
 影响比例(小于100%表示减少,大于表示增加)
可能有这样的一个技能:
火爆出击: 把对方的任意三艘船的战斗力减少为50%,持续2回合。

技能的数据库设计:

需要的动作:
初始化双方的舰队,便于寻找作用对象
    // 设置己方舰队    public function setSelfShips(array $ships)    {        $this->_selfShips = $ships;    }    // 设置对方舰队    public function setEnemyShips(array $ships)    {        $this->_enemyShips = $ships;    }

设置作用对象 技能的作用对象都是存在表中。

    // 设置受技能对象(们)    public function setTargetShips()    {        $targetConfig = explode(':', $this->_prop['target_config']);        // 攻击哪方        $targetSide = isset($targetConfig[0]) ? $targetConfig[0] : null;        // 攻击规则        $targetRule = isset($targetConfig[1]) ? $targetConfig[1] : null;        // 攻击范围        $targetNum  = isset($targetConfig[2]) ? $targetConfig[2] : null;        // 受技能方的舰队信息        $ships = $targetSide == 'SELF' ? $this->_selfShips : $this->_enemyShips;        switch ($targetRule) {            // 全体            case 'ALL':                $this->_targetShips = $ships;                break;            // 随机定位            case 'RAND':                // 随机定位1艘存活的船                if ($targetNum == 1) {                    $this->_targetShips = array(Model_Battle_Util::findRandAliveShip($ships, 1));                }                // 随机定位N艘存活的船                else {                    $this->_targetShips = Model_Battle_Util::findRandAliveShip($ships, $targetNum);                }                break;            // 随机定位敌方一艘存活的带有战斗内技能的船            case 'RAND_SKILLED':                $targetShip = Model_Battle_Util::findRandAliveShipWithSkillIn($shipss, 1);                // 如果敌方没有一艘船是有技能的                if (! $targetShip) {                    // 那么随机定位敌方一艘存活的船                    $targetShip = Model_Battle_Util::findRandAliveShip($ships, 1);                }                $this->_targetShips = array($targetShip);                break;            // 缺省为舰队中存活的第一艘船            default:                $this->_targetShips = array(Model_Battle_Util::findFirstAliveShip($ships));                break;        }    }
设置作用效果
 // 设置船只buffs    public function setBuffs()    {        if (! $buffType = $this->_prop['buff_type']) {            return null;        }        switch ($buffType) {            // 影响攻击力            case 'offense':            // 中毒            case 'poisoned':                foreach ($this->getTargetShips() as $ship) {                    $ship->buffs[$buffType] = array(                        'rounds' => $this->_prop['buff_rounds'],        // 该buff持续回合数                        'status' => $this->_prop['buff_status'],        // 该buff是良性or恶性                        'rate'   => $this->_prop['buff_effect_rate'],   // 影响比例(小于100%表示减少,大于表示增加)                    );                }                break;            // 冰冻            case 'frozen':            // 封印            case 'sealed':                foreach ($this->getTargetShips() as $ship) {                    $ship->buffs[$buffType] = array(                        'rounds' => $this->_prop['buff_rounds'],                        'status' => $this->_prop['buff_status'],                    );                }                break;            // 清除良性buff            case 'clear_good':                foreach ($this->getTargetShips() as $ship) {                    foreach ($ship->buffs as $key => $buff) {                        if ($buff['status'] == 'good') {                            unset($ship->buffs[$key]);                        }                    }                }                break;            // 清除恶性buff            case 'clear_bad':                foreach ($this->getTargetShips() as $ship) {                    foreach ($ship->buffs as $key => $buff) {                        if ($buff['status'] == 'bad') {                            unset($ship->buffs[$key]);                        }                    }                }                break;        }    }

这里,给某艘船只施加技能效果的主要做法是,给船只数组添加新技能的属性,或者删除旧技能属性。
或许到这里,大家明白了什么时候会触发技能,什么时候施加技能效果,但这些效果是如何体现的,我们可能还不知道。
技能的影响是在具体的开火结算类。也就是下面我要说的。

单次战斗结算

什么是战斗结算,就是计算伤害点数,计算这个点数的时候,我们需要考虑如下几点:

1,应用buff并返回处理结果(攻/防/暴/闪/命/抗暴的增减益),这里就应用了技能的影响。
2,应用炮甲相克对守船防御力造成的折扣,这里涉及到相生相克的问题。
结算流程:
    public function execute()    {        if (! $this->_attackerShip || ! $this->_defenderShip) {            return null;        }        // 应用buff并返回处理结果(攻/防/暴/闪/命/抗暴的增减益)        $oddsData = Model_Battle_InSkill::applyShipBuff($this->_attackerShip, $this->_defenderShip);        // 应用单次行动前的属性影响        if ($this->_skill) {            $oddsData = Model_Battle_InSkill::applySingleActEffect($oddsData, $this->_skill);        }        // 导出数组变量        extract($oddsData);        // 应用炮甲相克对守船防御力造成的折扣        if ($this->_attackerShip['cannon_id'] && $this->_defenderShip['armor_id']) {            $defenderDefense *= self::getCannonVsArmorEffectRatio($this->_attackerShip['cannon'], $this->_defenderShip['armor']);        }        // 计算本次伤害点数        $damage = $this->_calcDamagePoint($attackerOffense, $defenderDefense, $attackerHitOdds, $defenderAvoidOdds, $attackerCritOdds, $defenderAntiCritOdds);        // 执行扣血        if ($damage > 0) {            self::deductShipHp($this->_defenderShip, $damage);        }        // 记录本次的伤害数值        $this->_logger->setDamage($damage);    }

注意,类的职能的划分很重要,主要extract()函数的使用,妙。下面是具体的应用buff的实现。
    /**     * 应用buff生效     */    public static function applyShipBuff(Model_Ship $attackerShip, Model_Ship $defenderShip)    {        $attackerOffense      = $attackerShip['offense'];           // 攻船攻击力        $attackerHitOdds      = $attackerShip['hit_odds'];          // 攻船命中率        $attackerCritOdds     = $attackerShip['crit_odds'];         // 攻船暴击率        $defenderDefense      = $defenderShip['defense'];           // 守船防御力        $defenderAvoidOdds    = $defenderShip['avoid_odds'];        // 守船闪避力        $defenderAntiCritOdds = $defenderShip['anti_crit_odds'];    // 守船抗暴击率        // 应用攻船的buff        if (isset($attackerShip->buffs) && $attackerShip->buffs) {            foreach ($attackerShip->buffs as $buffType => $buff) {                // 如果是攻击力增强、减弱状态                if ($buffType == 'offense') {                    $attackerOffense = floor($attackerOffense * $buff['rate']);                }                // 如果是命中率增强、减弱状态                elseif ($buffType == 'hit') {                    $attackerHitOdds = floor($attackerHitOdds * $buff['rate']);                }                // 如果是暴击率增强、减弱状态                elseif ($buffType == 'crit') {                    $attackerCritOdds = floor($attackerCritOdds * $buff['rate']);                }            }        }        // 应用守船的buff        if (isset($defenderShip->buffs) && $defenderShip->buffs) {            foreach ($defenderShip->buffs as $buffType => $buff) {                // 如果是防御力增强、减弱状态                if ($buffType == 'defense') {                    $defenderDefense = floor($defenderDefense * $buff['rate']);                }                // 如果是闪避率增强、减弱状态                elseif ($buffType == 'avoid') {                    $defenderAvoidOdds = floor($defenderAvoidOdds * $buff['rate']);                }                // 如果是抗暴击率增强、减弱状态                elseif ($buffType == 'anti_crit') {                    $defenderAntiCritOdds = floor($defenderAntiCritOdds * $buff['rate']);                }            }        }        return array(            'attackerOffense'      => $attackerOffense,            'attackerHitOdds'      => $attackerHitOdds,            'attackerCritOdds'     => $attackerCritOdds,            'defenderDefense'      => $defenderDefense,            'defenderAvoidOdds'    => $defenderAvoidOdds,            'defenderAntiCritOdds' => $defenderAntiCritOdds,        );    }
以上,就是战斗过程的具体实现方式了。



原创粉丝点击