CODE Python RPG

独学でPythonでRPGを作成する(第60回)移動中に呪文を使う

投稿日:

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

前回は移動中のコマンド「じゅもん」を選択したら
覚えている呪文が表示されるようにしました。

今回はその呪文を使えるようにします。

目次

  1. 変数の変更
  2. 「▶」の位置
  3. 決定・取消
  4. 対象者の表示
  5. 呪文を使う
  6. 最後に

変数の変更

今回はmove.pyのみ変更します。

最初にグローバル変数を追加します。

import chara

DELAY_SPEED = 500 # 止める時間(ms)

spell_flag = [False, False, False, False] # フィールドで呪文画面を表示するか [true:呪文の使用者選択、true:呪文の選択、true:呪文の対象選択、true:呪文発動]
sel_p_y = [0, 0, 0] # コマンドのじゅもん選択時の"▶︎"のy位置(横には動かない)
import chara

呪文を使う時に
chara.pyの関数を
利用する為
importします。

DELAY_SPEED = 500

は呪文を使った後、
文字を一定時間(500ms)、
表示させておく為に使います。

spell_flag = [False, False, False, False]

は要素を1つ追加しました。
spell_flag[3]がTrueになったら
呪文を使います。

sel_p_y = [0, 0, 0]

は変更していません。

 

前回の続きで
以下のような感じにします。

spell_flag = [True, True, True, False]
 使う呪文を選択済
 呪文の対象者を選択中(▶は点滅)

 

 

「▶」の位置

前回と同様に
上下キーを
押下することで「▶」の位置を
変更します。

変更前

def move_player(key, player, people): # 主人公の移動
(省略)

    if not talk_flag: # 会話中でない時は動ける、会話できる
        if key[K_UP] == 1:
            if cmd_flag: # コマンド選択中
                if spell_flag[0]: # コマンドのじゅもん選択時
                    if spell_flag[1]: # 呪文の選択画面
                        if sel_p_y[1] > 0:
                            sel_p_y[1] -= 1
                    else: # じゅもんの使用者選択時
                        if sel_p_y[0] > 0:
                            sel_p_y[0] -= 1
                else: # どれでもない時はコマンドを選択
                    if cmd_y > 0:
                        cmd_y -= 1
(省略)

変更後

def move_player(key, player, people): # 主人公の移動
(省略)

    if not talk_flag: # 会話中でない時は動ける、会話できる
        if key[K_UP] == 1:
            if cmd_flag: # コマンド選択中
                if spell_flag[0]: # コマンドのじゅもん選択時
                    if spell_flag[2]: # 対象者の選択中
                        if sel_p_y[2] > 0:
                            sel_p_y[2] -= 1
                    elif spell_flag[1]: # 呪文の選択画面
                        if sel_p_y[1] > 0:
                            sel_p_y[1] -= 1
                    else: # じゅもんの使用者選択時
                        if sel_p_y[0] > 0:
                            sel_p_y[0] -= 1
                else: # どれでもない時はコマンドを選択
                    if cmd_y > 0:
                        cmd_y -= 1
if spell_flag[2]: # 対象者の選択中
    if sel_p_y[2] > 0:
        sel_p_y[2] -= 1

を追加しています。
※前回と同じように
 spell_flagは後ろから確認します。
※対象者を選択中(spell_flag[2]がTrue)は
 使う呪文の位置(sel_p_y[1])や
 呪文の使用者の位置(sel_p_y[0])を
 変更できないようにする為です。

 

下(↓)キーを押下したときです。

変更後

def move_player(key, player, people): # 主人公の移動
(省略)

        elif key[K_DOWN] == 1:
            if cmd_flag: # コマンド選択中
                if spell_flag[0]: # コマンドのじゅもん選択時
                    if spell_flag[2]: # 対象者の選択中
                        if sel_p_y[2] < len(player)-1:
                            sel_p_y[2] += 1
                    elif spell_flag[1]: # 呪文の選択画面
                        if sel_p_y[1] < len(player[sel_p_y[0]].mas_move_spell)-1: # 選択されたプレイヤーが覚えている呪文の数
                            sel_p_y[1] += 1
                    else: # じゅもんの使用者選択時
                        if sel_p_y[0] < len(player)-1:
                            sel_p_y[0] += 1
                else: # どれでもない時はコマンドを選択
                    if cmd_y < 2:
                        cmd_y += 1
