Pygame Zero演習11(一筆書きゲーム)

Python

前回のしょぼいゲームよりはもう少しまともなゲームを作ってみます。

実行イメージ

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()

コメント