見出し画像

PICO-8で遊ぼう(スプライトをいっぱい出したいんじゃ編

表題のとおりです。
まずは単純にいっぱいスプライトを出すプログラムを書きます。

main

ball

ui / bg / sprite

RUN

実行すると緑のボールが50個、ランダムに等速直線運動し壁で反射します。
zキー(○ボタン)を押すとボールが増えます。

STATS(ctrl+p)を表示して動作させていますが、ボールの動作が単純ですので1800個くらいまでなら30FPSを維持しています。

ボール同士の衝突判定

上記のプログラムにボール同士の衝突判定処理is_collision()を加えてボールを反射させる動作を入れてみたいと思います。

is_collison()

いわゆる矩形同士の衝突判定アルゴリズムです。
それぞれの矩形の大きさを足して半分にしたもの(dw,dh)と矩形同士の距離(dx,dy)を比較してdx,dyのどちらともdw,dhより小さければ衝突したとみなします。

ball collision

is_collision()balls全件ループさせて衝突判定をおこないます。
ボール同士が衝突したときの反射アルゴリズムはchatGPT様に作ってもらいました。

RUN

zキー(○ボタン)を押してボールを増やしていくと67個を超えたあたりで処理落ちが発生します。
ボール1個のupdate処理に対してballs全件をループさせているのでボールがちょっと増えると計算量が爆発してしまいます。
やってることはボールの衝突判定ですので全件ループさせなくてもボールの近隣にあるボールだけを対象にできれば処理が軽くなりそうです。

bucket hash lib

ちょうどよく、求めてたpico-8用に書かれていたライブラリあるのでそれを拝借したいと思います。
ボール座標x,yをある程度(size)に丸めたものをハッシュ値とした配列に入れることでボールの衝突判定を総当たりから周囲の範囲だけに絞り込むことができるようになり処理の高速化をはかれます。

衝突判定(ball collision)を総当たりからbucket hash libを使用した形に変更します。
bget()で周囲のボールのみの配列が返ってきます。
bstore()でbucket hashの配列に再挿入します。

ボールが100個を超えても処理落ちしなくなりました。

STATS(ctrl+p)を表示して動作させてみましたがギリ300個くらいまでは30fpsを保ってくれます。
300/67=4.47…およそ4倍くらい高速化できたようです。

bucket hash libいいね!

bucket hashを可視化してみた


この記事が気に入ったらサポートをしてみませんか?