CODE Python RPG

独学でPythonでRPGを作成する(第30回)マップの1マスの大きさを変える

更新日:

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

前回はマップを変更しました。
今回はマップの1マスの大きさを変えます。

それに伴ってプレイヤーが動いた時の動作を変更します。
また、プレイヤーがマップの端に動いた時、端は黒くなりますが
画像が表示されるように変更します。

目次

  1. 1マスの大きさを変える
  2. マップを変える
  3. マップの端の表示
  4. 最後に

1マスの大きさを変える

今まで1マスの画像の大きさは80でした。
※scaleについてはこちら

move.py

for i, img in enumerate(imgmap):
    imgmap[i] = pygame.transform.scale(img, (80, 80))

これを40に変えます。

最初に定数
M_WIDTH
M_HEIGHT
を用意しておきます。

n_map = [[]] # 今いるマップを取得
map_w = 0 # 今いるマップの横の要素数
map_h = 0 # 今いるマップの縦の要素数

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

1マスの画像の大きさを
40(M_WIDTH, M_HEIGHT)にします。

for i, img in enumerate(imgmap):
    imgmap[i] = pygame.transform.scale(img, (M_WIDTH, M_HEIGHT))

 

プレイヤーの大きさも変更しておきます。

chara.pyです。

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

class Brave(Chara):
    def __init__(self):
(省略)

        self.img = [
                pygame.image.load("image/mychr0.png"), # 上
                pygame.image.load("image/mychr1.png"), # 上
                pygame.image.load("image/mychr2.png"), # 下
                pygame.image.load("image/mychr3.png"), # 下
                pygame.image.load("image/mychr4.png"), # 左
                pygame.image.load("image/mychr5.png"), # 左
                pygame.image.load("image/mychr6.png"), # 右
                pygame.image.load("image/mychr7.png"), # 右
                pygame.image.load("image/mychr8.png") # 倒れた
            ]
        for i, img in enumerate(self.img):
            self.img[i] = pygame.transform.scale(img, (M_WIDTH, M_HEIGHT))

 

1マスの画像の大きさの変更は以上です。

 

 

マップを変える

1マスの大きさを変えたので
マップ全体の表示を変える必要があります。

move.pyのdraw_map関数を変えます。

変更前

def draw_map(bg, fnt, player):
    bg.fill(BLACK)
    for y in range(-4, 6):
        for x in range(-5, 6):
            X = (x+5)*80
            Y = (y+4)*80
            dx = player.x + x
            dy = player.y + y
            if 0 <= dx and dx < map_w and 0 <= dy and dy < map_h:
                bg.blit(imgmap[n_map[dy][dx]], [X, Y])
            if x == 0 and y == 0: # 主人公キャラの表示
                bg.blit(player.img[player.a], [X, Y-40])
    draw_para(bg, fnt, player) # 主人公の能力を表示

変更後

def draw_map(bg, fnt, player):
    bg.fill(BLACK)
#####変更ここから#####
    for y in range(-8, 10): # 18分割(-8,-7・・,0,1・・,9)
        for x in range(-10, 12): # 22分割(-10,-9・・,0,1・・,11)
            X = (x+10)*M_WIDTH
            Y = (y+8)*M_HEIGHT
#####変更ここまで#####
            dx = player.x + x
            dy = player.y + y
            if 0 <= dx and dx < map_w and 0 <= dy and dy < map_h:
                bg.blit(imgmap[n_map[dy][dx]], [X, Y])
            if x == 0 and y == 0: # 主人公キャラの表示
                bg.blit(player.img[player.a], [X, Y-40])
    draw_para(bg, fnt, player) # 主人公の能力を表示

以下のところ変更しました。

    for y in range(-8, 10):
        for x in range(-10, 12):
            X = (x+10)*M_WIDTH
            Y = (y+8)*M_HEIGHT

 

画面の大きさは(880, 720)の為、
横は880/40 → 22分割
縦は720/40 → 18分割
になります。

screen = pygame.display.set_mode((880, 720))

※one_hour_dungeon.py

 

maps.pyのマップも少し追加しました。
map_w = len(n_map[0]) → 51
map_h = len(n_map) → 32
です。

