【33】いっしょにまなぼう

Breakout #33 - Screenshake! - Pico-8 Hero PICO-8
Breakout #33 - Screenshake! - Pico-8 Hero

 TeamworkCastが配信している、PICO-8のチュートリアル動画の解説を連載中です。

前回はこちら

そして今回の動画はこちらです。

Breakout #33 – Screenshake! – Pico-8 Hero

【解説メモ】

今回は、画面エフェクトのスクリーンシェイクを実装する。

function _init()〜endの中にshake=0を書き込む

ソースコードの最後に画面を揺らす新しい関数、doshake()を記述する。

function doshake()
    -- -16 +16
    local shakex=16-rnd(32)
    local shakey=16-rnd(32)

    shakex=shakex*shake
    shakey=shakey*shake

    camera(shakex,shakey)

    shake=shake*0.95
    if shake<0.05 then
        shake=0
    end
end

X座標、Y座標の幅を-16〜16にしてランダムで導き、それにその振れ幅である変数shakeをかけることで、-16〜16内にランダムにカメラが動き、変数shakeに0.95をかけていくことで、少しずつおさまっていくようになる。

function _draw()〜endの中の頭に、doshake()を記述。

function updateball(bi)〜endの中のif ball_box(nextx,nexty,pad_x,pad_y,pad_w,pad_h) thenの後ろにshake+=1を記述して実行する。

ボールxパッドで揺らす
ボールxパッドで揺らす

確認ができたので、先程記述したshake+=1を削除する。

function updateball(bi)〜endの中のif #ball > 1 thenの後にshake+=0.15を加える。

elseの後にshake+=0.4を加える。

これで、マルチボールで複数ボールがある時のミスは小さく揺れ(shake+=0.15)、ボールが一つの時は大きく揺れる(shake+=0.4)。

複数と単一のボールのミスで揺れ方を変える
複数と単一のボールのミスで揺れ方を変える

function explodebrick(_i)〜endの中の最後にshake+=0.4を記述。

そして、ステージデータをlevels[1] = “h9h/p9p//s9s”にして、爆発ブロックを手前に一列並べるようにした。

で、実行するとこの有様。

爆発ブロックを試すが、揺れすぎた
爆発ブロックを試すが、揺れすぎた

揺れは収まらず、ゲームが続行できなくなってしまった。

爆発ブロックを1つにしても、似たような結果になってしまった。

爆発ブロックが1つでも大きな揺れになってしまう
爆発ブロックが1つでも大きな揺れになってしまう

shake+=0.4をhitbrick(j,false)の後ろへ移動し、その後ろに

if shake>1 then
    shake=1
end

を記述して、shake変数の内容が1よりも大きくならないようにする。

そしてステージデータをlevels[1] = “b9b/p9p/sbsbsbsbsbs”にして実行する(爆発の連鎖はしないようにしている)。

すると、爆発して隣のブロックが消えるときにしか揺れが起こらない(shake+=0.4の記述がhitbrick(j,false)の後ろだから)。

そこで、

shake+=0.4
if shake>1 then
    shake=1
end

をcheckexplosions()関数のexplodebrick(i)の後に移動する。

実行すると、また大きな揺れになってしまう。

原因を考えると、shake+=0.4を記述したところは、function explodebrick(_i)関数内。

その関数は、引数(_i)で該当するブロックのv要素(存在しているか いないか)をfalseにして存在していないようにし、他のブロックをチェックして隣接していればボールが当たった処理をそのブロックに行うという内容で、その最後にshake+=0.4を実行している。

そこで、ゲーム中にshake変数の内容がどうなっているのか調べてみたら(printh関数でコンソールに表示)、ある時に50.175となっていた(0.4を追加しているので100回以上実行されていることになる)。

この関数が何度も実行されているということは、関数がどこで呼び出しているかを確認すると、checkexplosions()関数内で実行されている。

実行する条件は、bricks[i].t == “z”の時だ。

t要素は、何を意味しているかというと、ブロックの種類を指している。

ここでチェックしているのは、t要素だけで、存在のv要素はチェックしていない。

なので、ブロックが消えてもあるかのごとく処理されてしまい、予想以上の揺れが生み出されてしまうことになる。

しかも、checkexplosions()関数は、update_game()で毎度呼び出されている。

そこで、checkexplosions()〜endの中のif bricks[i].t == “z” thenとif bricks[i].t == “zz” thenにand bricks[i].vを加える(bricks[i].vの内容は、bool値でtrueかfalseのどちらか)。

すると、思ったように揺れが起こり収まる。

爆発ブロックの揺れを修正
爆発ブロックの揺れを修正

これで、爆発ブロックに当たった時に揺れるようになる。

function draw_game()内のはじめの所cls(1)をcls() rectfill(0,0,127,127,1)とすることで、揺れた時に、背景の1番の色(紺色)が上からはみ出てこないようになる(rectfill()関数で描画しているので、カメラの座標の影響を受け追従する)。

【自分の感想】

今回は、この「揺れ過ぎる現象」の理由を探るために変数などの内容をprinthで表示させたりして、解析を行った(うやむやにしたくなかったので)。

改めて、消えたブロックもテーブルの中ではデータとして存在していて、ただv要素がfalseになっているだけなんだと思わされた。

この「?」を「!」にするために解析作業が、自分の中で面白くなってきている。

時間はかかってしまったが、色々なことを知り得たと思う(それが大切と信じている)。

コメント

タイトルとURLをコピーしました