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

Home PC-6001mkII Program etc

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

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


2012/11/12〜14:縦長文字その1
 どうもスコアや残りタイムの表示が小さいな。よし、文字を大きくするか。

 はじめは縦横2倍にしようと思ったが、縦はともかく横を倍角にすると画面に入りきらなさそうだ。なら縦倍角にしようかな。

 使用する文字をGPUTCHARでグラフィック画面に文字を描いたあと、縦2倍に加工してBGU0のキャラデータとして反映させる。ってあれ?GPUTCHARでアルファベット文字を出すときは何を指定すればいいんだっけ?

 マニュアルを見ても、探し方が悪いのか見当たらない。確か前も悩んだ気がするなと思い、過去に作ったテストプログラムを漁ってみる。...あった、「BGF」だ。ともかくこれで縦倍角文字を生成できる。

 こうして、表示に必要な文字だけのBGU0のキャラを生成し、合わせて縦倍角表示用のルーチンを作成する。

画像

 まあまあ見栄えが良くなったかな?

 でもグラフィック画面に描くと準備に時間がかかるな。別の方法にするか。CHRREADを使うと、文字のグラフィックデータを直接変数に入れられるので、これを利用する。
 取得した64文字のデータを8文字ずつ区切り、それを2回分並べて縦倍角用のキャラデータを生成する。これで少し速くなったかな。

2012/11/15〜18:コリジョンその2
 11/7に発生していたコリジョンの問題、いいかげん解決させよう。

 現象としては、たまに想定する範囲から横にずれた位置で衝突判定される。「たまに」というのがなんとも厄介だ。とりあえず敵の数を減らして現象が出るか確かめる。...これだと確実に出るな。調べたい時には好都合だ。

 ここまでわかれば後は時間の問題、と思いきや、それでもなかなか原因がつかめない。なにしろ敵の衝突範囲を変えても何も状況が変わらない。

 何度もリストを見直した末、ようやく原因がわかった。なんと、敵の衝突範囲を指定したつもりが、管理番号の指定を間違えてたよorz。...ともかく、これで想定通りの反応をするようになった。

2012/11/19〜20:コリジョンその3
 衝突判定のバグが直った所で、ようやく本題に入る。衝突判定の調整だ。

 まずはじめに衝突判定を行いたい範囲だが、以下のようにしたい。

画像

  • 敵とオプションは、キャラクタが接する位置(24ドット)
  • オプションと自機は、キャラクタが接する位置(24ドット)
  • 自機と敵は、敵と自機の中心が接する位置(16ドット)
 衝突判定の横方向(縦方向)のサイズを、敵:A, オプション:B, 自機:C とすると、以下の連立方程式を解けば良い。
 (A/2) + (B/2) = 24
 (B/2) + (C/2) = 24
 (C/2) + (A/2) = 16
 つまり、A=16, B=32, C=16 だ。範囲を図示するとこんな感じになる。見た目とはかなり異なる衝突範囲だが、おそらくこれで良いのだろう。

画像

 ただ、衝突判定が矩形のため、どうしても斜め方向の衝突判定が甘めになってしまう。特に自機と敵との間では、自機の中心にかすりもしない距離でも衝突したと判定されてしまう。

画像

 さてどうするか。まあ、愚直に敵と自機の距離を計算するしかないな。
 計算にかかる時間を最小限にするため、SPHITSPで衝突したとみなされた組み合わせだけ、自機と敵の距離を計算して2段階目の判定を行うようにする。

 ちなみに、斜め方向の衝突判定の甘さは 敵とオプション,オプションと自機の間でも当然発生するが、こちらの方は2段階目の判定は行っていない。プレイヤーに優位になる判定については、あまり気にならないものなので。

2012/11/20: オプション補正
 前に棚上げしていたオプションの不審な動きについて修正を行う。

 1つ目に、今ひとつ自機にオプションが寄り切らないことがある。2つ目にオプション集合後に自機を動かすと1回だけ自機につられてオプションが動く。

 前者は、自機を動かしながらオプションを集合する時によく起こるようだ。...そうか、オプション集合開始時の自機の位置に移動するから、そこから自機が移動するとずれて見えるんだ。
 ちゃんと自機を追尾しないとダメという事か。という事で、それまで1回だけだった自機へのSPOFSをフレーム毎に実行するように変更する。

 もう一つは、前者の修正時に処理の順序を変えた事で解決したようだ。

2012/11/21〜25:点数表示
 次に棚上げされていた部分、点数表示に移る。なぜ点数表示を棚上げしていたかというと、点数が100万点になるかもしれないのに、変数には±524287の範囲しか入らないからだ。

 はじめは、変数には実際の点数の1/1000で入れておいて表示時に小数点を省けばいい(12345点の場合は、その1/1000である「12.345」から小数点を省いて「12345」と表示)と思い実装してみた。でもこの方法だと以下の2つの問題があった。
  1. 小数点第3位が0だと表示上の桁数が狂う。
    例:点数が12340点の場合、変数上は「12.34」→「1234」と表示される
  2. 点数が1000点未満の時、前に余分な0が表示される
    例:点数が66点の場合、変数上は「0.066」→「0066」と表示される
 当然点数が100点の場合等、両方に該当する場合(「01」と表示)もある。

 条件で分けて表示処理を分ければ、おそらくうまく表示できるだろう。ただ、点数の表示処理が複雑になって遅くなりそうな気がする。さてどうするか...

 結局、変数上は実際の点数の1/128で格納し、表示する前に128倍する事にした。当然、これでは128倍した時点で524287を越えるとオーバーフローになる。という事で1回だけ分岐するようにする。
  • 点数の変数値が(100000/128)未満の場合:
    → 変数値を128倍して表示
  • 点数の変数値が(100000/128)未満の場合:
    → 先に(100000/128)で割った商を10万点以上の桁とし、この商×(100000/128)を変数から引く
     その後、変数値を128倍して10万点未満の桁とする
     最後に10万点以上と10万点未満の数値を文字としてつなげて表示
 結局、条件分岐は1つ入ったが、表示は大丈夫そうだ。