class Maps():
    def get_map(self, num, player):
        if num == 0: # (51, 32)
            maps = [
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 24,  3,  3,  3,  3, 23, 16, 16, 16, 24,  3,  3,  3, 23, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24,  3,  3,  3,  3,  3,  3,  3, 23, 20, 24,  3,  3,  3,  3,  3,  3,  3,  3, 23, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 24,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 23, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 24,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 23, 20, 16, 16, 16, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 16, 16, 16, 16, 24,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 23, 16, 16, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 16, 16, 16, 24,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 17, 16, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 16, 16, 24,  2,  2,  2,  2,  2,  2,  0,  0,  0, 10, 11,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 23, 16, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 16, 24,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 17, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 19,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 23, 16, 16, 16, 16, 16],
                [16, 16, 16, 16, 19,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 17, 16, 16, 16, 16],
                [16, 16, 16, 16, 19,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 17, 16, 16, 16, 16],
                [16, 16, 16, 16, 19,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,  0,  0,  0,  0,  4,  4,  4,  4,  4,  3,  3,  3,  3,  3,  3, 23, 16, 16, 16, 16],
                [16, 16, 16, 20, 24,  4,  4,  2,  2,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,  0,  0,  4,  4,  4,  4,  4,  4,  4,  4,  4,  3,  3,  3,  3, 23, 16, 16, 16],
                [16, 16, 19,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,  0,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  3,  3,  3,  3, 17, 16, 16],
                [16, 16, 24,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  3,  3,  3, 17, 16, 16],
                [16, 24,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5, 23, 16, 16],
                [19,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  3,  3,  3,  3,  3,  3,  3, 21, 18, 22,  5,  5,  5,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  5, 17, 16],
                [19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 16],
                [19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 25, 16, 16],
                [19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 23, 16],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 21, 16],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 23, 16],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 23, 17],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 23, 17],
                [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 23, 17]
            ]
        player.d = 1 # プレイヤーの向き
        player.a = 2 # プライヤーの画像
        player.x = 16 # マップの最初のx座標
        player.y = 8 # マップの最初のy座標
        return maps

 

実行すると以下のような感じです。

 

端の方に行くと黒くなります。

 

これは今までもそうでした。

 

 

 

マップの端の表示

ここからは端の方に行っても
マップが表示されるように変更します。
※プレイヤーが海を歩けている点は
 そのうち修正します(^_^;)

 

なお・・
今回の変更はなぜ出来たのか
あまり分かっていません・・
恥ずかしながら・・・

とりあえず、こんな感じかな、
とあれこれと変更していくうちに
気が付いたら、やりたいことが
出来ました(^_^;)

なので、このように変更した理由は
説明できませんので、あしからず・・(>人<;)

 

move.pyのdraw_map関数の変更後です。

def draw_map(bg, fnt, player):
    bg.fill(BLACK)
    x_range = int(bg.get_width() / M_WIDTH) # 画面の横幅の分割数(for文のレンジ) 22
    y_range = int(bg.get_height() / M_HEIGHT) # 画面の高さの分割数(for文のレンジ) 18
    for y in range(-8, 10): # 高さの分割数に合わせる 18
        for x in range(-10, 12): # 幅の分割数に合わせる 22
            if player.x < 10:
                X = (x+player.x)*M_WIDTH
            elif player.x > map_w-12:
                # 画面に見えない左側を引いている(map_w-x_range)
                X = (x-(map_w-x_range)+player.x)*M_WIDTH
            else:
                X = (x+10)*M_WIDTH
            if player.y < 8:
                Y = (y+player.y)*M_HEIGHT
            elif player.y > map_h-12:
                Y = (y-(map_h-y_range)+player.y)*M_HEIGHT
            else:
                Y = (y+8)*M_HEIGHT
            dx = player.x + x
            dy = player.y + y
            if 0 <= dx and dx < map_w and 0 <= dy and dy < map_h:
                bg.blit(imgmap[n_map[dy][dx]], [X, Y])

            # x=0,y=0の時にplayerを表示することは変わらない
            if x == 0 and y == 0: # 主人公キャラの表示
                bg.blit(player.img[player.a], [X, Y]) # 元はY-40、-40があると1ズレる
    draw_para(bg, fnt, player) # 主人公の能力を表示

 

最初に分割数を変数に入れています。

    x_range = int(bg.get_width() / M_WIDTH) # 画面の横幅の分割数(for文のレンジ) 22
    y_range = int(bg.get_height() / M_HEIGHT) # 画面の高さの分割数(for文のレンジ) 18

 

for文は以下のレンジです。

    for y in range(-8, 10): # 高さの分割数に合わせる 18
        for x in range(-10, 12): # 幅の分割数に合わせる 22

 

