CODE Python RPG

独学でPythonでRPGを作成する(第44回)町の人々を表示

投稿日:

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

前回は町のマップを作成して、フィールドマップから町マップへ移動できるようにしました。

今回は町マップに町の人々を表示します。
また、プレイヤーが町の人々と重ならないようにします。

目次

  1. 人々のシート
  2. charaの変更
  3. one_hour_dungeonの変更
  4. moveの変更
  5. 最後に

人々のシート

最初に、スプレッドシートに
新しく町の人々用のシートを作成します。
※シート名は「人物」にしました。

場所(A列)はマップ番号です。
前回も記載したmaps.pyの番号(num)です。
※その人物を表示する町(場所)です。

class Maps():
    def get_map(self, num, player):
        if num == 0: # フィールド
(省略)

        if num == 1: # 町

x,y(B,C列)は人々を表示する座標、
画像(D列)は人々の画像のファイル名です。

今回は以下のような画像を用意しました。
※何でも良いと思います。(動物でも)
※透過PNG画像が良いと思います。

あと、画像の大きさは40*40に
しています。
マップの1マスの大きさです。

move.py

M_WIDTH = 40 # 1マスの横幅
M_HEIGHT = 40 # 1マスの高さ

 

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

 

 

charaの変更

先程、新しく作ったシートの値を
chara.pyで読み込みます。

person_place = ws_person.col_values(1) # A列 場所
person_x = ws_person.col_values(2) # B列 x
person_y = ws_person.col_values(3) # C列 y
person_pic = ws_person.col_values(4) # D列 画像

 

次に、人物用のクラス(People)を
作成します。

町に入ったときに
その町にいる人々の情報を
上記の変数を使って取得します。

# 人物シート
class People():
    def __init__(self):
        self.x = []
        self.y = []
        self.pic = []
    def get_posi(self, area):
        self.x.clear()
        self.y.clear()
        self.pic.clear()
        for i in range(1, len(person_place)): # 1行目はカラムの為、とばす
            if int(person_place[i]) == area: # 人々の場所(A列)と一致したら取得
                self.x.append(int(person_x[i]))
                self.y.append(int(person_y[i]))
                self.pic.append(int(person_pic[i]))

 

get_posiメソッドは
入った町(area)の情報を
取得します。
※areaはマップ番号です。

self.x.clear()
self.y.clear()
self.pic.clear()

今は町は一つのみですが、
そのうち複数の町を用意しようと
思っています。

色々な町に出入りするので
入る度にいったん人々の情報を
削除します。
※clearの詳細はこちら

削除した後に入った町の人々の
情報を習得します。

for i in range(1, len(person_place)): # 1行目はカラムの為、とばす
    if int(person_place[i]) == area: # 人々の場所(A列)と一致したら取得
        self.x.append(int(person_x[i]))
        self.y.append(int(person_y[i]))
        self.pic.append(int(person_pic[i]))

入った町のマップ情報(area)と
人々の場所(A列)が一致したら
各変数に格納していきます。
※appendの詳細はこちら

 

charaの変更は以上です。

 

 

one_hour_dungeonの変更

次にone_hour_dungeon.pyを変更します。

player = chara.Brave()
maps = maps.Maps()
people = chara.People() # 追加

最初にPeopleクラスの
インスタンスを生成します。

 

def main():
(省略)

        elif idx == 1:
            tmr = 0
            idx, area = move.main(screen, clock, font, fontS, n_map, player, people) # 引数にpeopleを追加
        elif idx == 2: # マップと人々の設定
            n_map = maps.get_map(area, player)
            people.get_posi(area) # 追加
            idx = 1
idx, area = move.main(screen, clock, font, fontS, n_map, player, people) # 引数にpeopleを追加

町の人々の情報を渡す為、
move.pyのmain関数の引数に
peopleを追加しています。
※人々を表示するのは
 プレイヤーが移動中の時なので
 人々の情報はmove.pyで利用します。

elif idx == 2: # マップと人々の設定
    n_map = maps.get_map(area, player)
    people.get_posi(area) # 追加
    idx = 1

マップが変わったら
Peopleクラスの
get_posiメソッドを使って
人々の情報を更新します。

 

one_hour_dungeonの変更は以上です。

 

 

moveの変更

最後にmove.pyの変更です。
町の人々を表示します。

