ActBarrier for プチコンmkII 製作過程 その3

Home PC-6001mkII Program etc

 このページでは、ActBarrierの骨格部分作成の過程を書いています。

ActBarrier for プチコンmkII 製作過程 Top


2012/12/03:勘違い
 これまで100秒だと思っていたプレイ時間だが、疑惑が出てきた。

 元のHSPプログラムでは、内部的な時間カウンタを6666に設定していて、16ms毎にカウントダウンしていた。これをそのままプチコンに持っていき、VSYNC 2毎に2ずつカウントダウンしていったので...

 6666 × 1/30 ÷ 2 = 111.1秒じゃないか!

 ついでに言うと、HSP版も 6666 × 0.016 =106.656秒だった事が判明した。だが、すでに投稿の締め切りは過ぎているので手遅れだ。

 まあHSP版は置いておいて、プチコン版だ。元が111.1秒という事は、実プレイ時間が12/2時点で112秒前後だったので、もしかして30fpsではほぼ遜色ない速さになっているのではないか?ひょっとしてもう少し頑張れば60fpsに手が届くのではないだろうか?

 そう思い、VSYNC 2をVSYNC 1に変更してみると、一気に161秒まで遅くなったorz。

 こうして、60fpsに向けてさらに高速化を試みることにした。

2012/12/04:高速化その2
 プログラムの高速化に向けて、見直しを行う。

 まず、オプション移動用変数の配列を、256から32に減らす。これで、オプション集合時の配列変数再初期化が微妙に速くなるはず。

 次に、敵とオプションの判定で、オプションのパワー計算を毎回(敵数32×オプション数3)行っていたが、これをSPHITSPで衝突判定となった後に実行するよう変更した。こちらは効果てきめんで、一気に140秒程度まで速くなった。

 ただ、ランダム要素が多いプログラムなので、実プレイ時間は15秒程度のブレがある。実プレイ時間は参考程度に見るべきなのかな?

 さらに高速化するには、これまで敬遠していたSPHITに手を出すしかないか...。

2012/12/05:SPHITその1
 更なる処理速度アップを行うため、敬遠していたSPHIT命令と向き合う。

 これまで敬遠していたのは、マニュアルを見ても設定方法が今ひとつよくわからなかったからだ。とりわけわからなかったのが以下の2点だ。
  1. 同時に複数のスプライトが衝突した場合はどうなるのか
  2. グループの概念
 これらについて憶測を立てていく。

 まずは、複数衝突判定だ。マニュアルを見ると、衝突時にシステム変数に相手の情報を残すとの事。対応するシステム変数は、...字面的にSPHITNOなのだろう。衝突したときは0〜99の値を返すが、これがおそらく衝突先スプライトの管理番号なのだろう。

 ただ、複数の値が返ってくる気配はSPHITNOからは感じられない。いったいどうすりゃ良いんだ?

 そこでもう一度SPHITに戻ってみる。SPHITには管理番号の他に開始管理番号の引数がある。という事は、...複数衝突した場合は、一番小さい管理番号だけがSPHITNOに入るのではなかろうか?

 とすると、1回目のSPHITで衝突を確認したら、その時のSPHITNOの値を見て衝突処理。そしてSPHITの開始管理番号にSPHITNO+1を指定して2回目以降の衝突判定、といった流れになるのだろうか。

 憶測が多すぎて、どこまで合っているかがわからないが、大きくは外していないと思うのでこのまま突き進む。

2012/12/05:SPHITその2
 次にグループの概念だ。

 マニュアルを改めて見ても、やはり今ひとつ使い方がわからない。こういう時はWeb検索だ。「プチコンmkIIで弾幕STGのテストプログラムを作ってみた」の人のblogが一番わかりやすいかな?

 えーと、ようするにこういう事か。
  • グループは8種類ある。(SPCOLで指定可能な値の範囲 0〜255を2進数で表現するイメージ)
  • スプライト毎に複数のグループに属する事ができる。設定上、全てのグループに属したり、逆に全てのグループに属さない事も可能(のはず)
  • SPHITで指定した管理番号のスプライトが属しているグループと最低1つ以上同じグループに属するスプライトとの間でのみ衝突判定を行う。
  • 同じグループ同士といっても、SPHITで指定した管理番号との間では衝突判定を行わない(はず)。
 思うに、内部処理ではSPHITで指定したスプライトと他のスプライトとの間でグループをAND演算して、0でない場合にはじめて衝突判定を行うというフィルタリングを行っているのだろう。

 例えば、敵とオプションを衝突判定させるがオプション同士は衝突判定させたくない場合はこうなるのかな?
