iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
自我挑戰組

順著感覺走!從零開始的 Python & Vibe Coding 遊戲創作系列 第 18

第18天: 觸發強力效果:卡牌技能的程式碼實現深度解析

  • 分享至 

  • xImage
  •  

嗨,各位程式碼冒險家!歡迎來到我的「順著感覺走!從零開始的 Python & Vibe Coding 遊戲創作」第十八天。如果說 GameManager 是遊戲的心臟,那麼今天我們要深入探討的 trigger_card_effect 方法,就是將卡牌從一張靜態圖片,轉化為能夠撼動戰局的強大力量的關鍵。這個方法是整個戰鬥系統的核心,負責解析卡牌效果並精準地將其應用到目標身上。

在先前的設計中,我們使用一個名為 SkillEffect字典(Dictionary),集中管理了所有卡牌的技能效果。這種設計的優勢在今天將完全體現出來:它讓技能觸發邏輯變得極其靈活且易於維護。現在,讓我們深入 gamemanager.py,剖析這個賦予卡牌生命的方法。


一、技能觸發的核心樞紐:trigger_card_effect 方法

trigger_card_effect 方法位於 GameManager 類別中,其職責非常明確:接收觸發的卡牌類型施法者目標,然後根據 SkillEffect 字典的定義,執行一系列對應的遊戲邏輯。

程式碼實現 (gamemanager.py)
def trigger_card_effect(self, card_type, caster, target):
    if card_type not in SkillEffect:
        return

    effect = SkillEffect[card_type]
    log_message = f"卡牌 {card_type.value} 效果觸發:"
    effects_list = []

    # 處理傷害 (Damage) 邏輯
    if "damage" in effect:
        damage = effect["damage"]
        is_piercing = "pierce_shield" in effect and effect["pierce_shield"]
        
        if is_piercing:
            target.health = max(target.health - damage, 0)
            effects_list.append(f"對 {target.name} 造成 {damage} 穿透傷害")
        else:
            damage_dealt = target.take_damage(damage)
            effects_list.append(f"對 {target.name} 造成 {damage_dealt} 傷害")

    # 處理治療 (Heal) 邏輯
    if "heal" in effect:
        heal_amount = effect["heal"]
        caster.heal(heal_amount)
        effects_list.append(f"{caster.name} 恢復 {heal_amount} HP")

    # 處理護盾 (Shield) 邏輯
    if "shield" in effect:
        shield_amount = effect["shield"]
        caster.add_shield(shield_amount)
        effects_list.append(f"{caster.name} 增加 {shield_amount} 護盾")

    # 處理額外行動 (Extra Moves) 邏輯
    if "extra_moves" in effect:
        self.action_count = max(0, self.action_count - effect["extra_moves"])
        effects_list.append(f"{caster.name} 獲得 {effect['extra_moves']} 次額外行動")
    
    # 整合並記錄到戰鬥日誌
    log_message += ",".join(effects_list)
    self.add_to_log(log_message)

二、程式碼技術細節深度解析

1. 參數與 SkillEffect 字典的運用
  • card_type, caster, target:這三個參數是方法執行的基礎,清楚定義了「哪張牌 (card_type)」由「誰 (caster)」對「誰 (target)」產生了效果。
  • effect = SkillEffect[card_type]:這是整個方法的查詢核心。程式碼利用傳入的 card_type 作為鍵(Key),直接從 SkillEffect 字典中獲取對應的效果描述(一個包含具體效果的子字典)。例如,當 card_typeCardType.SWORDSMAN 時,effect 就會是 {"damage": 15}。這種鍵值對查詢的方式,讓我們無需使用冗長的 if/elif/else 結構來判斷卡牌類型,大幅提升了程式碼的可讀性與擴充性。
2. 傷害 (Damage) 邏輯的實現

這是最複雜的邏輯區塊,體現了條件判斷的精妙之處。

  • if "damage" in effect::首先檢查效果字典中是否存在 "damage" 這個鍵。
  • 穿透傷害 (pierce_shield):程式會進一步檢查 "pierce_shield" 鍵是否存在且其值為 True。如果是,則直接扣減目標的 health 屬性,完全繞過護盾的計算邏輯。這正是魔法師卡牌(造成10點無視護盾傷害)的實現方式。
  • 一般傷害:如果不是穿透傷害,程式會呼叫目標 Player 物件的 take_damage 方法。這個方法內部已經封裝了優先扣除護盾、再扣生命值的完整邏輯,確保了傷害計算的準確性。這種職責分離的設計(GameManager 負責觸發,Player 負責承受)讓程式碼結構更清晰。
3. 治療 (Heal) 與護盾 (Shield) 邏輯
  • if "heal" in effect::當效果字典包含 "heal" 鍵時,程式會取出治療數值,並呼叫施法者 (caster) 自己的 heal 方法。heal 方法會確保生命值不會超過 max_health 上限。例如,祭司卡牌能恢復 15 點生命。
  • if "shield" in effect::同理,若有 "shield" 鍵,則呼叫施法者的 add_shield 方法增加護盾值。例如,元素使在造成傷害的同時,還能為自己增加 10 點護盾。
4. 額外行動 (Extra Moves) 邏輯的巧思
  • self.action_count = max(0, self.action_count - effect['extra_moves']):這個實現非常巧妙。遊戲規則是每回合最多 5 次行動。與其增加總行動上限,程式選擇直接減少「已消耗」的行動次數 (self.action_count)
  • 舉例說明:假設玩家已行動 3 次 (action_count 為 3),此時打出盜賊卡(提供 1 次額外行動)。action_count 會變成 max(0, 3 - 1),也就是 2。這相當於「返還」了一次行動機會,讓玩家在本回合中可以再行動 3 次(5 - 2 = 3),完美實現了額外行動的效果。
5. 戰鬥日誌 (Combat Log) 的整合
  • self.add_to_log(log_message):在所有效果處理完畢後,程式會將生成的日誌訊息 (log_message) 加入到 self.combat_log 這個清單中。這不僅方便開發者進行除錯,也為後續打造可回顧的戰鬥紀錄介面提供了數據基礎。

透過 trigger_card_effect 這個精心設計的方法,我們成功地將遊戲的核心機制——卡牌技能——模組化且高效地實現了。它與 SkillEffect 字典的完美結合,不僅讓當前的程式碼清晰易懂,更為未來新增卡牌、調整平衡性留下了極大的彈性空間。

明天,我們將探討牌組的流轉機制,看看遊戲是如何處理抽牌、棄牌以及手牌上限等重要規則的。敬請期待!


上一篇
第17天: 遊戲運行的心臟:《奇幻卡牌競技場》GameManager 的啟動與核心屬性
下一篇
第19天: 牌組的流轉:抽牌、棄牌與手牌管理的藝術
系列文
順著感覺走!從零開始的 Python & Vibe Coding 遊戲創作20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言