CODE Python RPG

独学でPythonでRPGを作成する(第35回)補助系の呪文を変更

更新日:

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

前回は補助系の呪文(スカラ)を追加しました。

今回は前回追加した呪文(スカラ)の計算方法や戦闘メッセージの作成場所などを変更します。
※スカラの説明はこちら

目次

  1. charaの変更
  2. battleの変更
  3. 最後に

charaの変更

chara.pyから変更します。

最初に変数を変えます。

変更前

(省略)
        self.turn_sukara = 0 # スカラの有効ターン
        self.dfs_up = [1, 1] # dfs_up[0]:ぼうぎょ効果,dfs_up[1]:呪文効果

変更後

(省略)
        self.use_defense = False # コマンド「ぼうぎょ」を使っているか
        self.turn_sukara = 0 # スカラの有効ターン
        self.num_sukara = 0 # スカラを使った回数

リストdfs_upをやめて
変数を2つに分けました。

self.use_defense = False # コマンド「ぼうぎょ」を使っているか
self.num_sukara = 0 # スカラを使った回数

「ぼうぎょ」を使っているか

スカラの回数です。

有効ターン内にスカラを何回使ったかです。
有効ターンが終わると、何回使っていても
0回に戻ります。

 

 

防御力の計算

今の防御力を計算する
メソッドcheck_dfsを変更します。

変更前

class Chara():
(省略)

    def defense(self): # ぼうぎょ
        self.dfs_up[0] *= 2
        self.dfs *= self.dfs_up[0]
    def invalid_defense(self): # ぼうぎょ無効(ターン終了)
        self.dfs_up[0] = 1
    def check_dfs(self): # 防御力計算
        self.re_defense()
        for i in self.dfs_up:
            self.dfs *= i
        self.dfs = int(self.dfs)
        if self.dfs > 999:
            self.dfs = 999

変更後

class Chara():
(省略)

    def check_dfs(self): # 防御力計算
        self.dfs = self.get_dfs() # 元に戻す
        # 元々の守備力*0.5を追加
        self.dfs += int(0.5 * self.get_dfs()) * self.num_sukara # スカラ効果 アップした数字をメッセージに出す為、アップする数字にint
        tmp = self.dfs
        if self.use_defense: # 「ぼうぎょ」
            self.dfs *= 2
        if self.dfs > 999:
            self.dfs = 999
        return tmp # ぼうぎょする前の防御力を返す(ぼうぎょする前の防御力で1000未満か判定)
(省略)

class Brave(Chara):
(省略)

    def get_dfs(self):
        return int(chara1_dfs[self.lv])

 

check_dfsの中で防御力を
いったん元に戻してから
効果を追加していきます。

self.dfs = self.get_dfs() # 元に戻す
    def get_dfs(self):
        return int(chara1_dfs[self.lv])

 

元の防御力を取得するメソッドget_dfsで
今のレベルの防御力を取得します。

 

その後にスカラ効果を追加します。
スカラを1回使うごとに元の防御力の
半分を追加していきます。
※1回使う:1.5倍(1 + 0.5*1)
 2回使う:2倍(1 + 0.5*2)
 3回使う:2.5倍(1 + 0.5*3)

self.dfs += int(0.5 * self.get_dfs()) * self.num_sukara

 

後述しますが、スカラ効果の
戦闘メッセージを変える為に
コマンド「ぼうぎょ」する前の
値を返します。

return tmp # ぼうぎょする前の防御力を返す(ぼうぎょする前の防御力で1000未満か判定)

 

防御力の計算は以上です。

 

 

スカラの変更

sukaraメソッドを変更します。

変更前

class Chara():
(省略)

    def sukara(self, target):
        target.turn_sukara = random.randint(3, 4)
        target.dfs = int(1.5 * target.dfs) # 現在の防御力に1.5倍(re_defenseを使って元に戻すと「ぼうぎょ」も無効になってしまう)
        target.dfs_up[1] = 1.5 * target.dfs_up[1] # 現在のスカラの効果
    def invalid_sukara(self):
        self.dfs_up[1] = 1

変更後

