Star: The Gathering ソースコード
整理前のコードは http://codetter.com/?p=1037
制限時間と☆の速度と円の広がる速さなどを変えてます。
HSPの物理エンジンOBAQのコリジョン処理でハマったこと
去年OBAQ使ったゲームを作ってる時にコリジョン関係でバグを何度か直して「もう直しきったはず!」と安心しきってたけど、今日やってみたらまだ残っててうんざりしたので、整理がてらメモ残しておきます。今後OBAQ使って同じような処理するゲーム作ることがあったら、あと同じようにうんざりしている人が他にいたら、役に立つかも。
初めに、あるオブジェクトAに他のオブジェクトBが当たったらBが消えてスコアが100入るケース。
#include "obaq.as" screen 0, 320, 240 qreset qgravity 0, 0 ; オブジェクトA設置 qaddpoly target, 4, 20, 30, 0, 10, 20, , 1, , 2 qtype target, type_bind score = 0 fcnt = 0 *mainLoop redraw 0 color : boxf qexec ; 60フレーム毎にオブジェクトB出現 if ((fcnt \ 60) == 0) { qaddpoly obj, 4, 60, 30, , 4, 4, , 2 qinertia obj, 1 qspeed obj, -0.2 } ; Aに当たったら消えてスコア加算 qcollision target qgetcol i, x, y if (i >= 0) { score += 100 qdel i } qdraw ; 情報表示 color 255, 255, 255 pos 30, 20 mes "score " + score redraw 1 await 15 fcnt++ goto *mainLoop
左にある中心点が赤いオブジェAに、中心点が緑のオブジェBが衝突してきてAに当たると消えて100点加算される。これは大丈夫、問題ない。
次に、B が2つ同時に A に当たるケース。
上のスクリプトのB出現の箇所を以下に置き換えて。
; 60フレーム毎にオブジェクトB出現 if ((fcnt \ 60) == 0) { repeat 2 qaddpoly obj, 4, 60, 25 + cnt * 10, , 4, 4, , 2 qinertia obj, 1 qspeed obj, -0.2 loop }
同じ大きさ速度のオブジェをY座標だけ変えて同時に出しているから、同時にAに当たって同時に消えて200点入っている…ように見えるけど、よく見ると同時に消えていない。
ウェイト増やして確認すると、当たったとき上が先に消えて次のフレームで下が消えている。
Bを3つに増やしてみる。
; 60フレーム毎にオブジェクトB出現 if ((fcnt \ 60) == 0) { repeat 3 qaddpoly obj, 4, 60, 22 + cnt * 8, , 4, 4, , 2 qinertia obj, 1 qspeed obj, -0.2 loop }
3つとも当っているはずなのに一番下だけ消えずに跳ね返ってしまう。
これはコリジョン処理に問題があって、1フレームに1オブジェクトしか処理していないから。そのため3つ消すのに3フレームかかってしまうけど、3フレーム目にはもうAとは接触していないため3つ目のオブジェクトは消えない。
だから1フレームで接触してるオブジェ全部を処理したい。qgetcol 命令は実行するごとにオブジェクトIDを次々と返し、もう返すIDがなくなったときは -1 が返るのでそれを利用する。
コリジョン処理部分を以下に書き換えて。
; Aに当たったら消えてスコア加算 qcollision target repeat qgetcol i, x, y if (i < 0) : break score += 100 qdel i loop
if のところは (i = -1) の方が分かりやすいけどHSPTV部門的に…接触しているオブジェを全部処理して、-1 が返ったらループを抜ける。これで1フレームで全部消えてくれるはず。
実行するとちゃんと消えてる。ウェイト増やして見てみても間違いない!