CODE Python RPG

独学でPythonでRPGを作成する(第49回)移動中のコマンド

投稿日:

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

前回は町の宿屋に泊まれるようにしました(HPMPを全快にする)。

今回は前回までの会話から少し離れて、移動中のコマンドを表示するようにします。

目次

  1. コマンドとパラメータ
  2. moveの変更
  3. 宿屋
  4. 最後に

コマンドとパラメータ

移動中に前に人がいない場所で
「a」キーを押下すると
コマンドとパラメータを
表示するようにします。

※「b」キーを押下したら
 非表示にします。

  

今までのパラメータは削除します。

 

 

moveの変更

move.pyを変更します。

battle.pyと同じように
数字は全角で表示させたいので
モジュール「mojimoji」を
利用します。
戦闘コマンドの表示を変える

import mojimoji # 半角⇄全角変換

 

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

rest_flag = False # 寝る選択をしたかどうか #(前回追加)
cmd_flag = False # フィールドでコマンド画面を表示するか
cmd_x = 0 # コマンド選択の時の"▶︎"のx位置
cmd_y = 0 # コマンド選択の時の"▶︎"のy位置
(省略)

COMMAND = (("はなす", "じゅもん"), ("つよさ", "どうぐ"), ("そうび", "しらべる"))
cmd_flag = False # フィールドでコマンド画面を表示するか
cmd_x = 0 # コマンド選択の時の"▶︎"のx位置
cmd_y = 0 # コマンド選択の時の"▶︎"のy位置

コメントの通りです。
cmd_flagがTrueの時に
画面にコマンドとパラメータを
表示するようにします。

COMMAND = (("はなす", "じゅもん"), ("つよさ", "どうぐ"), ("そうび", "しらべる"))

コマンドをリストに入れます。
cmd_x、cmd_yに格納された値で
どれを選択したか判断します。
cmd_x:0
 cmd_x:0
 の場合は「はなす」

 

追加したグローバル変数を
使って変更します。

move_player関数に
追加します。

def move_player(key, player, people):
    global tmr, food, potion, blazegem, treasure, area
    global talk_flag, talk_mes, talk_end, talk_start, talk_yesno, talk_yesno_i, rest_flag
    global cmd_flag, cmd_x, cmd_y # 追加

 

「a」キーを押下した時、
前に人がいたら会話
(talk_flagをTrue)
前に人がいなければコマンド表示
(cmd_flagをTrue)
にします。

変更前

def move_player(key, player, people):
(省略)

    if not talk_flag: # 会話中でない時は動ける、会話できる
(省略)

        elif key[K_a] == 1:
            if player.d == 0: # 上向きの時
                for i in range(len(people.x)): # 人の表示
                    if people.y[i] == player.y-1 and people.x[i] == player.x:
                        print(people.talk[i])
                        talk_flag = True
                        talk_mes = people.talk[i].split("\n")
                        break

変更後

def move_player(key, player, people):
(省略)

    if not talk_flag: # 会話中でない時は動ける、会話できる
(省略)

        elif key[K_a] == 1:
            talk_flag, talk_mes = talk_judge(player, people)
            if not talk_flag: # 会話ではない場合、コマンド表示
                cmd_flag = True
talk_flag, talk_mes = talk_judge(player, people)

長くなってきたので
前に人がいるかの判断を
talk_judge関数にしました。

if not talk_flag: # 会話ではない場合、コマンド表示
    cmd_flag = True

talk_judge関数の戻り値で
talk_flagがFalseなら
(前に人がいないなら)
コマンドを表示します。

 

talk_judge関数です。

def talk_judge(player, people):
    flag = False # 会話中か(会話中は動かない)
    mes = [] # 会話の内容
    if player.d == 0: # 上向きの時
        for i in range(len(people.x)): # 人の表示
            if people.y[i] == player.y-1 and people.x[i] == player.x:
                flag = True
                mes = people.talk[i].split("\n")
                break
            for std in STAND:
                if int(n_map[player.y-1][player.x][2:]) == std: # 自分がいるところより一個上に台がある時
                    if people.y[i] == player.y-2 and people.x[i] == player.x: # 自分がいるところより2個上に人がいれば話す
                        flag = True
                        mes = people.talk[i].split("\n")
                        break
    elif player.d == 1: # 下向きの時
