Pyxel 画面をスクロールさせる例(アクションゲーム)

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 で検索して処理を追ってみてください)
 スクロール以外にも,キャラクターのアニメーションや敵キャラの出現,ゲームオーバーの処理などソースコードを参照してみてください。

 

関連記事

 kinutani.hateblo.jp