CODE Python RPG

初心者がPythonでRPGを作成する(第10回)「ぼうぎょ」を作成

更新日:

こんにちは。
「Pythonでつくる ゲーム開発 入門講座」のChapter11,12(本格RPGを作ろう!全編・後編)を基にRPGを作っていきます。

前回は新しい戦闘コマンドから「こうげき」と「にげる」を選択できるようにしました。
今回は「ぼうぎょ」を選択できるようにします。

また、「こうげき」のダメージの計算方法を変えます。
ダメージに影響あるのは攻撃力のみですが、受ける側の防御力も考慮した計算に変更します。

目次

  1. ぼうぎょ
  2. こうげきのダメージ計算
  3. 最後に

ぼうぎょ

元のコマンドには「ぼうぎょ」が無く、新しく追加したコマンドなので、
まず「ぼうぎょ」の概念についてです。

 

「ぼうぎょ」を選択すると、そのターンのみ自身の防御力を2倍にすることにします。
仲間がいないとあまり意味が無いコマンドですが、
そこは追い追い、できるかな・・?(;^_^A

何にしても変更して行きます。
最初に「chara.py」です。

class Brave():
    def __init__(self):
        self.name = chara1_name
        self.lv = int(chara1_lv)
        self.maxhp = int(chara1_maxhp)
        self.hp = int(chara1_hp)
        self.maxmp = int(chara1_maxmp)
        self.mp = int(chara1_mp)
        self.atk = int(chara1_atk)
        self.dfs = int(chara1_dfs) # 防御力
    def reset(self):
        self.hp = self.maxhp
        self.mp = self.maxmp

特に使っていませんでしたが、第3回でクラスを作った時に防御力の変数だけは
作っていましたので、これを使います。
このクラスの中にメソッドを作って、その中で防御力を2倍にします。

(追加)
    def defense(self):
        self.dfs *= 2 # 防御力2倍
    def re_defense(self):
        self.dfs = int(chara1_dfs) # 防御力を元に戻す

見たままですが、defenseメソッドで防御力を2倍にします。
コマンド「ぼうぎょ」の効果は1ターンのみの為、
防御力を元に戻す必要があります。

なので、re_defenseメソッドで元に戻します。
理由は後述しますが、1/2にして戻すのではなく、
最初の防御力を入れることで防御力を戻します。

これで防御力を2倍にする準備はできたので、次に「one_hour_dungeon.py」です。

def main(): # メイン処理
(省略)
        elif idx == 11: # プレイヤーのターン(入力待ち)
(省略)
                if COM[btl_cmd_y][btl_cmd_x] == "ぼうぎょ": # 追加
                    idx = 18
                    tmr = 0
                if COM[btl_cmd_y][btl_cmd_x] == "にげる":
                    idx = 14
                    tmr = 0

                # コマンドの位置のリセット
                btl_cmd_x = 0
                btl_cmd_y = 0

「ぼうぎょ」選択の判断は「こうげき」や「にげる」と同じよう
if COM[btl_cmd_y][btl_cmd_x] == "ぼうぎょ":
です。
今回、新しく追加した「ぼうぎょ」は、idx = 18で処理します。

        elif idx == 18: # ぼうぎょ
            draw_battle(screen, fontS)
            if tmr == 1:
                player.defense() # 防御力2倍
                set_message(player.name + "は みをまもっている。")
            if tmr == 5:
                idx = 13 # モンスターのターン(攻撃)
                tmr = 0

「char.py」で作ったdefenseメソッドを使って2倍にして、
戦闘メッセージも表示させます。
これで「ぼうぎょ」を選択すると防御力が2倍になりますが、
ターンが終わると元に戻さないといけないので、
同じく「chara.py」で作ったre_defenseメソッドを以下に追加しました。

        elif idx == 11: # プレイヤーのターン(入力待ち)
            player.re_defense() # ぼうぎょを元に戻す(ぼうぎょ効果を消す)
            draw_battle(screen, fontS)
            if tmr == 1:
                set_message(player.name + " のターン")

ターン開始の前ならモンスターの攻撃も終わっています。
また、これが先程少し述べた1/2にして戻すのではなく、
最初の防御力を入れることで防御力を戻した理由です。

1/2にして戻すと、戦闘が開始した時や「ぼうぎょ」していない時も
防御力が1/2になってしまいます。
なので、最初の防御力を入れることで防御力を元に戻します。
これなら戦闘開始時や「ぼうぎょ」していなくても影響ありません。 

 

        elif idx == 11: # プレイヤーのターン(入力待ち)
            player.re_defense() # ぼうぎょを元に戻す
            print(f"ターン開始時:{player.dfs}")
            ### 結果 → ターン開始時:10 ###
(省略)
        elif idx == 18: # ぼうぎょ
            draw_battle(screen, fontS)
            if tmr == 1:
                player.defense()
                set_message(player.name + "は みをまもっている!")
                print(f"ぼうぎょ時:{player.dfs}")
                ### 結果 → ぼうぎょ時:20 ###

 

 

こうげきのダメージ計算

「ぼうぎょ」を選択できるようになりました。
ただ、先程はサラッと記載しましたが、防御力の変数は今まで使っていませんでした。
つまり防御力が2倍になったところで、受けるダメージが半減するわけではありません。
それは攻撃のダメージ計算が以下のようになっている為です。

        elif idx == 12: # プレイヤーの攻撃
            draw_battle(screen, fontS)
            if tmr == 1:
                set_message(player.name + " の攻撃!")
                # se[0].play()
                dmg = player.atk + random.randint(0, 9) # ダメージ計算

dmg = player.atk + random.randint(0, 9)
→攻撃力 + ランダム(0〜9)
なので、防御力を考慮したダメージ計算に変更します。

ダメージ計算はこちらを利用させて頂きました。

基本ダメージ = (自分の攻撃力 - 相手の守備力 / 2) / 2
乱数幅 = 基本ダメージ/16 + 1
実ダメージ = 基本ダメージ ± 乱数幅内で生成された乱数

というわけで、これを計算する関数を「one_hour_dungeon.py」に作りました。

def battle_cal(obj1, obj2): # コマンドの入力と表示
    base_dmg = obj1.atk/2 - obj2.dfs/4
    if base_dmg <= 0: # 基本ダメージが0以下の(防御力の方が圧倒的に大きい)場合、ダメージは0か1
        return random.randint(0, 1)
    width_dmg = base_dmg/16 + 1
    min_dmg = int(base_dmg - width_dmg) # 最小値
    max_dmg = int(base_dmg + width_dmg) # 最大値
    print(f"{min_dmg} 〜 {max_dmg}")
    # 結果 攻撃力:1000,防御力:15の時 → 464 〜 528
    return random.randint(min_dmg, max_dmg) # min_dmg〜max_dmgのランダム値

2つのオブジェクトを引数に持ちます。
obj1が攻撃する側、obj2が攻撃される側です。
戻り値をmin_dmg〜max_dmgの範囲のランダム値にして、
これをダメージとして取得します。
また、防御力の方が圧倒的に大きい場合のダメージは0か1にしました。

このbattle_cal関数をプレイヤーの攻撃時とモンスターの攻撃時に呼び出します。

        elif idx == 12: # プレイヤーの攻撃
            draw_battle(screen, fontS)
            if tmr == 1:
                set_message(player.name + " の攻撃!")
                # se[0].play()
                # dmg = player.atk + random.randint(0, 9) (削除)
                dmg = battle_cal(player, monster) # 追加
(省略)
        elif idx == 13: # モンスターのターン、攻撃
            draw_battle(screen, fontS)
            if tmr == 1:
                set_message(monster.name + " のターン")
            if tmr == 5:
                set_message(monster.name + " の攻撃!")
                # se[0].play()
                emy_step = 30
            if tmr == 9:
                # dmg = monster.atk + random.randint(0, 9) (削除)
                dmg = battle_cal(monster, player) # 追加

これで防御力も考慮した攻撃ができるようになりました。
モンスターの攻撃もオブジェクトを入れ替えるだけです。

なお、プレイヤーの防御力の変数は作っていましたが、
モンスター側は作っていなかったので、作っておきます。

(chara.py)
mon_atk = ws_mon.col_values(8) # H列
mon_dfs = ws_mon.col_values(9) # I列 追加(スプレッドシートのI列に防御力のステータスを追加)

class Monster():
    def __init__(self, num):
        self.img = pygame.image.load("image/enemy"+str(num)+".png")
        self.name = mon_name[num]
        self.maxhp = int(mon_maxhp[num])
        self.hp = self.maxhp
        self.atk = int(mon_atk[num])
        self.dfs = int(mon_dfs[num]) # 追加

 

最後にもう1つ、ダメージが「0」の時はメッセージを変えます。

        elif idx == 12: # プレイヤーの攻撃
            draw_battle(screen, fontS)
            if tmr == 1:
                set_message(player.name + " の攻撃!")
                # se[0].play()
                dmg = battle_cal(player, monster)
            if 2 <= tmr and tmr <= 4:
                screen.blit(imgEffect[0], [600-tmr*100, tmr*100])
            if tmr == 5:
                emy_blink = 5
                ###追加###
                if dmg > 0:
                    set_message(monster.name + "に " + str(dmg)+"ポイントの ダメージ!!")
                else:
                    set_message("ミス!" + monster.name + "に ダメージを あたえられない!")
(省略)
        elif idx == 13: # 敵のターン、敵の攻撃
            draw_battle(screen, fontS)
            if tmr == 1:
                set_message(monster.name + " のターン")
            if tmr == 5:
                set_message(monster.name + " の攻撃!")
                # se[0].play()
                emy_step = 30
            if tmr == 9:
                dmg = battle_cal(monster, player)
                ###追加###
                if dmg > 0:
                    set_message(player.name + "は " + str(dmg) + "ポイントの ダメージを うけた!")
                else:
                    set_message("ミス!" + player.name + " は ダメージを うけない!")

 

という感じで、今回は以上です!(`・ω・´)

 

 

最後に

今回は「ぼうぎょ」コマンドを選択できるようにしたことと
それに伴い防御力を考慮したダメージ計算に変更しました。

次回はコマンドの選択はいったん置いておいて、
コマンド表示の時、その横にモンスターの名前を表示させようと思います。

まとめサイトへ

 

 

【ご注意】
プログラムやデータなどは著作権法により保護されています。
著作者の許諾を得ずに、プログラムおよびデータそのものまたは改変したものを
配布したり販売したりすることはできません。
また、これらを利用して発生した損害などに関して、著作者は一切責任を負いません。

 

 

-CODE, Python, RPG
-, , , , ,

Copyright© kerublog , 2021 All Rights Reserved Powered by STINGER.