画像


2012/11/20〜26:THE WORLD
 実はSPOFSによる補完フレームに変えて、弊害が一つ出ている。一時停止処理だ。

 HSP版では、敵が自機に当った時に1秒程度止まってまた動き出す処理を行っていた。ところがプチコンで補完フレームにすると、プログラムでVSYNC待ちにしても敵や爆風は勝手に動いてしまう。

 とはいえ停止させる方はまだ楽だ。全スプライトに対して現時点のスプライト位置をSPREADで取得し、SPOFSで同じ位置に「移動」すればいいのだから。とりあえず、こちらを先に作っておこう。サブルーチン名は「THEWORLD」。

 次に、敵の再移動の処理を考える。敵は、出現した瞬間から最終到達位置とスピードが決まっている。このため、最終到達地点に向けて(最終到達地点〜現在位置の距離)/スピード の時間を補完時間分の移動をSPOFSで指定すると良さそうだ。

 敵の最終到達地点は、THEWORLDルーチンで止まった時点で情報がなくなるため、あらかじめ出現時にスプライトの情報としてSPSETVで記録しておく。これで良いかな?

 さて、次は爆風だ。こちらは出現時の補完時間を表示カウンタとして配列変数に格納し、毎フレーム表示カウンタをカウントダウンした結果0になったら画面外に追いやる事にした。...のだが、なぜか移動後も少しの間画面に残っている爆風が散見されるようになった。

 しばらく原因がわからなかったが、どうやら処理がフレーム落ちしたときにスプライトの補完時間と表示カウンタにずれが出るようだ。せっかく作りこんだ処理が仇になったらしい。

 紆余曲折があって、最終的には、爆風スプライトのSPCHKの戻り値が0になったら画面外に爆風を追いやる事にした。正確には爆風は止まった後、再移動を行う事なく消えるが、心配していたほどは目立たないようだ。

2012/11/26〜12/02:高速化その1
 ゲーム部分がほぼ出来上がったところで、高速化にいそしむ。

 プチコンだろうがP6だろうが、高速化が効果的な場所は決まっている。実行回数が多い処理だ。本作では、最大64キャラクタを動かす爆風の処理と、最大32キャラクタを動かす敵の処理がこれにあたる。

 という事で、まず爆風の処理を見直す。とりあえず遅そうなのは、未使用の爆風を探す処理かな...。

 この時点では、爆風が未使用か否かの情報は配列変数で管理しており、毎回はじめから最後まで(64キャラクタ分)ループして最終的に使用可能な一つを決めていた。だけど、1つでも見つかればそれ以上探さなくても良いだろう。という事で、使用可能な爆風の番号を見つけたらループを抜けるように修正する。

 ただ、これだと平均処理時間は多少減るだろうが、最大処理時間(使用可能な爆風が全くない場合)は全く変わらないという事に気づいた。どうしよう。

 ここは割り切りかな?爆風が使われているか否かにかかわらず、64キャラクタを順繰りに使うようにする。番号をカウントアップし、最後まで行ったらまた1番目に戻るだけの処理なので、この部分はかなり高速化できたはずだ。

 この時点で、ゲーム中(30fps)の100秒が実時間では112秒前後。まだまだか...。

2012/11/27〜29:縦長文字その2
 縦倍角文字をメニュー画面も使いたいので、少し処理を変えるか。

 これまで、ゲーム中に使う文字「SCOREHIT:.」と数字のみ、縦倍角文字を生成し表示ルーチンを作成していた。これを、「BGF0」文字コード0〜255に対応させるようにする。

 BGF0の文字コード0→BGU0の文字コード0と1、
 BGF0の文字コード1→BGU0の文字コード2と3、
 …
 BGF0の文字コード127→BGU0の文字コード254と255、
 BGF0の文字コード128→BGU1の文字コード0と1、
 …
 BGF0の文字コード255→BGU1の文字コード254と255

 というように、256文字分の縦倍角文字データをBGU0とBGU1に生成する。こうする事で、文字コードを2倍すれば表示すべき縦倍角文字がBGPUTで出せるため、処理も簡単になる。

 本当に256文字分必要だったかという疑問もあるが、さほど生成処理に時間がかかるわけではないし、まあいいか。

 その他、敵へのダメージ音と撃破音を鳴らす処理も追加する。はじめは両方ともBEEPを使っていたが、ダメージ音に埋もれて撃破音がほとんど聞こえないため、撃破音をBGMPLAYのMML指定で出す事にする。

 やっぱり、音が入るとグッと良くなった、気がする。


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