CODE Python RPG

独学でPythonでRPGを作成する(第63回)動けないキャラの扱い

投稿日:

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

前回はmessege.pyを利用して少しプログラムの構成を変更・修正しました。

今回は細かい修正を加えていきます。
動けないキャラがいるときの動作や移動中に味方全員への呪文を使えるようにするなどです。

目次

  1. 動けないキャラ
  2. 「▶」の表示
  3. 味方全員への呪文
  4. 戦闘コマンド
  5. 最後に

動けないキャラ

動けないキャラがいるときの
動作を修正します。

動けないとはHPが0のキャラです。

今後、他にも毒や麻痺などの
ステータスも加えたいと思っています。

各ステータスによって、
使用した呪文が効果のある・なしの
動作も加えようと思います。
※そのうち。

 

今回はHPが0のキャラは
呪文が使えない、
また、HPが0のキャラに
回復呪文を使っても
効果がないようにします。

※move.pyです。

def draw_para(bg, fnt, player): # 主人公の能力を表示
(省略)

    if spell_flag[0]: # コマンドで「じゅもん」が選択された
(省略)

        if spell_flag[1]: # 使用者が選択された(選択されたプレイヤーの添字:sel_p_y[0])
            if player[sel_p_y[0]].hp == 0:
                if not spell_flag[4]:
                    msg = message.set_message(player[sel_p_y[0]].name + "は 気絶している!", msg)
                    spell_flag[4] = True
            elif len(player[sel_p_y[0]].mas_move_spell) == 0: # 移動中の呪文を覚えていないなら
                if not spell_flag[4]:
                    msg = message.set_message(player[sel_p_y[0]].name + "は 移動中の呪文を覚えていない", msg)
                    spell_flag[4] = True

 

if player[sel_p_y[0]].hp == 0:
    if not spell_flag[4]:
        msg = message.set_message(player[sel_p_y[0]].name + "は 気絶している!", msg)
        spell_flag[4] = True

を追加しています。
HPが0のキャラは
呪文を使えないようにしました。

 

呪文を使用する対象キャラの
HPが0のときも
効果がないようにします。

def draw_para(bg, fnt, player): # 主人公の能力を表示
(省略)

    if spell_flag[0]: # コマンドで「じゅもん」が選択された
(省略)

        elif spell_flag[3]: # 呪文発動
            if not spell_flag[4]:
                if player[sel_p_y[2]].hp == 0:
                    msg = message.set_message("しかし なにも おこらなかった", msg)

 

if player[sel_p_y[2]].hp == 0:
    msg = message.set_message("しかし なにも おこらなかった", msg)

を追加しました。
ただ、ここはまた後で
もう少し修正します。

 

 

「▶」の表示

「▶」の表示で
呪文を使った後も
「だれに」の「▶」が
点滅するので修正します。

呪文を使った後も赤枠の「▶」が
点滅するので、
使った後は点滅しないようにします。

 

def draw_para(bg, fnt, player): # 主人公の能力を表示
(省略)

        if spell_flag[1]: # 使用者が選択された(選択されたプレイヤーの添字:sel_p_y[0])
(省略)

            else: # 呪文の選択画面