(省略)

    return flag, mes

変更前の「elif key[K_a] == 1:」以下を
ほぼそのままコピーです。

 

あと、コマンド表示中に
「b」キーを押下したら
コマンドを非表示にします。
(cmd_flagをFalse)

def move_player(key, player, people):
(省略)

    if not talk_flag: # 会話中でない時は動ける、会話できる
(省略)

        elif key[K_a] == 1:
(省略)
        elif key[K_b] == 1: # 「b」キーを押下したら、コマンド非表示(キャンセル)
            if cmd_flag:
                cmd_flag = False

 

次にコマンド表示されている場合
(cmd_flagがTrue)
上下左右キーを押下したら
cmd_x,cmd_yが変更される
ようにします。

変更前

def move_player(key, player, people):
(省略)

    if not talk_flag: # 会話中でない時は動ける、会話できる
        if key[K_UP] == 1:
            player.d = 0
            if player.y > 0:
(省略)

変更後

def move_player(key, player, people):
(省略)

    if not talk_flag: # 会話中でない時は動ける、会話できる
        if key[K_UP] == 1:
            if cmd_flag: # コマンド選択中
                if cmd_y > 0:
                    cmd_y -= 1
            else:
                player.d = 0
                if player.y > 0:
(省略)

        elif key[K_DOWN] == 1:
            if cmd_flag: # コマンド選択中
                if cmd_y < 2:
                    cmd_y += 1
            else:
                player.d = 1
(省略)

        elif key[K_LEFT] == 1:
            if cmd_flag: # コマンド選択中
                if cmd_x > 0 :
                    cmd_x -= 1
            else:
                player.d = 2
(省略)

        elif key[K_RIGHT] == 1:
            if cmd_flag: # コマンド選択中
                if cmd_x < 1:
                    cmd_x += 1
            else:
                player.d = 3
(省略)

        elif key[K_a] == 1:
            talk_flag, talk_mes = talk_judge(player, people)
(省略)
COMMAND = (("はなす", "じゅもん"), ("つよさ", "どうぐ"), ("そうび", "しらべる"))

の為、
cmd_xの最大値は1、
cmd_yの最大値は2
です。
※NumPyを使えばこの辺りの値を
 取得できそうですが、
 今回はとりあえず(^_^;)

 

あとはdraw_para関数を変更して、
コマンドを表示します。

変更前(変更後は全て削除)

def draw_para(bg, fnt, player): # 主人公の能力を表示
    X = 30
    Y = 100
    bg.blit(imgPara, [X, Y])
    col = WHITE
    if player.hp < 10 and tmr%2 == 0:
        col = RED
    draw_text(bg, "{}/{}".format(player.hp, player.maxhp), X+128, Y+6, fnt, col)
    draw_text(bg, str(player.atk), X+128, Y+33, fnt, WHITE)
    col = WHITE
    if food == 0 and tmr%2 == 0:
        col = RED
    draw_text(bg, str(food), X+128, Y+60, fnt, col)
    draw_text(bg, str(potion), X+266, Y+6, fnt, WHITE)
    draw_text(bg, str(blazegem), X+266, Y+33, fnt, WHITE)

変更後