class Chara():
(省略)

    def sukara(self, target):
        target.num_sukara += 1 # スカラ継続中に使った回数 現在のスカラの効果(元の防御力*0.5 をnum_sukara倍して、元の防御力にプラスする)
        target.turn_sukara = random.randint(4, 5) # 効果の残りターン
        tmp = target.check_dfs()
        return tmp # ぼうぎょする前の防御力を返す
    def invalid_sukara(self):
        self.turn_sukara = 0 # 戦闘の最後に元に戻すため
        self.num_sukara = 0
(省略)

class Brave(Chara):
(省略)

    def reset(self):
        self.maxhp = int(chara1_maxhp[1])
        self.hp = self.maxhp
        self.mp = self.maxmp
        self.invalid_sukara() # 追加

 

変更前はsukaraメソッドの中で
防御力を増やしましたが
check_dfsメソッドの中で
増やすことにします。

sukaraメソッドの中では
スカラを使った回数と
効果の残りターンを変えます。

invalid_sukaraでスカラ効果を
消します。
※有効ターンを0にする

前回は忘れていましたが、
戦闘が終わった時にも効果を消す為
戦闘終了時にinvalid_sukaraを呼び出します。
※スカラ効果は次の戦闘には継続させません。

あと、resetメソッドに
invalid_sukaraに追加しておきます。
一応・・(^_^;)

 

 

呪文を使う

呪文を使う時のメソッドuse_spellを
変更します。

変更前

class Chara():
(省略)

    def use_spell(self, str_spell, num, target=""):
        if str_spell == "スカラ":
            self.sukara(target)
            return -1
        dmg = []
        for _ in range(num):
            dmg.append(random.randint(spell_lo_dict[str_spell], spell_up_dict[str_spell]))
        return dmg

変更後

class Chara():
(省略)

    def use_spell(self, str_spell, target, spell_target_no):
        # 戻り値が-1は状態変化の呪文
        if str_spell == "スカラ":
            tmp_dfs = self.sukara(target)
            if tmp_dfs < 1000: # ぼうぎょしていない状態で1000未満
                message = target.name + " の しゅびりょくが " + str(int(0.5 * target.get_dfs())) + "ふえた!"
            else:
                message = target.name + " の しゅびりょくが 最大になった!"
            return -1, message

        point = random.randint(spell_lo_dict[str_spell], spell_up_dict[str_spell])
        if spell_target_no == 0 or spell_target_no == 1:
            message = target.name + " の キズが かいふくした!"
        else:
            message = target.name + "に " + str(point) + "ポイントのダメージを与えた!"
        return point, message

 

呪文の戦闘メッセージは
battle.py側で作っていましたが
use_spellメソッドの中で
戦闘メッセージを作成することにしました。

なので、戻り値は2つにしました。

 

そして、スカラを使った時に
コマンド「ぼうぎょ」を使っていない状態で
1000より上か下かを判定するので
sukaraメソッドから「ぼうぎょ」前の守備力を受け取ります。

 

また、グループ攻撃用にダメージを
リストに入れていましたが、
リストを辞めました。

1回ごとにuse_spellメソッドを
呼び出してダメージを返します。
※後ほど、battle.pyを変更します。

なので、引数も少し変わっています。
num:グループのモンスター数(不要)
target:呪文を使う相手は必須
spell_target_no:
 0:味方単体、1:味方全員、2:単体、3:敵グループ、4:敵全体

 

chara.pyは以上です。

 

 

battleの変更

次にbattle.pyを変更します。

chara.pyの変数use_defenseや
メソッドcheck_dfsで
変えたところを変えます。

変更前

def main(screen, clock, font, fontS, player, area):
(省略)

        elif idx == 11: # プレイヤーのターン(入力待ち)
            btl_enemy = 0
            player.invalid_defense() # ぼうぎょを元に戻す(ぼうぎょ効果を消す)
            player.check_dfs()
(省略)

                if COMMAND[btl_cmd_y][btl_cmd_x] == "ぼうぎょ":
                    player.act = 18 # get_battle_turnの戻り値idxを18
                    player.defense() # 選択した時点で防御力2倍(ターンが回ってきてからではない)
                    idx = 23
                    tmr = 0

変更後