if spell_flag[2]: # 対象者の選択中
    if sel_p_y[2] < len(player)-1:
        sel_p_y[2] += 1

を追加しています。

 

 

決定・取消

決定(aキー)を変更します。

def move_player(key, player, people): # 主人公の移動
(省略)

        elif key[K_a] == 1:
            if cmd_flag: # コマンド選択中
                if not spell_flag[0]: # じゅもんが選択されていない
                    if cmd_x == 1 and cmd_y == 0: # じゅもんの位置でaを押下
                        spell_flag[0] = True # じゅもんを選択済、使用者を選択中
                elif not spell_flag[1]: # じゅもんが選択されていて、使用者が選択されていない
                    spell_flag[1] = True # 使用者を選択済、呪文を選択中
                elif not spell_flag[2]: # 使用者が選択されていて、呪文が選択されていない
                    spell_flag[2] = True # 呪文を選択済、対象者を選択中
                elif not spell_flag[3]: # 呪文発動
                    spell_flag[3] = True
elif not spell_flag[2]: # 使用者が選択されていて、呪文が選択されていない
    spell_flag[2] = True # 呪文を選択済、対象者を選択中
elif not spell_flag[3]: # 呪文発動
    spell_flag[3] = True

を追加しています。

elif not spell_flag[2]: # 使用者が選択されていて、呪文が選択されていない
    spell_flag[2] = True # 呪文を選択済、対象者を選択中

で、spell_flag = [True, True, True, False]
となります。

elif not spell_flag[3]: # 呪文発動
    spell_flag[3] = True

で、spell_flag = [True, True, True, True]
となります。
この時、呪文を使います。

 

取消(bキー)に
変更はありません。

def move_player(key, player, people): # 主人公の移動
(省略)

        elif key[K_b] == 1:
            if cmd_flag:
                if spell_flag[0]:
                    if spell_flag[2]:
                        spell_flag[2] = False
                        sel_p_y[2] = 0
                    elif spell_flag[1]:
                        spell_flag[1] = False
                        sel_p_y[1] = 0
                    else:
                        spell_flag[0] = False
                        sel_p_y[0] = 0

呪文を使ったら
(spell_flag[3]がTrue)
後戻りはできません。
※呪文を使ったことを
 取り消せません。

 

 

対象者の表示

呪文を使う対象者を表示します。
※「だれに」を表示

 

def draw_para(bg, fnt, player): # 主人公の能力を表示
    global cmd_flag, spell_flag, sel_p_y

グローバル変数の値を
変更するので追加します。

 

変更前

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

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

                draw_text(bg, "{}".format(player[sel_p_y[0]].name + "は 移動中の呪文を覚えていない"), x_i_t, y_i_t, fnt, col)
            else:
                y_c_h = 50 * len(player[sel_p_y[0]].mas_move_spell) + 30 # 50=30(枠内の開始位置or文字間隔)+20(文字の大きさ) 30=最後の間隔
                pygame.draw.rect(bg, BLACK, [x_c_i+x_c_w, y_c_i, x_c_w/2, y_c_h], 0, 5) # 枠
                pygame.draw.rect(bg, col, [x_c_i+x_c_w, y_c_i, x_c_w/2, y_c_h], 2, 5) # 枠
                pygame.draw.line(bg, col, [x_c_i+x_c_w, y_c_i+65], [x_c_i+x_c_w, y_c_i+65], 2) # 線 65=30(枠内の開始位置)+20(文字の大きさ)+15(文字間隔の半分)
                for i, s in enumerate(player[sel_p_y[0]].mas_move_spell): # 覚えている呪文を表示
                    draw_text(bg, s, x_c_i_t+cmd_x*x_c_w, y_c_i_t+i*50, fnt, col)

                draw_text(bg, "▶︎", x_c_i_t-50+x_c_w/2, y_c_i_t+(sel_p_y[0]+1)*50, fnt, col) # 呪文使用者を選択した後は常に名前の左に▶︎
                if tmr%5 != 0:
                    draw_text(bg, "▶︎", x_c_i_t-50+x_c_w, y_c_i_t+(sel_p_y[1])*50, fnt, col) # 呪文選択中は呪文の左に▶︎を点滅
        else:
            if tmr%5 != 0:
                draw_text(bg, "▶︎", x_c_i_t-50+x_c_w/2, y_c_i_t+(sel_p_y[0]+1)*50, fnt, col) # 呪文使用者を選択中は名前の左に▶︎を点滅

