TeamworkCastが配信している、PICO-8のチュートリアル動画の解説を連載中です。
前回はこちら。
そして今回の動画はこちらです。
【解説メモ】
今回は、画面エフェクトのスクリーンシェイクを実装する。
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を記述して実行する。
確認ができたので、先程記述した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つにしても、似たような結果になってしまった。
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になっているだけなんだと思わされた。
この「?」を「!」にするために解析作業が、自分の中で面白くなってきている。
時間はかかってしまったが、色々なことを知り得たと思う(それが大切と信じている)。
コメント