def main(screen, clock, font, fontS, player, area):
(省略)

    # spell_dmg = [] # 不要

        elif idx == 11: # プレイヤーのターン(入力待ち)
            btl_enemy = 0
            player.use_defense = False # ぼうぎょを元に戻す(ぼうぎょ効果を消す)
            player.check_dfs()
(省略)

                if COMMAND[btl_cmd_y][btl_cmd_x] == "ぼうぎょ":
                    player.act = 18 # get_battle_turnの戻り値idxを18
                    player.use_defense = True
                    player.check_dfs() # 選択した時点で防御力2倍(ターンが回ってきてからではない)
                    idx = 23
                    tmr = 0
(省略)

        elif idx == 22: # 戦闘終了
            idx = 1
            monster.clear() # モンスターオブジェクトを削除
            dead_monster.clear()
            btl_exp = 0
            player.invalid_sukara() # 追加
            return 1

リストspell_dmgは
辞めるので消します。

メソッドcheck_dfsで
防御力を計算するように変更したので
use_defenseの値を変えたら
check_dfsを呼び出して
防御力を計算します。

あと、戦闘が終わったら
スカラ効果は消すので
idx22でinvalid_sukaraを
呼び出します。
※次の戦闘にスカラ効果は
 継続させません。

 

次にuse_spellメソッドで
変えたところを変更します。

        elif idx == 26: # 呪文発動
            draw_battle(screen, fontS, turn_obj, player)
(省略)

                    spell_target_no = turn_obj.get_spell_target(turn_obj.mas_spell[sel_spell_i])
                    if spell_target_no == 0: # 呪文の対象が味方単体
                        spell_dmg = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], 1, player)
                        if spell_dmg != -1:
                            player.hp += spell_dmg[0] # 単体なので添字は0
                            if player.hp > player.maxhp:
                                player.hp = player.maxhp
                            set_message(player.name + " の キズが かいふくした!")
                        else:
                            set_message(player.name + " の 守備力が上がった!")

変更後

        elif idx == 26: # 呪文発動
            draw_battle(screen, fontS, turn_obj, player)
            
            spell_point = 0 # プレイヤーが与えるダメージ、受けるダメージ 呪文用
(省略)

                if turn_obj.check_mp(turn_obj.mas_spell[sel_spell_i]): # mpが足りていたら
                    spell_target_no = turn_obj.get_spell_target(turn_obj.mas_spell[sel_spell_i]) # 呪文の対象(0:味方単体,1:味方全員,2:敵単体,3:敵グループ,4:敵全体)
                    if spell_target_no == 0: # 呪文の対象が味方単体
                        spell_point, spell_message = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], player, spell_target_no)
                        if spell_point != -1: # 回復系
                            player.hp += spell_point
                            if player.hp > player.maxhp:
                                player.hp = player.maxhp
                        set_message(spell_message)

リストspell_dmgの代わりの
変数spell_pointを用意します。
※回復にも使うのでdmgではなく
 pointにしました(^_^;)

use_spellを使って、
spell_pointの値と
戦闘メッセージを受け取ります。

spell_pointが-1ではない時(補助系)は
戦闘メッセージを表示するのみです。
※use_spellの中で防御力を変更済

 

残りです。
※呪文の対象が2:単体、3:敵グループ、4:敵全体

変更前

                    elif spell_target_no == 2: # 呪文の対象がモンスター単体
                        spell_dmg = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], 1)
                        set_message(monster[spell_target_i].name + "に " + str(spell_dmg[0])+"ポイントのダメージを与えた!")
                        btl_exp += do_attack(spell_target_i, spell_dmg[0], turn_obj)
                        check_monster()
                    elif spell_target_no == 3: # 呪文の対象がモンスターグループ
                        # 呪文の対象のモンスターNoを取得(list_typに格納する)して、対象モンスターNoの数を取得する→ dic_typ[list_typ[spell_target_i]]
                        dic_typ, list_typ = mon_overlap() # 例{9:1、1:1}、[9, 1]
                        spell_dmg = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], dic_typ[list_typ[spell_target_i]]) # dic_typのvalueを使う、list_typ[spell_target_i]はキー(モンスターNo)
                        j = 0
                        for i, mon in enumerate(monster):
                            if mon.num == list_typ[spell_target_i]:
                                set_message(mon.name + "に " + str(spell_dmg[j])+"ポイントのダメージを与えた!")
                                btl_exp += do_attack(i, spell_dmg[j], turn_obj)
                                draw_battle(screen, fontS, turn_obj, player)
                                pygame.display.update()
                                time.sleep(1)
                                j += 1
                        check_monster()
                    elif spell_target_no == 4: # 呪文の対象がモンスター全体
                        spell_dmg = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], len(monster)) # dic_typのvalueを使う、list_typ[spell_target_i]はキー(モンスターNo)
                        j = 0
                        for i, mon in enumerate(monster):
                            set_message(mon.name + "に " + str(spell_dmg[j])+"ポイントのダメージを与えた!")
                            btl_exp += do_attack(i, spell_dmg[j], turn_obj)
                            draw_battle(screen, fontS, turn_obj, player)
                            pygame.display.update()
                            time.sleep(1)
                            j += 1
                        check_monster()

