CODE Python RPG

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

更新日:

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

前回は町の人々が少し長いことを話せる(表示ページを更新する)ようにしました。

今回は町の人々と会話するようにします。
具体的には町の人々の質問に対して「はい」「いいえ」を返します。

目次

  1. 人物シート
  2. moveの変更
  3. 台を挟んで話す
  4. 最後に

人物シート

町の人々の質問に対して
「はい」か「いいえ」かで
答えるようにします。

 

スプレッドシートの人物シートで
言葉を以下の赤枠のようにします。

変更後

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

※会話の内容はこちら
 参考にさせて頂きました。

 

前回、「#page」や「#end」を
追加しましたが、
今回も新しく
「#yesno」「#yes」「#no」
を追加します。

#yesno:質問が始まる
#yes:質問に対して「はい」を返した時
#no:質問に対して「いいえ」を返した時
として使います。

「#yesno」「#yes」「#no」は
画面に表示させません。

 

人物シートは以上です。

 

 

moveの変更

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

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

talk_flag = False # 会話中か(会話中は動かない)
talk_end = False # 会話の最後か(aを押したら会話が終わりか)
talk_mes = []
talk_line = 0 # セリフの行数(talk_mesの何行目か)
talk_start = 0 # セリフを表示する最初の行数(会話の途中の場合は会話の途中の行数)
talk_yesno = False # yesnoクエスチョン中か
talk_yesno_i = 0 # yesnoクエスチョンの位置 0:はい、1:いいえ
talk_yesno = False # yesnoクエスチョン中か
talk_yesno_i = 0 # yesnoクエスチョンの位置 0:はい、1:いいえ

を追加しています。

「talk_yesno」がTrueの時に
「はい」「いいえ」を
画面に表示して
どちらかを選択できるようにします。

「talk_yesno_i」は
「はい」を選択したら0
「いいえ」を選択したら1
を格納します。

 

次に「はい」「いいえ」を
表示します。

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

    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) # 枠

#####追加「はい」いいえ」#####
    x_yesno_i = bg.get_width()*0.7 # x座標の開始位置
    x_yesno_w = bg.get_width()*0.2 # 横幅
    y_yesno_i = bg.get_height()*0.1 # y座標の開始位置
    y_yesno_h = bg.get_height()*0.15 # 高さ
    x_yesno_i_t = x_yesno_i + 60 # テキストのx座標の開始位置
    y_yesno_i_t = y_yesno_i + 30 # テキストのy座標の開始位置
#####追加「はい」いいえ」#####
x_yesno_i = bg.get_width()*0.7 # x座標の開始位置
x_yesno_w = bg.get_width()*0.2 # 横幅
y_yesno_i = bg.get_height()*0.1 # y座標の開始位置
y_yesno_h = bg.get_height()*0.15 # 高さ
x_yesno_i_t = x_yesno_i + 60 # テキストのx座標の開始位置
y_yesno_i_t = y_yesno_i + 30 # テキストのy座標の開始位置

横幅や高さなど
「はい」「いいえ」を
表示するのに必要な
変数を追加します。

 

追加した変数を使って
「はい」「いいえ」を
表示します。

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

    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": # 会話の最後を表示している
(省略)
        elif talk_mes[talk_line] == "#page": # 会話の途中を表示している(会話の続きがある)
(省略)

        elif talk_mes[talk_line] == "#yesno": # 会話の途中を表示している(会話の続きがある)、yesnoの後には必ず#pageか#endを持ってくる必要がある
            pygame.draw.rect(bg, BLACK, [x_yesno_i, y_yesno_i, x_yesno_w, y_yesno_h], 0, 5) # 枠
            pygame.draw.rect(bg, col, [x_yesno_i, y_yesno_i, x_yesno_w, y_yesno_h], 2, 5) # 枠
            draw_text(bg, "{}".format("はい"), x_yesno_i_t, y_yesno_i_t, fnt, col)
            draw_text(bg, "{}".format("いいえ"), x_yesno_i_t, y_yesno_i_t+30, fnt, col)
            if tmr%5 != 0: # 点滅
                draw_text(bg, "{}".format("▶︎"), x_yesno_i_t-50, y_yesno_i_t+30*talk_yesno_i, fnt, col)
            talk_yesno = True
            break
elif talk_mes[talk_line] == "#yesno":
    pygame.draw.rect(bg, BLACK, [x_yesno_i, y_yesno_i, x_yesno_w, y_yesno_h], 0, 5) # 枠
    pygame.draw.rect(bg, col, [x_yesno_i, y_yesno_i, x_yesno_w, y_yesno_h], 2, 5) # 枠
    draw_text(bg, "{}".format("はい"), x_yesno_i_t, y_yesno_i_t, fnt, col)
    draw_text(bg, "{}".format("いいえ"), x_yesno_i_t, y_yesno_i_t+30, fnt, col)
    if tmr%5 != 0: # 点滅
        draw_text(bg, "{}".format("▶︎"), x_yesno_i_t-50, y_yesno_i_t+30*talk_yesno_i, fnt, col)
    talk_yesno = True
    break

