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

转载自:http://www.lxway.com/4418844601.htm


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

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

战斗前期

在航海类游戏中,参战的首要条件是,你必须是出海状态,然后检测你的参战资格,例如你的生命值不能低于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,
        );
    }
以上,就是战斗过程的具体实现方式了。

你可能感兴趣的:(游戏,战斗系统)