Pyxelでアクションゲームを作る
以前の記事で,Python向けレトロゲームエンジン「Pyxel(ピクセル)」を使ってキャラクターがジャンプするゲームの例を紹介しました。
kinutani.hateblo.jp
上記記事で作成したプログラムでは,128×128ドットのステージで画面の表示を固定していました。今回はステージのサイズを大きくして,キャラクターの移動に合わせてゲーム画面をスクロール(表示位置を変える)する例を紹介します。
※ リソースファイルとソースコードは上記記事のものをベースにして改造していきます。
スクロール処理のイメージ
まずはタイルマップエディタで大きなステージを作成します。
プログラムはこのステージの一部を切り出して画面に表示します。切り出す範囲の左上座標を管理するための変数として,scroll_x,scroll_y を用意します。キャラクターの移動に合わせてscroll_x,scroll_y の値を変えることで,画面に表示されるステージの位置も変化し画面のスクロールが行われます。
横方向のスクロール処理
横方向のスクロールの仕様を決めます。キャラクターが画面中央で動く場合はスクロールを行わずに,画面端に移動したときにだけスクロールを行うようにしたいと思います。
画面端からの線の位置は右側48ドット,左側40ドットとしておきます。(右側はキャラの幅分8ドット多くしています)
キャラクターを表示するx座標の変数 x と scroll_x の値更新のイメージは以下のようになります。
【ソースコード】はこちらのリンクから確認してください(Googleドキュメント)
list06_01.py 抜粋
STAGE_WIDTH = 128 * 3 STAGE_HEIGHT = 128 * 1 LEFT_LINE = 40 RIGHT_LINE = pyxel.width - 48 scroll_x = 0 scroll_y = 0
・タイルマップで作成したステージ全体の幅と高さを STAGE_WIDTH と STAGE_HEIGHT に設定しています。今回はタイルマップエディタで横3画面分のステージを作成しました。横方向にもっと長いステージを作成した人は STAGE_WIDTH を大きくしてください。
・スクロールを行う境界線(画面両端からの線)の位置を LEFT_LINE と RIGHT_LINE としました。(値はゲーム画面のサイズにより調整してください。変数名も BORDER や LIMIT の方がふさわしかったと思います)
def chkwall(cx,cy): c = 0 if cx < 0 or STAGE_WIDTH -8 < cx: c = c + 1 if STAGE_HEIGHT < cy: c = c + 1 ・・・ return c
・chkwall()関数の右限界と下限界の判定を画面の幅/高さではなく,ステージの幅と高さとに変更しています。
def update(): global scroll_x,scroll_y,x,y,dx,dy,pldir,jump,score ・・・ # 左方向へのスクロール if x < scroll_x + LEFT_LINE: scroll_x = x - LEFT_LINE if scroll_x < 0: scroll_x = 0 # 右方向へのスクロール if scroll_x + RIGHT_LINE < x: scroll_x = x - RIGHT_LINE if STAGE_WIDTH - pyxel.width < scroll_x: scroll_x = STAGE_WIDTH - pyxel.width
・update()関数でx座標の決定後に,その値がスクロールを行う境界線を越えたかどうかの判定を行います。x座標がLEFT_LINEの位置より小さければscroll_xを更新します。ただしscroll_xは0より小さくならないようにしています。
・x座標がRIGHT_LINEの位置を超えた場合はscroll_xを更新します。右端で一画面分表示した位置がscroll_xの最大値になるようにステージ幅と画面幅で計算しています。
def draw(): pyxel.cls(0) pyxel.camera() pyxel.bltm(0,0, 0, scroll_x,scroll_y, pyxel.width,pyxel.height, 0) pyxel.camera(scroll_x,scroll_y) pyxel.blt( x, y, 0, 0, 8, pldir*8,8, 0) if 10 == score : pyxel.text(scroll_x+45,scroll_y+56,"FINISH!",7) return
・pyxel.camera(x,y)
画面の左上隅の座標を (x, y) に変更します。camera()で左上隅の座標を (0, 0) にリセットします。
pyxel.camera()
pyxel.bltm(0,0, 0, scroll_x,scroll_y, pyxel.width,pyxel.height, 0)
タイルマップ表示前に座標をリセットしてから,画面一杯にタイルマップを表示させています。
・ pyxel.camera(scroll_x,scroll_y)
この命令で画面左上の座標をスクロール位置に変更できるので,キャラクターの表示位置に x, y の値をそのまま使うことができます。(カメラの位置を変更しない場合は,キャラのx座標からscroll_xを引いて画面上の位置を決めるなどの対応が必要)
・pyxel.text(scroll_x+45,scroll_y+56,"FINISH!",7)
FINISH!のテキストがスクロール後の画面に表示できるように座標指定を変更しました。
実行結果
縦方向のスクロール処理
縦方向のスクロールも同様にキャラクターの上下に境界線を決めてスクロールさせることにします。
タイルマップエディタでステージを縦方向に広げてリソースファイルを更新して,ソースコードにy座標と scroll_y の処理を追加しましょう。
【ソースコード】はこちらのリンクから確認してください(Googleドキュメント)
list06_02.py 抜粋
STAGE_WIDTH = 128 * 3 STAGE_HEIGHT = 128 * 2 LEFT_LINE = 40 RIGHT_LINE = pyxel.width - 48 UPPER_LINE = 40 BOTTOM_LINE = pyxel.height - 40 scroll_x = 0 scroll_y = 0
・STAGE_HEIGHT を2画面分にしました。
・UPPER_LINE と BOTTOM_LINE で上下の境界線の位置を設定します。(下側にキャラの高さ分の8ドットがありませんが作成するゲームに合わせて調整してみてください)
# 上方向へのスクロール if y < scroll_y + UPPER_LINE: scroll_y = y - UPPER_LINE if scroll_y < 0: scroll_y = 0 # 下方向へのスクロール if scroll_y + BOTTOM_LINE < y: scroll_y = y - BOTTOM_LINE if STAGE_HEIGHT - pyxel.height < scroll_y: scroll_y = STAGE_HEIGHT - pyxel.height
・update()関数のジャンプと落下処理でy座標の決定後に,スクロール処理を追加します。
上側の境界線を越えれば scroll_y を減らしてキャラが境界線上になるようにする。
下側の境界線を越えれば scroll_y を増やしてキャラが境界線上になるようにする。
実行結果
以上で,キャラクターの移動に合わせて画面をスクロールさせる処理が実現できました。
本処理はPyxel公式サンプル「10_platformer.py マップのある横スクロールアクションゲーム」を参考にしています。(変数名 scroll_x や SCROLL_BORDER_X で検索して処理を追ってみてください)
スクロール以外にも,キャラクターのアニメーションや敵キャラの出現,ゲームオーバーの処理などソースコードを参照してみてください。