卡牌遊戲戰鬥系統的設計和實現(三)

上一篇文章,我主要是從全局的一個角度,架構了戰鬥系統,這裏我將詳細分析具體的實現細節。

這場戰鬥中,我們需要關注的點:戰鬥前期準備,單次戰鬥結算, 技能釋放,戰鬥結算。

戰鬥前期

在航海類遊戲中,參戰的首要條件是,你必須是出海狀態,然後檢測你的參戰資格,例如你的生命值不能低於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,
        );
    }
以上,就是戰鬥過程的具體實現方式了。



發佈了41 篇原創文章 · 獲贊 14 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章