前回は覚えている呪文を
表示するところまででした。

変更後

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

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

                draw_text(bg, "{}".format(player[sel_p_y[0]].name + "は 移動中の呪文を覚えていない"), x_i_t, y_i_t, fnt, col)
            else: # 呪文の選択画面
                y_c_h = 50 * len(player[sel_p_y[0]].mas_move_spell) + 30 # 50=30(枠内の開始位置or文字間隔)+20(文字の大きさ) 30=最後の間隔
                pygame.draw.rect(bg, BLACK, [x_c_i+x_c_w, y_c_i, x_c_w/2, y_c_h], 0, 5) # 枠
                pygame.draw.rect(bg, col, [x_c_i+x_c_w, y_c_i, x_c_w/2, y_c_h], 2, 5) # 枠
                pygame.draw.line(bg, col, [x_c_i+x_c_w, y_c_i+65], [x_c_i+x_c_w, y_c_i+65], 2) # 線 65=30(枠内の開始位置)+20(文字の大きさ)+15(文字間隔の半分)
                for i, s in enumerate(player[sel_p_y[0]].mas_move_spell): # 覚えている呪文を表示
                    draw_text(bg, s, x_c_i_t+cmd_x*x_c_w, y_c_i_t+i*50, fnt, col)

                if spell_flag[2]: # 呪文が選択された(選択された呪文の添字:sel_p_y[1]) 対象の選択
                    y_c_h = 50 * (1+len(player)) + 30 # 高さ 1+は「だれに」 50=30(枠内の開始位置or文字間隔)+20(文字の大きさ) 30=最後の間隔
                    pygame.draw.rect(bg, BLACK, [x_c_i+x_c_w*1.5, y_c_i, x_c_w/2, y_c_h], 0, 5) # 枠
                    pygame.draw.rect(bg, col, [x_c_i+x_c_w*1.5, y_c_i, x_c_w/2, y_c_h], 2, 5) # 枠
                    pygame.draw.line(bg, col, [x_c_i+x_c_w*1.5, y_c_i+65], [x_c_i+x_c_w*2, y_c_i+65], 2) # 線 65=30(枠内の開始位置)+20(文字の大きさ)+15(文字間隔の半分)
                    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 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はだれに)
                    draw_text(bg, "▶︎", x_c_i_t-50+x_c_w, y_c_i_t+(sel_p_y[1])*50, fnt, col) # 呪文を選択した後は常に呪文の左に▶︎
                else:
                    if tmr%5 != 0:
                        draw_text(bg, "▶︎", x_c_i_t-50+x_c_w, y_c_i_t+(sel_p_y[1])*50, fnt, col) # 呪文選択中は呪文の左に▶︎を点滅
                draw_text(bg, "▶︎", x_c_i_t-50+x_c_w/2, y_c_i_t+(sel_p_y[0]+1)*50, fnt, col) # 呪文使用者を選択した後は常に名前の左に▶︎
        else:
            if tmr%5 != 0:
                draw_text(bg, "▶︎", x_c_i_t-50+x_c_w/2, y_c_i_t+(sel_p_y[0]+1)*50, fnt, col) # 呪文使用者を選択中は名前の左に▶︎を点滅(+1はじゅもん)
if spell_flag[2]:

以降を追加・変更しています。

「だれに」を表示します。

また、選択中の場合
「▶」は点滅させます。
※上図は静止画の為、
 消えているように見えますが
 「だれに」の「▶」は
 点滅しています。
※「じゅもん」と呪文は
 選択済みの為、
 「▶」は常に表示されています。

この辺りは
if tmr%5 != 0:
で制御しています。
※詳細はコメントで・・(^_^;)

 

 

呪文を使う

・呪文を使うキャラを選択して
・使う呪文を選択して
・対象のキャラを選択して
・呪文を使う
の流れなので、
対象のキャラまで選択したら
呪文を使います。