人が発する言葉に
「#yesno」が出てきたら
「はい」「いいえ」を表示します。

また、「talk_yesno」を
Trueにして質問中にします。
※「はい」「いいえ」を選択中。

 

続いて、「はい」「いいえ」を
選択できるようにします。

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

    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_end = False
                talk_mes = []
                talk_flag = False
                talk_start = 0
                talk_yesno_i = 0 # yesnoの▶︎をはいの位置に戻す
                talk_yesno = False
            else: # 会話の途中でaを押したら続きの会話を表示する
                talk_start = talk_line + 1 # #pageの次の行から表示する

グローバル変数
talk_end, talk_yesno, talk_yesno_i
を追加します。

前回、talk_endは
draw_message関数で
変更しましたが、
move_player関数で
変更するようにします。

if key[K_a] == 1:
    if talk_end: # 会話の最後でaを押したら会話終了(会話情報をリセット)
        talk_end = False
        talk_mes = []
        talk_flag = False
        talk_start = 0
        talk_yesno_i = 0 # yesnoの▶︎をはいの位置に戻す
        talk_yesno = False

また、「talk_yesno_i」「talk_yesno」
も会話が終わったら
デフォルトに戻します。

 

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

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

    else: # 会話中
        if key[K_a] == 1:
(省略)

#####追加#####
        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_yesno_i == 1:
                    while True:
                        talk_start += 1
                        if talk_mes[talk_start] == "#no":
                            talk_start += 1
                            break
                talk_yesno = False

「はい」「いいえ」の選択です。

if key[K_UP] == 1:
    talk_yesno_i = 0
elif key[K_DOWN] == 1:
    talk_yesno_i = 1

2択なので
↑キーを押下したら0(はい)
↓キーを押下したら1(いいえ)
にします。
※↑キーを何回押下しても0
 ↓キーを何回押下しても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_yesno_i == 1:
        while True:
            talk_start += 1
            if talk_mes[talk_start] == "#no":
                talk_start += 1
                break
    talk_yesno = False

aキーを押下したら
「はい」「いいえ」を
決定します。

「はい」を選択したら
talk_startを「#yes」の
次の行まで進めて、
「いいえ」を選択したら
talk_startを「#no」の
次の行まで進めています。

 

会話はtalk_startから
表示するようにしています。

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

    i = 0
    talk_line = talk_start # 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
(省略)

「はい」を選択

「いいえ」を選択

 

最後に、
「はい」を選択した時は
「いいえ」を選択した時の
言葉を表示させないようにします。

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

    while True:
(省略)
        elif talk_mes[talk_line] == "#yesno": # 会話の途中を表示している(会話の続きがある)、yesnoの後には必ず#pageか#endを持ってくる必要がある
(省略)

#####追加#####
        elif talk_mes[talk_line] == "#no": # yesを選択した時は#noの内容を#pageか#endまで飛ばす
            while True:
                talk_line += 1
                if 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] == "#end":
                    talk_end = True
                    break
            break

「はい」を選択したら
「#no」〜「#page」もしくは
「#no」〜「#end」の内容を
飛ばします。

なので、「#yesno」の後には
「#page」か「#end」の
どちらかが必要になります。

 

質問に対する
「はい」「いいえ」の回答は以上です。

 

 

台を挟んで話す

少し細かいところを修正します。

45回目で台を挟んで
話せるようにしました。

台の画像は
120.pngと121.pngで
120と121を使って
人との間に台があるか
判定しています。

これを定数(リスト)にします。

STAND = [120, 121] # 台の画像(台の先の人に話せる)

リストSTANDに
台の画像の情報を入れます。

STANDを使って
人との間に台があるか
判定します。

変更前

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

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

        elif key[K_a] == 1:
            if player.d == 0: # 上向きの時
(省略)

                    if int(n_map[player.y-1][player.x][2:]) == 120 or int(n_map[player.y-1][player.x][2:]) == 121: # 自分がいるところより一個上に台がある時
                        if people.y[i] == player.y-2 and people.x[i] == player.x: # 自分がいるところより2個上に人がいれば話す
                            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:
            if player.d == 0: # 上向きの時
(省略)

                    if int(n_map[player.y-1][player.x][2:]) in STAND: # 自分がいるところより一個上に台がある時
(省略)

下左右についても同様です。

今後、台の画像が
変わるかもしれませんが
その時はSTANDの値を変更します。

 

 

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

 

 

最後に

今回は町の人々の質問に対して「はい」「いいえ」を返すようにしました。

次回は宿屋に泊まります。

まとめサイトへ

 

 

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

 

 

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

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