PICO-8の怪

for i #t,1,-1 do の実行結果 PICO-8
for i #t,1,-1 do の実行結果

PICO-8でスネークゲーム「ピコニョロ」をつくっていて、どうもおかしい動作をすることに悩ませていました。

ステージ上の全てのカエルと、ヘビの体の全てに当たり判定をしているコードで、初めに頭の当たり判定をして、次に体の当たり判定を順番に行う様に書いてあります。

そして、頭と体の間にカエルが来た時にどうなるかを試したところ、カエルは食べられ(頭と当たった)、カエルに咬まれてヘビにダメージがありました(体と当たった)。

つまり、両方の動作がされたことになります。

希望する動作は、先に頭との当たり判定になった時、テーブルからカエルを削除しているので、「体の当たり判定は行われない」見解でした。

ですが「無いのに有る」・・・正に駐車場に掲げられている「空あり」です。

「なぜだろう?」理由がわかりませんので、printhで各変数の中を表示したり、別のプログラムで検証したりしました。

そこで、ある事実がわかりました。

まずは、このプログラムリストと実行結果を見てください。

for i in all(t) do のプログラム
for i in all(t) do のプログラム
for i in all(t) do の実行結果
for i in all(t) do の実行結果
for i #t,1,-1 do のプログラム
for i #t,1,-1 do のプログラム
for i #t,1,-1 do の実行結果
for i #t,1,-1 do の実行結果

似た動作をさせる2つのプログラムですが、先のはdel()命令でテーブルから座標要素を削除しているのにも関わらず、その後で要素の値を変更出来ています。

後のプログラムは、del()命令でテーブルから座標要素を削除した後に、要素にアクセスしようとするとnilだとエラーが出ています。

内部構造は わかりませんが、テーブルから要素を取り出すループにて、in all()を使う場合、要素を削除してもループ内ならアクセスできてしまうのです。

そしてループから抜けた後にアクセスすると、nilだとエラーが出ます。

なので、仕様だと受け止めて、

in all()を使う場合、要素を削除した後はアクセスしないようにする

というルールでコードを書くことです。

オフィシャルのBBSに書き込んでみようかな。

コメント

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