前回のしょぼいゲームよりはもう少しまともなゲームを作ってみます。
実行イメージ
game_hitofude.py
# Pygame Zero: 一筆書きゲーム
import pgzrun
# ゲーム状態
GAME = 1
GAMECLEAR = 2
GAMEOVER = 3
status = GAME
# キャラクタチップサイズ
CSIZE = 64 # 64x64
# 画面サイズ
WIDTH = CSIZE * 5 # 320px
HEIGHT = CSIZE * 5 # 320px
TITLE = "一筆書きゲーム"
# マップデータ
map = []
# プレイヤーを生成
px = py = 0 # プレイヤーのマップ上座標
xnext = ynext = 0 # プレイヤーの移動先位置
player = Actor("kero_nuri")
player.topleft = px * CSIZE, py * CSIZE # マップ上の座標を描画座標に変換してプレイヤーを描画
# 指定した種類のマップ座標を取得する関数
def getMapXY(type):
for y in range(5):
for x in range(5):
if map[y][x] == type:
return x, y
return -1, -1
# マップ座標に指定した種類のブロックをセットする関数
def setMapXY(x, y, type):
map[y][x] = type
# 初期化処理
def init():
global map, px, py, xnext, ynext, status
status = GAME
sounds.beat1.stop() # BGMストップ
# マップを生成(9:プレイヤー、1:壁、0:通路、2:すでに塗った場所)
map = [
[9, 0, 0, 0, 0],
[0, 1, 1, 0, 0],
[0, 1, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 1, 1, 1],
]
# プレイヤーのマップ上の座標を取得
px, py = getMapXY(9)
# 移動先を設定(初期状態は移動先がプレイヤー位置と同じ)
xnext, ynext = px, py
# BGMスタート
sounds.beat1.play(-1)
# 初期化処理実行(マップとプレイヤー位置を初期化)
init()
# 描画関数
def draw_map():
# 壁を描画
for y in range(5):
for x in range(5):
if map[y][x] == 1: # 壁
screen.blit("kabe", (x*CSIZE, y*CSIZE))
elif map[y][x] == 2: # 塗った通路
screen.blit("nuri", (x*CSIZE, y*CSIZE))
elif map[y][x] == 0: # 通路
screen.blit("no_kabe", (x*CSIZE, y*CSIZE))
# プレイヤーを移動先に描画
player.topleft = xnext * CSIZE, ynext * CSIZE
player.draw()
# 操作方法描画
draw_control()
# ゲームクリア・ゲームオーバーを描画
if status == GAMECLEAR:
game_clear()
elif status == GAMEOVER:
game_over()
# フレーム処理
def update():
global px, py, xnext, ynext, status
if status == GAME:
# 移動先が壁かどうか?
if check_kabe():
xnext, ynext = px, py # 移動先を元の位置に戻す
else: # 壁ではない
if check_nuri(): # 塗った場所かどうか?
status = GAMEOVER # ゲームオーバー
sounds.beat1.stop() # BGMストップ
setMapXY(px, py, 2) # プレイヤーの元位置を塗りブロックにする
setMapXY(xnext, ynext, 9) # 移動先にプレイヤーを設定
px, py = xnext, ynext # プレイヤーの現在位置と移動先を一致させる
# 全て塗ったらゲームクリア
if check_map():
status = GAMECLEAR
sounds.beat1.stop() # BGMストップ
sounds.fue.play()
# 画面描画
draw_map()
# キーボードが押された時の処理
def on_key_down(key):
global xnext, ynext
# キー入力をチェック
if key == keys.R: # リトライ
init()
if status != GAME:
return
if key == keys.A:
xnext -= 1 # 左
elif key == keys.D:
xnext += 1 # 右
elif key == keys.W:
ynext -= 1 # 上
elif key == keys.S:
ynext += 1 # 下
# 移動先が壁かどうかのチェック
def check_kabe():
if xnext < 0 or xnext >= 5 or ynext < 0 or ynext >= 5: # マップ外も壁と判定
return True
elif map[ynext][xnext] == 1: # 壁
return True
return False # 移動可能
# 塗った場所かどうかのチェック
def check_nuri():
if map[ynext][xnext] == 2: # 塗った場所である
return True
return False # まだ塗っていない
# 全て塗ったかのチェック
def check_map():
for y in range(5):
for x in range(5):
if map[y][x] == 0: # 塗り残しあり
return False
return True # 全て塗った
# 操作方法表示
def draw_control():
textcolor = 0, 150, 0 # 文字色
outlinecolor = 255, 255, 255 # 枠線色
screen.draw.text("Move: WSDA", (150, 260), owidth=3, ocolor=outlinecolor, color=textcolor, fontsize=24, fontname="honobonopop")
screen.draw.text("Retry: R", (150, 285), owidth=3, ocolor=outlinecolor, color=textcolor, fontsize=24, fontname="honobonopop")
# ゲームクリア表示
def game_clear():
textcolor = 0, 200, 0 # 文字色
outlinecolor = 255, 255, 255 # 枠線色
screen.draw.text("Game Clear!!!", (40, 140), owidth=2, ocolor=outlinecolor, color=textcolor, fontsize=32, fontname="honobonopop")
# ゲームオーバー表示
def game_over():
textcolor = 200, 0, 0 # 文字色
outlinecolor = 255, 255, 255 # 枠線色
screen.draw.text("Game OVER!", (60, 140), owidth=2, ocolor=outlinecolor, color=textcolor, fontsize=32, fontname="honobonopop")
# ゲームスタート
pgzrun.go()
コメント