3 迷路ゲーム

迷路ゲームを作成します(maze.py)。 迷路内の鍵を取得しドアを開けてゴールを目指します。鍵は2つあり、2つとも取得しなければなりません。
3.1 マップ
64×64の画像を用意し、この画像をタイルとして縦12枚、横12枚に並べます。 ですので、幅と高さは64×12になります。これらを定数にします、
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "100,100"
import pgzrun
from pgzero.builtins import *
TILE_SIZE = 64
ROW_COUNT = 12 #行数
COL_COUNT = 12
WIDTH = TILE_SIZE * ROW_COUNT
HEIGHT = TILE_SIZE * COL_COUNT
画像は empty、wall、key, door,goal の5種類です。それをどう配置するかを2次元リストで表します。
tiles = ['empty', 'wall', 'goal', 'key', 'door']
maze = [
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,1,1,0,0,3,1],
[1,0,1,0,1,0,1,1,0,1,0,1],
[1,0,1,0,0,0,0,0,0,0,0,1],
[1,0,1,0,1,1,1,1,1,0,1,1],
[1,0,0,0,0,0,0,0,0,0,1,1],
[1,0,1,0,1,1,0,1,0,1,1,1],
[1,0,1,0,0,0,3,1,0,0,4,1],
[1,0,1,0,1,0,1,1,1,1,0,1],
[1,0,0,0,0,0,1,1,1,1,0,1],
[1,1,1,1,1,1,1,1,1,1,2,1],
[1,1,1,1,1,1,1,1,1,1,1,1]
]
これを描画する関数draw_mazeを作成します。for文で0~12の繰り返しを行と列で行います。そのxとy座標を計算し、そこのタイルの画像を表示します。 screen.blit(画像, 座標)で表示できます。
def draw_maze():
for row in range(ROW_COUNT):
for col in range(COL_COUNT):
x = col * TILE_SIZE
y = row * TILE_SIZE
tile_type = maze[row][col]
screen.blit(tiles[tile_type], (x, y))
これをdraw関数で呼び出します。
def draw():
screen.clear()
draw_maze()
pgzrun.go()
3.2 プレイヤーの表示と移動
プレイヤーを用意します。初期位置は(1,1)です。ここに配置するため、anchorで基準点を左上にしています。
player = Actor("player", anchor=(0, 0), pos=(1 * TILE_SIZE, 1 * TILE_SIZE))
これをdrawで描画します。
player.draw()
キーボードで移動できるようにします。 まず、元の座標と押したキーから新たな座標を計算するnew_position関数を作成します。
def new_position(row, col, key):
new_row, new_col = row, col
# 移動
if key == keys.UP:
new_row = row - 1
elif key == keys.DOWN:
new_row = row + 1
elif key == keys.LEFT:
new_col = col - 1
elif key == keys.RIGHT:
new_col = col + 1
return new_row, new_col
これをon_key_downで呼び出します。現在位置はplayerのx、y座標をタイル幅で割って取得します。
def on_key_down(key):
# 現在位置取得
row = int(player.y / TILE_SIZE)
col = int(player.x / TILE_SIZE)
new_row, new_col = new_position(row, col, key)
移動先のタイルがempty(空)の場合、そこに移動します。
new_tile = maze[new_row][new_col] # 移動先タイル
if new_tile == 0: # empty
x = new_col * TILE_SIZE
y = new_row * TILE_SIZE
player.x = x
player.y = y
3.3 鍵とドア
鍵をいくつ持っているかの属性key_countをプレイヤーに設定します。
player.key_count = 0
鍵のマスに来たときに鍵の数を1増やします。 on_key_downのif文に追加します。鍵のマスは空きマスに変えます。
elif new_tile == 2: # key
player.key_count += 1
maze[new_row][new_col] = 0
ドアのところまで来たときに鍵を2つ持っていたらドアを空きマスに変えます。
elif new_tile == 3 and player.key_count == 2: # door
maze[new_row][new_col] = 0
これで鍵を2つ保持していたら、ドアを開けることが出来ます。
3.4 ゴール処理
ゲームの状態を表すstatusをプレイヤーに設定します。これはplayとgoalのどちらかです。
player.status = 'play'
ゴールのマスに来たときに状態をgoalに変更します。 on_key_downのif文に追加します。
elif new_tile == 4: # goal
player.status = 'goal'
ゴールしたら動けないようにします。
def on_key_down(key):
if player.status != 'play':
return
draw関数にゴールの表示を加えます。
if player.status == 'goal':
screen.draw.text("GOAL!!", midtop=(WIDTH//2, HEIGHT//2), fontsize=60, color='white')
3.5 アニメーション
現在、キャラクターが移動するときには、plyaerのxとyを更新しています。
if new_tile == 0: # empty
x = new_col * TILE_SIZE
y = new_row * TILE_SIZE
# この部分
player.x = x
player.y = y
これをanimate関数でアニメーション処理に変更します。アニメーション処理とはActor の属性(位置・透明度・角度など)を一定時間かけて変化させるためのものです。 animate(アクター, pos=位置, tween=変化方法, duration=時間)で指定します。
animate(player, pos=(x, y), tween='decelerate', duration=0.1)
tweenは以下を指定できます
- accelerate : だんだん速く動く
- decelerate : だんだん遅くなる
- bounce : バウンドするような動き
- linear : 一定速度(デフォルト)