def draw_para(bg, fnt, player): # 主人公の能力を表示
    col = WHITE
    x_c_i = bg.get_width()*0.05 # x座標の開始位置
    x_c_w = bg.get_width()*0.4 # 横幅
    y_c_i = bg.get_height()*0.05 # y座標の開始位置
    y_c_h = bg.get_height()*0.25 # 高さ
    x_c_i_t = x_c_i + 50 # テキストのx座標の開始位置
    y_c_i_t = y_c_i + 30 # テキストのy座標の開始位置
    pygame.draw.rect(bg, BLACK, [x_c_i, y_c_i, x_c_w, y_c_h], 0, 5) # 枠
    pygame.draw.rect(bg, col, [x_c_i, y_c_i, x_c_w, y_c_h], 2, 5) # 枠

    for i in range(3): # コマンドの表示
        for j in range(2):
            draw_text(bg, COMMAND[i][j], x_c_i_t+j*x_c_w/2, y_c_i_t+i*50, fnt, col)
    if tmr%5 != 0:
        draw_text(bg, "▶︎", x_c_i_t-50+cmd_x*x_c_w/2, y_c_i_t+cmd_y*50, fnt, col)

枠は以下のような感じです。

 

また、プレイヤーのパラメータも
表示します。

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

    x_p_i = bg.get_width()*0.8 # x座標の開始位置
    x_p_w = bg.get_width()*0.15 # 横幅
    y_p_i = bg.get_height()*0.75 # y座標の開始位置
    y_p_h = bg.get_height()*0.25-20 # 高さ
    x_p_i_t = x_p_i + x_p_w/2 - 40 # テキストのx座標の開始位置
    y_p_i_t = y_p_i + 20 # テキストのy座標の開始位置
    pygame.draw.rect(bg, BLACK, [x_p_i, y_p_i, x_p_w, y_p_h], 0, 5) # 枠
    pygame.draw.rect(bg, col, [x_p_i, y_p_i, x_p_w, y_p_h], 2, 5) # 枠
    draw_text(bg, "{}".format(player.name), x_p_i_t, y_p_i_t, fnt, col)
    if len(str(player.hp)) == 3:
        draw_text(bg, mojimoji.han_to_zen("H{}".format(player.hp)), x_p_i_t, y_p_i_t+36, fnt, col)
    elif len(str(player.hp)) == 2:
        draw_text(bg, mojimoji.han_to_zen("H {}".format(player.hp)), x_p_i_t, y_p_i_t+36, fnt, col)
    elif len(str(player.hp)) == 1:
        draw_text(bg, mojimoji.han_to_zen("H  {}".format(player.hp)), x_p_i_t, y_p_i_t+36, fnt, col)

    if len(str(player.mp)) == 3:
        draw_text(bg, mojimoji.han_to_zen("M{}".format(player.mp)), x_p_i_t, y_p_i_t+66, fnt, col)
    elif len(str(player.mp)) == 2:
        draw_text(bg, mojimoji.han_to_zen("M {}".format(player.mp)), x_p_i_t, y_p_i_t+66, fnt, col)
    elif len(str(player.mp)) == 1:
        draw_text(bg, mojimoji.han_to_zen("M  {}".format(player.mp)), x_p_i_t, y_p_i_t+66, fnt, col)
    
    if len(str(player.lv)) == 2:
        draw_text(bg, mojimoji.han_to_zen("L:{}".format(player.lv)), x_p_i_t, y_p_i_t+96, fnt, col)
    elif len(str(player.lv)) == 1:
        draw_text(bg, mojimoji.han_to_zen("L: {}".format(player.lv)), x_p_i_t, y_p_i_t+96, fnt, col)

枠は以下のような感じです。

 

if len(str(player.hp)) == 3:
    draw_text(bg, mojimoji.han_to_zen("H{}".format(player.hp)), x_p_i_t, y_p_i_t+36, fnt, col)

HPの桁数によって
表示の開始位置を変更しています。

また、数字を全角で表示する為に
mojimoji.han_to_zenを利用しています。

 

移動中のコマンド表示と
パラメータは以上です。

とりあえず今回は表示のみで
コマンドの機能はまた今度にします(^_^;)

 

 

宿屋

前回、宿屋に泊まるようにしましたが
少し変更します。

会話を以下のように変更します。

変更後

*「ようこそ 旅の宿に。
*「ひと晩 10ゴールドですが
  お泊まりに なりますか?
#yesno
#yes
*「それでは ごゆっくり
  おやすみください。
#yesrest
*「おはようございます。
  では いってらっしゃいませ。