(省略)

                if spell_flag[2]: # 呪文が選択された(選択された呪文の添字:sel_p_y[1]) 対象の選択
                    if player[sel_p_y[0]].check_mp(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]]) or spell_flag[3]: # mpが足りている もしくは 呪文発動している
                        spell_target_no = chara.get_spell_target(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]])
                        if spell_target_no == 0: # ターゲットが味方単体の場合
                            message.draw_frame_sel_t(bg, col, player)
                            draw_text(bg, "だれに", x_c_i_t+x_c_w*1.5, y_c_i_t, fnt, col)
                            for i, p in enumerate(player):
                                draw_text(bg, p.name, x_c_i_t+x_c_w*1.5, y_c_i_t+(i+1)*50, fnt, col) # i=0は「だれに」
                            if spell_flag[3]: # 呪文発動したら常にターゲットの左に▶︎
                                draw_text(bg, "▶︎", x_c_i_t-50+x_c_w*1.5, y_c_i_t+(sel_p_y[2]+1)*50, fnt, col) # 呪文選択中は呪文の左に▶︎を点滅(+1はだれに)
                            else:
                                if tmr%5 != 0:
                                    draw_text(bg, "▶︎", x_c_i_t-50+x_c_w*1.5, y_c_i_t+(sel_p_y[2]+1)*50, fnt, col) # 呪文選択中は呪文の左に▶︎を点滅(+1はだれに)
                        elif spell_target_no == 1: # ターゲットが味方全員
                            spell_flag[3] = True # 呪文発動
                        draw_text(bg, "▶︎", x_c_i_t-50+x_c_w, y_c_i_t+(sel_p_y[1])*50, fnt, col) # 呪文を選択した後は常に呪文の左に▶︎

 

if player[sel_p_y[0]].check_mp(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]]) or spell_flag[3]:

でspell_flag[3]の条件を追加しています。
※呪文を使ったことで
 MPが0になることもあります。
 MPが0だとここがFalseになるので
 spell_flag[3]の条件を追加しました。

if spell_flag[3]: # 呪文発動したら常にターゲットの左に▶︎
    draw_text(bg, "▶︎", x_c_i_t-50+x_c_w*1.5, y_c_i_t+(sel_p_y[2]+1)*50, fnt, col) 
else:
    if tmr%5 != 0:
        draw_text(bg, "▶︎", x_c_i_t-50+x_c_w*1.5, y_c_i_t+(sel_p_y[2]+1)*50, fnt, col)

呪文を使った後は「▶」を常に表示、
そうでない場合は点滅します。

 

なお、spell_target_noですが
ここで確認するようにしました。

spell_target_noの値
0:味方単体
1:味方全員
2:敵単体
3:敵グループ
4:敵全体

spell_target_no = chara.get_spell_target(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]])

後述しますが、味方全員に
使う呪文を利用できるように
する為です。

elif spell_target_no == 1: # ターゲットが味方全員
    spell_flag[3] = True # 呪文発動

味方全員に使う場合は
対象を選択する必要が無い為
ここでspell_flag[3]をTrueにして
呪文を使ったことにします。

 

 

味方全員への呪文

移動中は味方一人のみでしたが、
味方全員への呪文も使えるようにします。

 

 

判定位置の変更

先に、spell_flag[3]とspell_flag[4]の
判定の位置を入れ替えます。
※spell_flag[4]は前々回追加しました。
※これがTrueの時に
 「a」や「b」を押下すると
 メッセージ枠を閉じます。

変更前

def draw_para(bg, fnt, player): # 主人公の能力を表示
(省略)

        if spell_flag[3]: # 呪文発動
            if not spell_flag[4]:
(省略)
        
        if spell_flag[4]:
            x_m_i_t, y_m_i_t = message.draw_frame_mes(bg, col)
            for i in range(5): # 移動メッセージの表示
                draw_text(bg, "{}".format(msg[i]), x_m_i_t, y_m_i_t+i*40, fnt, col)

変更後

def draw_para(bg, fnt, player): # 主人公の能力を表示
(省略)

        if spell_flag[4]:
            x_m_i_t, y_m_i_t = message.draw_frame_mes(bg, col)
            for i in range(5): # 移動メッセージの表示
                draw_text(bg, "{}".format(msg[i]), x_m_i_t, y_m_i_t+i*40, fnt, col)

        elif spell_flag[3]: # 呪文発動

 

「if spell_flag[4]:」を
「if spell_flag[3]:」の
前にして、
「elif spell_flag[3]:」に
しました。

「if not spell_flag[4]:」が
不要になる為です。

 

 

呪文を使う

では、味方全員へ呪文を
使えるようにします。

 

変更前