変更後

                    elif spell_target_no == 2: # 呪文の対象がモンスター単体
                        spell_point, spell_message = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], monster[spell_target_i], spell_target_no)
                        if spell_point != -1: # 攻撃系
                            btl_exp += do_attack(spell_target_i, spell_point, turn_obj)
                        set_message(spell_message)
                        check_monster()
                    elif spell_target_no == 3: # 呪文の対象がモンスターグループ
                        list_typ = mon_overlap() # [9, 1]
                        for i, mon in enumerate(monster):
                            if mon.num == list_typ[spell_target_i]:
                                spell_point, spell_message = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], mon, spell_target_no)
                                set_message(spell_message)
                                if spell_point != -1: # 攻撃系
                                    btl_exp += do_attack(i, spell_point, turn_obj)
                                draw_battle(screen, fontS, turn_obj, player)
                                pygame.display.update()
                                time.sleep(1)
                        check_monster()
                    elif spell_target_no == 4: # 呪文の対象がモンスター全体
                        for i, mon in enumerate(monster):
                            spell_point, spell_message = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], mon, spell_target_no)
                            set_message(spell_message)
                            btl_exp += do_attack(i, spell_point, turn_obj)
                            draw_battle(screen, fontS, turn_obj, player)
                            pygame.display.update()
                            time.sleep(1)
                        check_monster()

 

対象がモンスター単体の時も
spell_pointが-1か確認します。

今はまだありませんが、
モンスターの守備力を下げるなど
攻撃系の補助呪文の時の為です。

if spell_point != -1

 

対象がモンスターグループの時ですが
mon_overlapの引数を一つにしました。

use_spellの引数にモンスターグループに
何匹のモンスターがいるか(num)が
不要になった為です。

ので、mon_overlapからはグループの
モンスターのNoのみを取得します。
mon_overlapの変更は後ほど。

そして、use_spellをfor文の中で使います。
※for文の中で使うのでリストspell_dmgを
 辞めました。

対象がモンスター全体の場合もほぼ同じです。

 

最後にmon_overlapの変更です。

変更後

def mon_overlap():
    # 呪文の対象のモンスターNoを取得(list_typに格納する)
    mon_no = [] # モンスターNoを格納
    for mon in monster: # 既にfor文の中であり、monを使っているので、ここでmonは使えない
        mon_no.append(mon.num)
    dic_typ = collections.Counter(mon_no) # 重複を抽出(倒すとmonsterが変わるので毎回取得) 例{9:1、1:1}
    list_typ = list(dic_typ.keys()) # キーをリストで取得(キーがモンスターNo)list_typ[0]=9,list_typ[1]=1
    return list_typ
(省略)

def draw_battle(bg, fnt, obj, player): # 戦闘画面の描画 obj:戦闘で行動中のオブジェクト
(省略)

                    elif player.get_spell_target(player.mas_spell[sel_spell_i]) == 3: # 呪文の対象がモンスターグループ
                        list_typ = mon_overlap() # [9, 1]

単純にdic_typを消しただけです。

関数draw_battleのところでは
元々、dic_typを使っていないので
こちらも消しただけです。

 

 

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

 

 

最後に

今回は前回追加したスカラの計算方法を
変えただけになりました(^_^;)

次回はモンスターに使う補助系の呪文を追加したいと思います。

まとめサイトへ

 

 

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

 

 

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

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