【Pyxel】作りながら学ぶゲームプログラム (クリックゲーム)
今回はレトロゲームエンジン「Pyxel」を使って簡単なミニゲーム作成する手順を紹介します。
Pyxelのセットアップ手順はこちらの記事にまとめています。
■今回作成するゲーム
シンプルなクリックゲームを作成します。画面内を動き回るニャンコをクリックできるとゲームクリアとなります。
■画面の表示
まずは画面表示を実装します。テキストエディタを開いて、以下のコードを記述して「click_game.py」などのファイル名で保存します。
import pyxel
class App:
def __init__(self):
pyxel.init(160, 120, fps=60)
pyxel.run(self.update, self.draw)
def update(self):
pass
def draw(self):
pass
App()
ゲームを実行する最小限のコードとなります。コマンドプロンプトやターミナルから「python3 click_game.py」とコマンドを入力して実行すると黒い画面が表示されます。
■画像を表示する
ニャンコの画像を表示します。ニャンコの画像はこちらを右クリックして保存します
ダウンロード用:http://syun777.sakura.ne.jp/tmp/pyxel/cat.png
コードは以下のように修正します。
import pyxel
class App:
def __init__(self):
pyxel.init(160, 120, fps=60)
pyxel.image(0).load(0, 0, "cat.png") # 画像読み込み
pyxel.run(self.update, self.draw)
def update(self):
pass
def draw(self):
pyxel.cls(0) # 画面をクリアする
pyxel.blt(0, 0, 0, 0, 0, 16, 16, 5) # ニャンコ様を描画する
App()
pyxel.image(0).load() を使用して画像を読み込み、pixel.blt() で画像を描画します。pyxel.blt() の引数の説明は以下の通りです。
▼pyxel.blt(x, y, image_no, u, v, w, h, colkey)
・x: 描画座標(左上のX座標)
・y: 描画座標(左上のY座標)
・image_no: 画像番号
・u: 切り出しの左上のX座標
・v: 切り出しの左上のY座標
・w: 切り出す幅
・h: 切り出す高さ
・colkey: 抜き色(パレット番号)
実行すると画面の左上にニャンコの画像が描画されます。
■ニャンコを動かす
ニャンコが画面内を動き回るようにします。コードを以下のように修正します。
import pyxel
class App:
def __init__(self):
pyxel.init(160, 120, fps=30)
pyxel.image(0).load(0, 0, "cat.png") # 画像読み込み
# 変数初期化
self.x = 0
self.y = 0
self.vx = 1
self.vy = 1
pyxel.run(self.update, self.draw)
def update(self):
# 移動する
self.x += self.vx
self.y += self.vy
def draw(self):
pyxel.cls(0)
# XY座標を指定して描画する
pyxel.blt(self.x, self.y, 0, 0, 0, 16, 16, 5) # ニャンコ様を描画する
App()
__init__() での変数初期化で、self.x / self.y / self.vx / self.vy を追加しました。x, y はXY座標、vx, vy は移動量を格納する変数となります。
また、update() で座標に移動量を足しこむことで、移動処理を行っています。
最後の draw() で x, y の値を反映させることで、実際に描画される座標が変更されるようになります。
実行してみると、ニャンコが画面を動き回るようになります。
ただ、画面に出てしまうと、ニャンコは戻ってきません……。そこで画面外に出ないようにします。
update()に「画面外に出ないようにする」の部分のコードを書き加えます。
def update(self):
# 移動する
self.x += self.vx
self.y += self.vy
# 画面外に出ないようにする
if self.x < 0:
self.x = 0
self.vx *= -1 # 移動方向を反転する
if self.y < 0:
self.y = 0
self.vy *= -1 # 移動方向を反転する
if self.x > pyxel.width:
self.x = pyxel.width
self.vx *= -1 # 移動方向を反転する
if self.y > pyxel.height:
self.y = pyxel.height
self.vy *= -1 # 移動方向を反転する
def draw(self):
すると、画面端にぶつかった時に、ニャンコが逆方向に反射するようになりました。
しかし、右側と下側に衝突した場合には、画面外にはみ出てしまっています。これは画像の描画の原点が左上となっているためです。
例えば、(x, y) = (80, 40) に描画した場合は、上記のように描画されます。
そして画面外の判定を pyxel.width / pyxel.height そのままの値で判定しているため、このように画面外に出てしまいます。
これを解決するには、pyxel.width / pyxel.height をそのまま使うのではなく、画像サイズの 16px ぶん減らして判定します。
def update(self):
# 移動する
self.x += self.vx
self.y += self.vy
# 画面外に出ないようにする
if self.x < 0:
self.x = 0
self.vx *= -1 # 移動方向を反転する
if self.y < 0:
self.y = 0
self.vy *= -1 # 移動方向を反転する
if self.x > pyxel.width - 16: # 画像のサイズだけ引く
self.x = pyxel.width - 16
self.vx *= -1 # 移動方向を反転する
if self.y > pyxel.height - 16: # 画像のサイズだけ引く
self.y = pyxel.height - 16
self.vy *= -1 # 移動方向を反転する
update() の画面外判定を修正しました。
これで画面からはみ出すことがなくなりました。
■マウスクリックでニャンコを消せるようにする
クリックしたらニャンコを消せるようにします。
Pyxelはデフォルトでマウスカーソルが消えているので、まずはマウスを表示します。
def __init__(self):
pyxel.init(160, 120, fps=30)
pyxel.image(0).load(0, 0, "cat.png") # 画像読み込み
# 変数初期化
self.x = 0
self.y = 0
self.vx = 1
self.vy = 1
pyxel.mouse(True) # マウスカーソルを表示する
pyxel.run(self.update, self.draw)
__init__() に、pyxel.mouse(True) の記述を追加します。これでマウスカーソルが表示されるようになります。
次に、マウスクリックしたらニャンコが消えるようにします。"exists"フラグを用意して制御を行います。
import pyxel
class App:
def __init__(self):
pyxel.init(160, 120, fps=30)
pyxel.image(0).load(0, 0, "cat.png") # 画像読み込み
# 変数初期化
self.x = 0
self.y = 0
self.vx = 1
self.vy = 1
self.exists = True # ニャンコ様存在フラグ
pyxel.mouse(True) # マウスカーソルを表示する
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btnp(pyxel.MOUSE_LEFT_BUTTON):
# 左クリックしたらニャンコ様消滅
self.exists = False
if self.exists == False:
return # 消滅しているので更新不要
# 移動する
self.x += self.vx
self.y += self.vy
# 画面外に出ないようにする
if self.x < 0:
self.x = 0
self.vx *= -1 # 移動方向を反転する
if self.y < 0:
self.y = 0
self.vy *= -1 # 移動方向を反転する
if self.x > pyxel.width - 16:
self.x = pyxel.width - 16
self.vx *= -1 # 移動方向を反転する
if self.y > pyxel.height - 16:
self.y = pyxel.height - 16
self.vy *= -1 # 移動方向を反転する
def draw(self):
pyxel.cls(0)
if self.exists == False:
return # 消滅しているので更新不要
pyxel.blt(self.x, self.y, 0, 0, 0, 16, 16, 5) # ニャンコ様を描画する
App()
まず、__init__() で、exists フラグを True (ニャンコが存在している) にしておき、update() で pyxel.btnp(pyxel.MOUSE_LEFT_BUTTON) を使ってマウス左クッリをしたかどうか判定します。クリックしたなら、exists フラグを False にして存在しないようにします。
そして、update() / draw() にて、exists が False であれば、移動も描画も行わないようにします。これによりクリックしたらニャンコが消滅します。
クリックするとニャンコ様が消失
これだとゲームにならないので、ちゃんとニャンコをクリックしたら消えるようにします。
判定は以下のように行います。
ニャンコの画像は (x, y)を左上にして、16x16 の画像を表示しているので、この範囲内にマウスカーソルがあれば当たりとなります。
def update(self):
if pyxel.btnp(pyxel.MOUSE_LEFT_BUTTON):
left = self.x
top = self.y
right = self.x + 16
bottom = self.y + 16
if left <= pyxel.mouse_x <= right:
if top <= pyxel.mouse_y <= bottom:
self.exists = False
マウスクリックした際、左上を(left, top) 、右下を(right, bottom) とし、その範囲内に pyxel.mouse_x / pyxel.mouse_y が存在していた場合に exists フラグを False にしています。
実行するとニャンコの画像をクリックした時のみ、ニャンコが消滅するようになるはずです。
■ゲームクリアの表示
最後にゲームクリアの表示を実装します。draw() を以下のように修正します。
def draw(self):
pyxel.cls(0)
if self.exists == False:
pyxel.text(60, 50, "GAME CLEAR", 7)
return # 消滅しているので更新不要
pyxel.blt(self.x, self.y, 0, 0, 0, 16, 16, 5) # ニャンコ様を描画する
if self.exsits == False の判定が成立したら、pyxel.text() で "GAME CLEAR" の文字を表示するようにしました。
■完成データのダウンロード
完成データは以下からダウンロードできます。
http://syun777.sakura.ne.jp/tmp/pyxel/click.zip
もし、うまく動かなかった場合は、こちらを参考にしてみてください。
■次回予告
次回は、このクリックゲームを改造して複数のニャンコを表示できるようにしたいと思います。