ちなみに各変数は以下になります。

呪文を使うキャラ:player[sel_p_y[0]]
・使う呪文:player[sel_p_y[0]].mas_move_spell[sel_p_y[1]]
・対象のキャラ:player[sel_p_y[2]]

変更後

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

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

        else:
            if tmr%5 != 0:
                draw_text(bg, "▶︎", x_c_i_t-50+x_c_w/2, y_c_i_t+(sel_p_y[0]+1)*50, fnt, col) # 呪文使用者を選択中は名前の左に▶︎を点滅(+1はじゅもん)

        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]]

            # 文字を表示する枠
            x_i = bg.get_width()*0.1/2 # x座標の開始位置
            x_w = bg.get_width()*0.9 # 横幅
            y_i = bg.get_height()*0.6 # y座標の開始位置
            y_h = bg.get_height()*0.4-10 # 高さ
            x_i_t = x_i + 30 # テキストのx座標の開始位置
            y_i_t = y_i + 30 # テキストのy座標の開始位置
            pygame.draw.rect(bg, BLACK, [x_i, y_i, x_w, y_h], 0, 5) # 枠
            pygame.draw.rect(bg, col, [x_i, y_i, x_w, y_h], 2, 5) # 枠

            if player[sel_p_y[0]].check_mp(player[sel_p_y[0]].mas_move_spell[sel_p_y[1]]): # mpが足りていたら
                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)
                draw_text(bg, f"{player[sel_p_y[0]].name}は {player[sel_p_y[0]].mas_move_spell[sel_p_y[1]]}を となえた!", x_i_t, y_i_t, fnt, col)
                draw_text(bg, f"{spell_message}", x_i_t, y_i_t+50, fnt, col)
                if spell_point != -1: # 回復系、-1は補助系
                    player[sel_p_y[2]].hp += spell_point
                    if player[sel_p_y[2]].hp > player[sel_p_y[2]].maxhp:
                        player[sel_p_y[2]].hp = player[sel_p_y[2]].maxhp
            else:
                draw_text(bg, "MPがたりない!", x_i_t, y_i_t, fnt, col)
            cmd_flag = False
            spell_flag = [False, False, False, False]
            sel_p_y = [0, 0, 0]
            pygame.display.update()
            pygame.time.delay(DELAY_SPEED)

if spell_flag[3]:
以降を追加しています。

呪文を使う時は
基本的にはbattle.pyと
同じです。

chara.pyの
check_mpメソッド
 →MPが足りているか確認
get_spell_target関数
 →対象を取得
use_spellメソッド
 →呪文を使う
としています。

get_spell_target関数は
0:味方単体
1:味方全員
2:モンスター単体
3:モンスターグループ
4:モンスター全体
のいずれかの値を取得しますが
移動中に攻撃呪文は利用しないので
0もしくは1を
取得することになります。

 

if spell_point != -1: # 回復系、-1は補助系
    player[sel_p_y[2]].hp += spell_point
    if player[sel_p_y[2]].hp > player[sel_p_y[2]].maxhp:
        player[sel_p_y[2]].hp = player[sel_p_y[2]].maxhp

HPを回復します。

味方単体だけでなく
味方全員に使う呪文も
使えるようにしたいと思います。
そのうち。。

また、使える呪文は
回復呪文のみですが
補助呪文も使えるように
したいと思います。
いずれ。。

 

cmd_flag = False
spell_flag = [False, False, False, False]
sel_p_y = [0, 0, 0]

呪文を使った後は
各変数を初期値に戻します。
※「はなす」「じゅもん」などの
 コマンド枠も消します。

 

pygame.display.update()
pygame.time.delay(DELAY_SPEED)

呪文を使った後に
文字を表示しますが
すぐに消えてしまう為
これを追加しています。

ただ、何となくあまり
良くない方法な気がするので
これも変えたいと思います。
いつか。。

 

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

 

 

最後に

今回は移動中のコマンド「じゅもん」で
呪文を使えるようにしました。

ただ、先述のような問題もありますし
他にも、呪文を覚えていないキャラを
選択したらエラーになったりします。

ので、次回ももう少し「じゅもん」を
修正したいと思います。

まとめサイトへ

 

 

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

 

 

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

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