CODE Python RPG

独学でPythonでRPGを作成する(第46回)町の人々と話す

投稿日:

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

前回プレイヤーが条件を満たした時にその町の人々が言葉を発するようにしました。

今回は町の人々がもう少し長いことを話せるようにします。
また、話すことについて他にも細かいところを変更します。

目次

  1. 人物シート
  2. moveの変更
  3. 最後に

人物シート

前回、町の人々の言葉を
表示できるようにしましたが
言葉が長いと全てを
表示できません。

というわけで話が長くても
表示できるようにします。

 

最初に、スプレッドシートの
「人物」シートに町の人々の
言葉を以下にようにします。

 

言葉に「#page」や「#end」を
追加しました。

「#page」はまだ続きある、
「#end」はこれで終わり、
ということにします。

「#page」でいったん表示を
区切ります。

「#page」「#end」自体は
画面に表示はさせません。

 

シートについては以上です。

 

 

moveの変更

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

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

talk_line = 0 # セリフの行数(talk_mesの何行目か)
talk_start = 0 # セリフを表示する最初の行数(会話の途中の場合は会話の途中の行数)
talk_end = False # 会話の最後か(aを押したら会話が終わる)

リストtalk_mesに
人々の言葉(E列)を
格納します。

talk_mesを1行ずつ
読み込む為に
talk_lineを使います。

 

talk_startは
表示する最初の言葉の
行数を格納します。

人の言葉が
「さようなら 旅の人。
 #page
 お気をつけて 旅を
 つづけられますように。
 #end」
の場合は以下のような
感じです。

言葉の途中の場合は
「#page」の次の行が
talk_startになります。

 

talk_endは
話がそこで終わりかを
判定する為に使います。

「#end」となったら
talk_endをTrueにして
話を終えます。

 

次に人々の話を表示します。

変更前

def draw_message(bg, fnt):
(省略)

    for i, tmp in enumerate(talk_mes):
        draw_text(bg, "{}".format(tmp), x_i_t, y_i_t+30*i, fnt, col)

変更後

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

    i = 0
    talk_line = talk_start
    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
            talk_end = False
            break
global talk_line, talk_end

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

i = 0
talk_line = talk_start

talk_startの位置から
読み込んで行きます。

while True:
(省略)
    if talk_mes[talk_line] == "#end": # 話の最後を表示している
(省略)
    elif talk_mes[talk_line] == "#page": # 話の途中を表示している(話の続きがある)
(省略)

while文で
「#end」もしくは
「#page」までの言葉を
画面に表示させます。

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

talk_lineを使って
1行ずつ読み込んで行きます。

if talk_mes[talk_line] == "#end": # 話の最後を表示している
    talk_end = True
    break

「#end」を読み込んだら
while文から抜けて話を終えます。

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
    talk_end = False
    break

「#page」を読み込んだら
まだ話が途中であることを示す為に
「▼」を表示させます。

続きがあるので、
talk_endはFalseのまま
while文から抜けます。

 

あと、いちおう例外を設定しておきます。
※例外の詳細はこちら

「#end」が抜けていると
list index out of range
になってしまう為です。

※以下のようにしてしまった時

def draw_message(bg, fnt):
(省略)
    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
        try:
            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
                talk_end = False
                break
        except IndexError as e:
            print(e)
            if "#end" not in talk_mes:
                print(f"「#end」がない:{talk_mes}")
            else:
                print("move.py draw_message関数 でエラー")
            talk_end = True
            break

#####エラー( 「a」キーを押下するまで無限ループ)#####
# list index out of range
# 「#end」がない:['こんにちは', 'ごきげんよう', '#page', 'こんばんは']
except IndexError as e:
    print(e)
    if "#end" not in talk_mes:
        print(f"「#end」がない:{talk_mes}")
    else:
        print("move.py draw_message関数 でエラー")
    talk_end = True
    break

「#end」がないと
talk_line += 1
で、リストtalk_mesのインデックスを
増やし続けて、いずれ要素数を
オーバーしてしまいます。

 

続いて「a」キーを押下したら
話を進める、もしくは終える
ようにします。

def move_player(key, player, people):
    # talk_startを追加
    global tmr, food, potion, blazegem, treasure, area, talk_flag, talk_mes, talk_start
(省略)

    else:
        if key[K_a] == 1:
            if talk_end: # 話の最後でaを押したら終了
                talk_mes = []
                talk_flag = False
                talk_start = 0
            else: # 話の途中でaを押したら続きの話を表示する
                talk_start = talk_line + 1 # #pageの次の行から表示する
if talk_end: # 話の最後でaを押したら終了
    talk_mes = []
    talk_flag = False
    talk_start = 0

talk_endがTrueの時
(「#end」まで読み込んだら)
話を終えます。

前回は話を終えるタイミング
(talk_flagをFalseにする)が
無かったので、話が始まったら
表示を消せませんでした(^_^;)

else: # 話の途中でaを押したら続きの話を表示する
    talk_start = talk_line + 1 # #pageの次の行から表示する

talk_endがFalseの時
(「#page」まで読み込んだら)
続きを表示するようにします。
※talk_lineは「#page」の位置にいるので
 1行進めます。

 

これで町の人々の話が長くても
ページを切り替えて
表示させることができるようになりました。

 

「a」キーを押下(#pageの次を表示)

「a」キーを押下(#endなので終了)

 

最後に
人が話をしている間は
プレイヤーが動けないようにします。

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

    if not talk_flag: # 話中でない時は動ける
        if key[K_UP] == 1:
(省略)
        elif key[K_DOWN] == 1:
(省略)
        elif key[K_LEFT] == 1:
(省略)
        elif key[K_RIGHT] == 1:
(省略)
        elif key[K_a] == 1: # 人がいたら話中になる(talk_flag=Trueになる)
(省略)
    else:
        if key[K_a] == 1:
            if talk_end: # 話の最後でaを押したら話終了
                talk_mes = []
                talk_flag = False
                talk_start = 0
            else: # 話の途中でaを押したら続きの話を表示する
                talk_start = talk_line + 1 # #pageの次の行から表示する

上下左右のキーを押下できるのは
talk_flagがFalseの時だけにします。

また、「a」キーは
話中かそうでないかで
動作が変わります。

 

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

 

 

最後に

今回は町の人々がもう少し長いことを話せるようにしました。

次回は町の人々と会話できるようにしたいと思います。
(質問に対して「はい」「いいえ」を選択する)

まとめサイトへ

 

 

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

 

 

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

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