def draw_para(bg, fnt, player): # 主人公の能力を表示
(省略)

        if spell_flag[3]: # 呪文発動
            # 使う:player[sel_p_y[0]]
            # 呪文:player[sel_p_y[0]].mas_move_spell[sel_p_y[1]]
            # 対象:player[sel_p_y[2]]
            if not spell_flag[4]:
                spell_target_no = chara.get_spell_target(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]])
                spell_point, spell_message = player[sel_p_y[0]].use_spell(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]], player[sel_p_y[2]], spell_target_no)
                msg = message.set_message(player[sel_p_y[0]].name + "は " + player[sel_p_y[0]].mas_move_spell[sel_p_y[1]] + " を となえた!", msg)
                msg = message.set_message(spell_message, msg)
                if spell_point != -1: # 回復系、-1は補助系
                    (省略 回復)
                spell_flag[4] = True

変更後

def draw_para(bg, fnt, player): # 主人公の能力を表示
(省略)

        elif spell_flag[3]: # 呪文発動
            # 使う:player[sel_p_y[0]]
            # 呪文:player[sel_p_y[0]].mas_move_spell[sel_p_y[1]]
            # 対象:player[sel_p_y[2]]
            msg = message.set_message(player[sel_p_y[0]].name + "は " + player[sel_p_y[0]].mas_move_spell[sel_p_y[1]] + " を となえた!", msg)
            player[sel_p_y[0]].consume_mp(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]])
            if spell_target_no == 0:
                if player[sel_p_y[2]].hp == 0:
                    msg = message.set_message("しかし なにも おこらなかった", msg)
                else:
                    spell_point, spell_message = player[sel_p_y[0]].use_spell(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]], player[sel_p_y[2]], spell_target_no)
                    msg = message.set_message(spell_message, msg)
                    if spell_point != -1: # 回復系、-1は補助系
                        (省略 回復)
            elif spell_target_no == 1:
                for i, p in enumerate(player):
                    if p.hp == 0:
                        continue
                    spell_point, spell_message = player[sel_p_y[0]].use_spell(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]], p, spell_target_no)
                    if spell_point != -1: # 回復系、-1は補助系
                        p.hp += spell_point
                        if p.hp > p.maxhp:
                            p.hp = p.maxhp
                msg = message.set_message("全員 の キズが かいふくした!", msg)
            spell_flag[4] = True

 

spell_target_no = chara.get_spell_target(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]])

前述の通り、spell_target_noの確認位置を
変えたのでここでは削除しています。

 

if spell_target_no == 0:
    if player[sel_p_y[2]].hp == 0:
        msg = message.set_message("しかし なにも おこらなかった", msg)

前述の通り、HPが0のキャラには
回復呪文は使えません。

 

player[sel_p_y[0]].consume_mp(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]])

前後しますが、
新しくconsume_mpメソッドを
追加します。
※後程、chara.pyに追加します。

mp消費を計算するメソッドです。

今まではuse_spellメソッドで
計算していましたが、
効果が無くてもmpを消費するようにする為
切り離しました。

 

elif spell_target_no == 1:
で味方全員への呪文を使います。

if p.hp == 0:
    continue

HPが0のキャラは無効です。

あとは一人ずつuse_spellメソッドを
使って、回復量を決めて
回復していきます。

 

なお、動けないキャラは
呪文の効果がないようにしましたが、
動けないキャラにしか効果がない呪文も
追加しようと思います。

生き返らせる呪文などはHPが0でないと
意味がないですが、現状の判定だと
この呪文も弾いてしまうので
修正が必要になります。

が、生き返らせる呪文を追加するときに
修正します。(今後です)

 

 

consume_mp

前述したconsume_mpを
chara.pyに追加します。

変更前

class Chara():
(省略)

    def use_spell(self, str_spell, target, spell_target_no):
        self.mp -= spell_usemp_dict[str_spell] # 消費mp

変更後

class Chara():
(省略)

    def consume_mp(self, str_spell):
        self.mp -= spell_usemp_dict[str_spell] # 消費mp
    def use_spell(self, str_spell, target, spell_target_no):

 