種類グループ
00000111
オプション100000100
オプション200000010
オプション300000001

 あ、でもこれだと敵同士が衝突判定されるな...。

 あ、違うか。オプションから見た衝突判定にすれば良いのか。各スプライトのグループとSPHITで指定する管理番号をセットで考えないとダメっぽい。
種類管理番号グループSPHIT実行
0〜3100000111
オプション13300000100SPHIT(33)
オプション23400000010SPHIT(34)
オプション33500000001SPHIT(35)


 さらに、自機と敵、自機とオプションの共通グループを加えるといったいどうなるのか?なんかパズルみたいだな。
種類管理番号グループSPHIT実行
0〜3100001111
自機3201111000SPHIT(32)?
オプション13301000100SPHIT(33)?
オプション23400100010SPHIT(34)?
オプション33500010001SPHIT(35)?

 うーむ、なんか違うな。ちょっと頭で整理しきれなくなった。自機とオプションの衝突判定は判定回数が3回で済むので、ここだけSPHITSPで行って、残りの衝突判定をSPHITで処理すればいいか。
種類管理番号グループSPHIT実行
0〜3100001111
自機3200001000SPHIT(32)
オプション13300000100SPHIT(33)
オプション23400000010SPHIT(34)
オプション33500000001SPHIT(35)

 と、この時は軽く考えていた。

2012/12/05:SPHITその3
 いざ実装!

 心配していた複数衝突判定は、見た目上機能しているように見える。ただ、オプションと爆風の間でも衝突判定をしているようだ。SPCOLでグループを指定しない場合は、暗黙的に全グループに属するのかな?
 爆風との衝突判定処理は特に行う必要がないので、爆風はどこのグループにも属さないように設定した。

 そしてもう一つの問題だが、なぜか自機とオプションのSPHITSPによる衝突判定が効かなくなった。ここは処理を変えてないんだけどな...。

 あ!ひょっとしてSPHITSPの衝突判定もグループのフィルタリングが入るのか?マニュアルには一言も書いてないけど、そう考えると辻褄は合う。けどどうしようか。

 結局、各スプライトのグループはこんな風に設定した。少し負けた気がするけどしょうがない。
種類管理番号グループSPHIT実行
0〜3111111111
自機3211111111SPHIT(32)
オプション13311111111SPHIT(33)
オプション23411111111SPHIT(34)
オプション33511111111SPHIT(35)
爆風36〜9900000000

 オプションと敵,自機と敵はSPHITで衝突判定する。オプション同士やオプション-自機も衝突判定されてしまうが、衝突判定した結果(SPHITNO)が31より大きければ、それ以上敵には当っていないと判断することにした。
 また、自機とオプションの衝突判定はSPHITSPをオプションの数だけ実行するようにした。

 最良の策ではないかもしれないが、これが現時点の精一杯だ。
 気になる時間は...114秒!ざっと25秒ほど速くなった。SPHIT、凄いや。

2012/12/08:高速化その3
 さらなる高速化を行う前に、実行時間のムラを少なくするためにプログラムに細工を行う。

 一つ目は、ランダム要素の排除。同じ位置から敵が出現するようにする。
 二つ目は、自機のやられ処理を行わないようにする。
 三つ目は、時短のため、残り時間を100秒→25秒にする。

画像

 この状態で、一旦実行時間を調べる。敵を全く撃破しないパターンで27.3秒、逆に極力敵を撃破するパターンでは46.5秒となった。

 まず敵出現時、空いている敵をサーチする処理に手を加える。これまで、敵の状態をあらわす配列変数を敵の数(最大32)だけ調べていたが、SPHITを応用したら処理がもっとシンプルになるのではなかろうか?

 具体的には、画面外に空き判定用のスプライトを1つ用意する。そして、画面外に出た敵をこのスプライトの位置にSPOFSで移動させるようにする。

画像

 あとは、この画面外に配置した空き判定用のスプライトの管理番号を引数にしてSPHITを実行すれば良い。
種類管理番号グループSPHIT実行
0〜3111111111
自機3211111111SPHIT(32)
オプション13311111111SPHIT(33)
オプション23411111111SPHIT(34)
オプション33511111111SPHIT(35)
爆風36〜9800000000
空き判定用9911111111SPHIT(99)

 何も衝突しなければ敵の空きがないという事だし、衝突すれば、SPHITNOで空いている敵の管理番号がわかるという理屈だ。

 さて、どこまで速くなったか...45.3秒。少し速くはなったけど、体感上はあまり変わらないな。


その2 ActBarrier for プチコンmkII 製作過程 その4