なので、プレイヤーがいる位置によって
場合分けをしました。

イメージです。(左下と右下は割愛)

左上

 

右上

 

この場合分けを入れると以下のようになりますが
さっきと逆が黒くなりました(^_^;)

 

さっきの画像

 

と、いうわけでもう少し変えます。

以下ではない時(else)を追加します

            if 0 <= dx and dx < map_w and 0 <= dy and dy < map_h:
                bg.blit(imgmap[n_map[dy][dx]], [X, Y])

 

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

            if 0 <= dx and dx < map_w and 0 <= dy and dy < map_h:
                bg.blit(imgmap[n_map[dy][dx]], [X, Y])
            else:
                if dx < 0: # 右側が見切れるので、見切れた分だけ表示させる
                    X = (x+player.x+x_range)*M_WIDTH
                    if dy < 0: # 下側が見切れるので、見切れた分だけ表示させる
                        Y = (y+player.y+y_range)*M_HEIGHT
                        bg.blit(imgmap[n_map[dy+y_range][dx+x_range]], [X, Y])
                    elif dy >= map_h: # 上側が見切れるので、見切れた分だけ表示させる
                        Y = (y-(map_h-y_range)+player.y)*M_HEIGHT - bg.get_height()
                        bg.blit(imgmap[n_map[dy-y_range][dx+x_range]], [X, Y])
                    else:
                        bg.blit(imgmap[n_map[dy][dx+x_range]], [X, Y])
                elif dx >= map_w: # dx < map_wの部分は「if 0 <= dx and dx < map_w and 0 <= dy and dy < map_h:」で表示
                    # 画面に見えない左側を引いている(map_w-x_range)
                    # 画面左から途中を描画、途中から右側は「dx < map_w」で表示
                    X = (x-(map_w-x_range)+player.x)*M_WIDTH - bg.get_width()
                    if dy < 0:
                        Y = (y+player.y+y_range)*M_HEIGHT
                        bg.blit(imgmap[n_map[dy+y_range][dx-x_range]], [X, Y])
                    elif dy >= map_h:
                        Y = (y-(map_h-y_range)+player.y)*M_HEIGHT - bg.get_height()
                        bg.blit(imgmap[n_map[dy-y_range][dx-x_range]], [X, Y])
                    else:
                        bg.blit(imgmap[n_map[dy][dx-x_range]], [X, Y])
                else:
                    if dy < 0:
                        Y = (y+player.y+y_range)*M_HEIGHT
                        bg.blit(imgmap[n_map[dy+y_range][dx]], [X, Y])
                    elif dy >= map_h:
                        Y = (y-(map_h-y_range)+player.y)*M_HEIGHT - bg.get_height()
                        bg.blit(imgmap[n_map[dy-y_range][dx]], [X, Y])
                    # else:は「if 0 <= dx and dx < map_w and 0 <= dy and dy < map_h:」
            # x=0,y=0の時にplayerを表示することは変わらない
            if x == 0 and y == 0: # 主人公キャラの表示
                bg.blit(player.img[player.a], [X, Y]) # 元はY-40、-40があると1ズレる
    draw_para(bg, fnt, player) # 主人公の能力を表示

 

それぞれ以下のような条件の時に
黒色の部分の画像を表示します。※はずです(^_^;)
(左下と右下は割愛)

 

 

表示するようにした結果の画像です。

 

あと1つ、キャラ表示も少し変えています。
Y-40 から Yに変更しています。

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

 

Y-40の場合(yが0の時、キャラが消える)

 

Yの場合(yが0の時、キャラが一番上)

これもこうなったから
Y-40からYに変更してみた、というだけです(^_^;)

 

最初にもお伝えした通り、試しにこんな変更にしてみたら
やりたいことが出来ただけです。。

それぞれの条件文の中で
print(f"X {x},{dx},{X}")
print(f"Y {y},{dy},{Y}")
のようなことをして
値がどうなるか確認しながら進めて
うまく行ったので、このように変更しました。

 

もっと上手い分け方とかあると思いますが、、
今回は以上です!(`・ω・´)

 

 

最後に

今回はマップの1マスの大きさを変えました。

また、プレイヤーがマップの端に動いた時、
端を黒にせずに画像が表示されるように変更しました。

次回はマップ(エリア)ごとに出現するモンスターが
変わるようにしたいと思います。

まとめサイトへ

 

 

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

 

 

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

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