imgmap = []
for i in range(129):
    imgmap.append(pygame.image.load("map/" + str(i) + ".png"))

#####追加#####
imgperson = []
for i in range(3):
    imgperson.append(pygame.image.load("person/" + str(i) + ".png")

まず、人々の画像を
リストimgpersonに入れます。
※ここではpersonフォルダに
  人々画像を格納しています。

 

(省略)

def draw_map(bg, fnt, player, people):
(省略)

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

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

次に各関数の引数にpeopleを
追加します。
※呼び出す側も追加します。

 

def draw_map(bg, fnt, player, people):
(省略)

    for y in range(-8, 10):
(省略)

            #####追加#####
            for i in range(len(people.x)):
                if dy==people.y[i] and dx==people.x[i]:
                    bg.blit(imgperson[int(people.pic[i])], [X, Y])
            #####追加#####

            if x == 0 and y == 0: # 主人公キャラの表示
                bg.blit(player.img[player.a], [X, Y]) # 元はY-40、-40があると1ズレる

draw_map関数で
町の人々を表示します。

for i in range(len(people.x)):
    if dy==people.y[i] and dx==people.x[i]:
        bg.blit(imgperson[int(people.pic[i])], [X, Y])

人々が持っている座標(B,C列)が
一致するところに画像を表示します。

 

最後に人々と同じ場所(座標)に
プレイヤーが移動できないように
します。

変更前

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

    x = player.x # 移動したかを確認する為に今の位置を保存
    y = player.y
    if key[K_UP] == 1:
        player.d = 0
        if player.y > 0:
            if int(n_map[player.y-1][player.x][2:]) < 101:
                player.y = player.y - 1
def move_player(key, player, people):
(省略)

    x = player.x # 移動したかを確認する為に今の位置を保存
    y = player.y
    posi_flag = False
    if key[K_UP] == 1:
        player.d = 0
        if player.y > 0:
            if int(n_map[player.y-1][player.x][2:]) < 101:
                for i in range(len(people.x)): # 人と重ならないか
                    if player.y-1 == people.y[i] and player.x == people.x[i]:
                        posi_flag = True
                if not posi_flag:
                    player.y = player.y - 1

上への移動です。

for i in range(len(people.x)): # 人と重ならないか
    if player.y-1 == people.y[i] and player.x == people.x[i]:
        posi_flag = True

プレイヤーが移動しようとする座標と
人々の座標が一致するか確認します。

if not posi_flag:
    player.y = player.y - 1

一致しなければ上に移動します。

 

左右下も同様です。

変更後

(省略)

    if key[K_DOWN] == 1:
        player.d = 1
        if player.y < map_h-1: # map_hになるとout of rangeになる
            if int(n_map[player.y+1][player.x][2:]) < 101: # player.y+1なので、player.y=map_h-1の時out of rangeになる
                for i in range(len(people.x)):
                    if player.y+1 == people.y[i] and player.x == people.x[i]:
                        posi_flag = True
                if not posi_flag:
                    player.y = player.y + 1

    if key[K_LEFT] == 1:
        player.d = 2
        if player.x > 0:
            if int(n_map[player.y][player.x-1][2:]) < 101:
                for i in range(len(people.x)):
                    if player.y == people.y[i] and player.x-1 == people.x[i]:
                        posi_flag = True
                if not posi_flag:
                    player.x = player.x - 1

    if key[K_RIGHT] == 1:
        player.d = 3
        if player.x < map_w-1:
            if int(n_map[player.y][player.x+1][2:]) < 101:
                for i in range(len(people.x)):
                    if player.y == people.y[i] and player.x+1 == people.x[i]:
                        posi_flag = True
                if not posi_flag:
                    player.x = player.x + 1

なお、
for i in range(len(people.x)):
の辺りはzipやリスト内包表記を
使った方が良い気がします。
※zipの詳細はこちら
※リスト内包表記はこちら

追い追い慣れていけたらと・・(^_^;)

 

兎にも角にも
これで町の人々が表示できる
ようになりました。

こんな感じです。

赤字は座標です。
シートの(B列、C列)
の値です。 

 

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

 

 

最後に

今回は町マップに町の人々を表示できるようにしました。

次回も町の人々について変更していこうと思います。

まとめサイトへ

 

 

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

 

 

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

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