MPの消費を
consume_mpメソッドに
切り離したのみです。

 

あと、use_spellメソッドを変えたので
battle.pyも修正しておきます。
※1行追加。

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

        elif idx == 26: # 呪文発動
(省略)
            if tmr == 8:
                if turn_obj.check_mp(turn_obj.spell): # mpが足りていたら
                    turn_obj.consume_mp(turn_obj.spell) # 追加

 

味方全員への呪文については以上です。

 

 

戦闘コマンド

ここでは話を変えて
戦闘中のコマンドについて
修正します。

キャンセルしたときに
HPが0のキャラが
コマンド選択できてしまうので
修正します。

HPが0であったり
眠っていたりしたら
コマンド選択はできないように
しています。

※battle.pyです。

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

        elif idx == 11: # プレイヤーのターン(入力待ち)
(省略)

            # 眠っていないならコマンド選択 眠っているとactは28にセットされている
            if player[btl_player].hp == 0 or player[btl_player].flag_sleep:
                idx = 23

HPが0もしくは眠っている場合
コマンド選択せずに次のキャラへ(idx=23)

 

ただ、コマンド選択した後に
「b」キーでキャンセルした時に
HPが0のキャラに戻ってしまいます。

キャラ1:生存
キャラ2:生存
キャラ3:生存していない
キャラ4:生存

の場合、
キャラ2がコマンド選択すると
キャラ3はHP0なので
キャラ4のコマンド選択に移りますが
この時に「b」キーでキャンセルすると
キャラ3に移ってしまいます。

なので、キャンセルの時も
動けないキャラは飛ばすようにします。

def battle_command(key, player): # コマンドの入力と表示
(省略)

    elif key[K_b]: # キャンセル
        tmp = btl_player # コマンド選択中のキャラ(playerのインデックス)
        while tmp > 0:
            tmp -= 1
            if player[tmp].hp != 0 and not player[tmp].flag_sleep: # 生存 かつ 眠っていないなら戻る
                btl_player = tmp
                break

(省略)

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

        elif idx == 11: # プレイヤーのターン(入力待ち)
(省略)

            else:
                draw_battle(screen, fontS, turn_obj, player)
                if battle_command(key, player) == True:

 

tmp = btl_player
    while tmp > 0:
        tmp -= 1
            if player[tmp].hp != 0 and not player[tmp].flag_sleep:
                btl_player = tmp
                break

キャンセルした時に
前に動けるキャラがいるなら
戻れるようにしています。

また、各キャラの状態を確認する必要がある為
引数にplayerを追加しています。

 

ちなみに移動中の時に
眠っているというステータスは無いので
move.pyではflag_sleepの判定は
省いています。

今後、移動中も影響のある
麻痺などのステータスを追加した時は
判定に追加しようと思います。

battle.py(戦闘終了時)

        elif idx == 22: # 戦闘終了
            idx = 1
            monster.clear() # モンスターオブジェクトを削除
            dead_monster.clear()
            btl_exp = 0
            btl_player = 0 # 二人目以降で逃げた時に必要
            for p in player:
                p.spell_reset() # 呪文効果をリセット
            return 1

chara.py(戦闘終了後、眠り効果を消す)

    def spell_reset(self):
        self.invalid_sukara()
        self.invalid_rukani()
        self.check_dfs()
        self.turn_baikiruto = 0 # バイキルトの残りターン
        self.turn_henatos = 0 # ヘナトスの残りターン
        self.atk = self.get_atk() # 攻撃力を元に戻す
        self.invalid_manusa() # マヌーサの効果を消す
        self.invalid_sleep() # ラリホー、ラリホーマの効果を消す

 

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

 

 

最後に

今回は動けないキャラがいるときの動作や
移動中に味方全員への呪文を使えるようにするなどの
変更・修正をしました。

次回もまた何かを修正したいと思います。

まとめサイトへ

 

 

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

 

 

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

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