コンテンツにスキップ

迷路ゲーム

マップ

画像

64×64の画像を用意し、この画像をタイルとして縦8枚、横8枚に並べします。

import pgzrun

TILE_SIZE = 64
WIDTH = TILE_SIZE * 8
HEIGHT = TILE_SIZE * 8

画像は empty、wall、goalの3種類です。それをどう配置するかを2次元リストで表します。

tiles = ['empty', 'wall', 'goal']

maze = [
    [1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 1, 2, 0, 1],
    [1, 0, 1, 0, 1, 1, 0, 1],
    [1, 0, 1, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 0, 1],
    [1, 0, 1, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1]
]

これをdrawで描画します。

def draw():
    screen.clear()
    for row in range(len(maze)):
        for column in range(len(maze[row])):
            x = column * TILE_SIZE
            y = row * TILE_SIZE
            tile = tiles[maze[row][column]]
            screen.blit(tile, (x, y))
pgzrun.go()

プレイヤーの表示と移動

プレイヤーを用意します。

player = Actor("player", anchor=(0, 0), pos=(1 * TILE_SIZE, 1 * TILE_SIZE))

これをdrawで描画します。

player.draw()

キーボードで移動できるようにします。

def on_key_down(key):
    # 現在位置取得
    row = int(player.y / TILE_SIZE)
    column = int(player.x / TILE_SIZE)

    # 移動    
    if key == keys.UP:
        row = row - 1
    if key == keys.DOWN:
        row = row + 1
    if key == keys.LEFT:
        column = column - 1
    if key == keys.RIGHT:
        column = column + 1

    # 新たな位置設定
    player.x = column * TILE_SIZE
    player.y = row * TILE_SIZE

壁には移動できないようにします。ゴールに到達したら終了です。

tile = tiles[maze[row][column]]
if tile == 'empty':
    player.x = column * TILE_SIZE
    player.y = row * TILE_SIZE
elif tile == 'goal':
    print("Well done")
    exit()

移動はアニメーションで移動するようにします。

if tile == 'empty':
    x = column * TILE_SIZE
    y = row * TILE_SIZE
    animate(player, pos=(x, y), duration=0.2)

敵の配置と移動

敵を配置します。

enemy = Actor("enemy", anchor=(0, 0), pos=(3 * TILE_SIZE, 6 * TILE_SIZE))

drawで描画する。

enemy.draw()

敵は上下に移動します。移動方向をvy属性で示します。

enemy.vy = 1

敵の移動タイミングはキーを押したとき、プレイヤーが移動した後です。

row = int(enemy.y / TILE_SIZE)
column = int(enemy.x / TILE_SIZE)
row = row + enemy.vy

移動先タイルが壁の場合、移動方向を逆にします。

tile = tiles[maze[row][column]]
if not tile == 'wall':
    x = column * TILE_SIZE
    y = row * TILE_SIZE
    animate(enemy, duration=0.1, pos=(x, y))
else:
    enemy.vy = enemy.vy * -1

敵とプレイヤーが衝突したらプレイヤーの負けとなります。

if enemy.colliderect(player):
    print("You died")
    exit()        

鍵とドア

タイルの種類にドアと鍵を追加します。鍵が無ければドアが開きません。

tiles = ['empty', 'wall', 'goal', 'door', 'key']

地図に3(ドア)と4(鍵)を加えます。

maze = [
    [1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 1, 2, 0, 1],
    [1, 0, 1, 0, 1, 1, 3, 1],
    [1, 0, 1, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 0, 1],
    [1, 0, 1, 4, 1, 0, 0, 1],
    [1, 0, 1, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1]
]

鍵を持っているかどうかの属性hashkeyをプレイヤーに設定します。

player.haskey = False

ゴール判定の後にif文を追加します。鍵のマスに来たときに鍵を持たせるようにします。 鍵のマスは空きマスに変えます。

elif tile == 'key':
    player.haskey = True
    maze[row][column] = 0

ドアのところまで来たときに鍵を持っていたらドアを空きマスの変えます。

elif tile == 'door' and player.haskey:
    maze[row][column] = 0