レッスン93
レッスンの目標⌗
Pythonを使ったPyxelというというレトロゲームエンジンを使ってレトロゲームをつくってみましょう。
Pyxel Code Maker⌗
Pyxel Code Makerを使うとブラウザで簡単にPyxelを試すことができます。
Pyxel Code Makerにアクセスすると、左側にサンプルコードが表示され、右側にその実行結果が出力されます。
サンプルでは、右の画面をクリックすると中央に「Pyxel Code Maker」という文字が表示され、人の顔のような黄色いキャラクターが中央の左から右に移動します。
プログラムの説明⌗
import pyxel # pyxelライブラリを呼び出します。
class App: # メインプログラム
def __init__(self): 初期化関数
pyxel.init(160, 120) # 画面を160x120で初期化します
pyxel.load("my_resource.pyxres") # 画像データを読み込みます
self.x = 0 # 画像のx方向の表示位置を0に設定します。
pyxel.run(self.update, self.draw) # 更新関数と描画関数を指定してメインプログラムを実行します。
def update(self): # 更新関数
self.x += 1 # 更新のたびに画像のx方向に表示位置を1つずつ増やします
if self.x >= pyxel.width: # 右端まで到達したら
self.x = 0 # 画像の位置を左端(0)に戻します
def draw(self): # 描画関数
pyxel.cls(0) # 画面をクリアします
pyxel.blt(self.x, 60, 0, 0, 0, 8, 8, 2) # (x, 60)の位置に8x8の画像を描画します。
pyxel.text(48, 53, "Pyxel Code Maker", pyxel.rndi(1, 15))
# (48, 53)の位置に「Pyxel Code Maker」という文字を表示します。
# 色は毎回ランダムに変わります。(1から15のパレット色の間で)
App() # メインプログラムを実行します
敵のキャラクターを作ろう⌗
敵のキャラクターを作ってみましょう。
画面の上の「Res」というタブを押してください。
左側がプログラムから画像編集に切り替わります。
画像は上下左右に縦横8ピクセルずつ、4つの部分に分割されていて現在表示されているキャラクターは左上に表示されています。なお、キャラクターの上下左右に紫色の部分がありますが、これはpyxel.blt(self.x, 60, 0, 0, 0, 8, 8, 2)の最後の「2」の部分で2番めのパレット色(紫色)が透明になるという指定にんっているので、右側の画面上では表示されていません。
現在表示されているキャラクターを変えたいときは、左上の部分を書き換えます。
今回は、新しい敵キャラクターを作るので、右上の8x8に部分に新規のキャラクターを書き加えます。
左下の16色のパレットを選んで、好きなキャラクターを作ってみましょう。透明にしたい部分は今回も2番めのパレット色(紫色)で書きましょう。
敵のキャラクターを表示してみよう⌗
右上の8x8の部分に敵のキャラクターを作成したら、画面の上の「Code」というタブを押します。左側が元のプログラム画面に戻ります。
pyxel.blt(self.x, 60, 0, 0, 0, 8, 8, 2)の部分を
pyxel.blt(self.x, 60, 0, 8, 0, 8, 8, 2)に書き換えて、画面の上の「Run」というタブを押してください。
移動するキャラクターが、先ほど作成した敵のキャラクターに変わります。
pyxel.blt(self.x, 60, 0, a, b, c, d, 2)のa, b, c, dの部分は16x16の元画像から(a, b)の位置から(c, d)の画像を切り出すという意味です。
最初は(0, 0, 8, 8)となっていたので、元画像の左上(0, 0)から8 x 8分の画像を切り出します。
変更後は(8, 0, 8, 8)となっていたので、元画像から左上から右に8ピクセル移動した位置(8, 0)から8 x 8分の画像を切り出します。
元のキャラクターと、敵のキャラクターを両方表示してみよう⌗
元のキャラクターと、新しく作った敵のキャラクターを両方表示してみましょう。
同じ位置に表示すると上書きされてしまって1つのキャラクターしか見えなくなってしまうので、それぞれ表示する位置を変えてみましょう。
一番簡単なのは、2つのキャラクターで表示するyの位置(高さ方向)を変えることです。
先ほど修正した部分を以下のように書き換えてみましょう。
pyxel.blt(self.x, 60, 0, 0, 0, 8, 8, 2)
pyxel.blt(self.x, 40, 0, 8, 0, 8, 8, 2)
上に敵キャラクター、下に元のキャラクターが同じx位置に表示されるようになります。
敵のキャラクターを反対方向に移動させてみよう⌗
元のキャラクターと敵のキャラクターが同じ方向に移動していてはおもしろくないので、敵のキャラクターは逆方向に移動させてみましょう。このときyの位置(高さ方向)は同じにしてみましょう。
まず、敵のキャラクターのx位置の変数としてself.exを新たに作成しまします。
def __init__(self)のself.x = 0の後にself.ex = pyxel.widthを追加します。pixel.widthというのは画面の右端の位置を意味します。
左に移動する部分はupdate(self)の後ろに以下のプログラムを追加します。
def update(self):
...
self.ex -= 1
if self.ex <= 0:
self.ex = pyxel.width + 8
これで、敵は左に進み、左端に着いたら右端に移動します。
最後に、def draw(self)の敵の画像を表示する部分を
pyxel.blt(self.ex, 60, 0, 8, 0, 8, 8, 2)に書き換えます。
同じ高さで元のキャラクターと敵のキャラクターが反対方向に交差するように移動します。
元のキャラクターをジャンプさせて、敵のキャラクターからよけられるようにしよう⌗
このままだと毎回敵のキャラクターとぶつかってしまうので、元のキャラクターをジャンプさせて、敵のキャラクターとぶつからないようにしてみましょう。
スペースボタンを押したらジャンプするようにします。
ジャンプするために以下のような値をもたせます。
y … 高さ
vy… 高さ方向の速度
g… 重力
式は以下の通りです。
vy は毎フレーム g ずつ増える
y += vy
初期値を以下のように追加します。
def __init__(self):
...
self.y = 60
self.vy = 0
self.g = 0.4
self.jump = False
...
以下のように更新します。
def update(self):
# スペースキーでジャンプする
if pyxel.btnp(pyxel.KEY_SPACE) and not self.jump:
self.jump = True
self.vy = -5
# ジャンプ後の動き
if self.jump:
self.vy += self.g
self.y += self.vy
# 地面に落ちたら終了
if self.y > 60:
self.y = 60
self.jump = False
...
描画を以下のように変更します。
def draw(self):
...
pyxel.blt(self.x, self.y, 0, 0, 0, 8, 8, 2)
...
これで、スペースキーを押すと、元のキャラクターがジャンプするようになり、敵をよけれるようになりました。
敵のキャラクターにぶつかったらゲームオーバーになる⌗
このままだと、敵のキャラクターにぶつかってもすれちがうだけなので、敵のキャラクターにぶつかったらゲームオーバーになるようにします。
現在表示されている「Pyxel Code Maker」を「Game Over」に変更し、通常は非表示としてゲームオーバーになったら表示するようにします。このとき、キャラクターは非表示にします。
元のキャラクターと敵のキャラクターがぶつかったかどうかは以下の式で判断します。
if abs(self.x - self.ex) < 6 and abs(self.y - 60) < 6:
元キャラクターと敵キャラクターのx位置の差が6ピクセル以内かつ、y位置の差が6ピクセル以内のとき、ぶつかったと判断しています。
初期化部分にgameoverフラグを追加します。
def __init__(self):
...
self.gameover = False
...
更新部分でぶつかったかどうかの判断をし、ぶつかったらgameoverフラグをTrueにします。
def update(self):
...
if abs(self.x - self.ex) < 6 and abs(self.y - 60) < 6:
self.gameover = True
描画部分でgameoverフラグによって描画処理を変えます
def draw(self):
pyxel.cls(0)
if self.gameover:
pyxel.text(48, 53, "Game Over", pyxel.rndi(1, 15))
else:
pyxel.blt(self.x, self.y, 0, 0, 0, 8, 8, 2)
pyxel.blt(self.ex, 60, 0, 8, 0, 8, 8, 2)
これでぶつかったときだけ、ゲームオーバーになります。
自由に改造してゲームをおもしろくしよう⌗
あとは自分のアイデアでゲームを面白くしてみましょう。
-
敵にぶつからないで右端までいけたら得点を加算する
-
敵のキャラクターのスピードを登場するたびにランダムに変化させる
-
キャラクターがぶつかってもすぐにゲームオーバーにせず、ライフの値をもたせて、ぶつかったらライフを減らし、ライフが0になったらゲームオーバーにする
-
敵のキャラクターが複数登場するようにする
など、いろいろ工夫してください。