#no
*「さようなら 旅の人。
  お気をつけて 旅を
  つづけられますように。
#end

 

動作は変わりませんが、
「はい」「いいえ」の質問には
#yes,#noを使いたかったからです。

 

プログラムは以下のようにしました。

def move_player(key, player, people):
    global tmr, food, potion, blazegem, treasure, area
    global talk_flag, talk_mes, talk_end, talk_start, talk_yesno, talk_yesno_i # rest_flagを削除
    global cmd_flag, cmd_x, cmd_y

(省略)

    else: # 会話中
(省略)

        if talk_yesno: # yesnoクエスチョン中
            if key[K_UP] == 1:
                talk_yesno_i = 0
            elif key[K_DOWN] == 1:
                talk_yesno_i = 1
            elif key[K_a] == 1:
                talk_start = talk_line
                if talk_yesno_i == 0:
                    while True:
                        talk_start += 1
                        if talk_mes[talk_start] == "#yes":
                            talk_start += 1
                            break
                        #####削除#####
                        #elif talk_mes[talk_start] == "#yesrest":
                        #    rest_flag = True
                        #    player.rest()
                        #    talk_start += 1
                        #    break
                        #####削除#####
                elif talk_yesno_i == 1:
                    while True:
                        talk_start += 1
                        if talk_mes[talk_start] == "#no":
                            talk_start += 1
                            break
                talk_yesno_i = 0 # ▶︎をはいの位置に戻す(複数回、回答する時用)
                talk_yesno = False
(省略)

def draw_message(bg, fnt, player):
    global talk_line, talk_end, talk_yesno, rest_flag # rest_flagを追加
(省略)

    while True:
        #####削除#####
        #draw_text(bg, "{}".format(talk_mes[talk_line]), x_i_t, y_i_t+30*i, fnt, col)
        #i += 1
        #talk_line += 1
        #####削除#####

        if talk_mes[talk_line] == "#end": # 会話の最後を表示している
            talk_end = True
            break
        elif talk_mes[talk_line] == "#page": # 会話の途中を表示している(会話の続きがある)
            if tmr%5 != 0: # 点滅
                draw_text(bg, "{}".format("▼"), x_i_t, y_i_t+30*i, fnt, col)
                i += 1
            break
        #####追加#####
        elif talk_mes[talk_line] == "#yesrest": # 休む
            rest_flag = True
            break
        #####追加#####
        elif talk_mes[talk_line] == "#yesno": # 会話の途中を表示している(会話の続きがある)、yesnoのの後には必ず#pageか#endを持ってくる必要がある
(省略)
        #####追加#####
        else:
            draw_text(bg, "{}".format(talk_mes[talk_line]), x_i_t, y_i_t+30*i, fnt, col)
            i += 1
        talk_line += 1
        #####追加#####

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

        elif idx == 2: # 画面切り替え(階段)
(省略)

            if tmr == 5:
                if rest_flag: # 休んでいる時なら会話を進める(画面が開いたら会話が進んでいる)
                    talk_start = talk_line + 1
                    player.rest() # 追加
elif talk_mes[talk_start] == "#yesrest":
    rest_flag = True
    player.rest()
    talk_start += 1
    break

を削除

elif talk_mes[talk_line] == "#yesrest": # 休む
    rest_flag = True
    break

を追加

if tmr == 5:
    if rest_flag: # 休んでいる時なら会話を進める(画面が開いたら会話が進んでいる)
        talk_start = talk_line + 1
        player.rest() # 追加

player.rest()を追加しています。

 

また、
draw_text(bg, "{}".format(talk_mes[talk_line]), x_i_t, y_i_t+30*i, fnt, col)
の位置を少し変更しました。

else:
    draw_text(bg, "{}".format(talk_mes[talk_line]), x_i_t, y_i_t+30*i, fnt, col)
    i += 1
talk_line += 1

 

 

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

 

 

最後に

今回は移動中のコマンドやパラメータを表示するようにしました。

次回はどうするか迷っています。

まとめサイトへ

 

 

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

 

 

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

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