縦スクロールシューティング02


フレームの設定と基本オブジェクト配置

アプリケーションとフレームの設定

アプリケーションとフレームを新規作成します。そして各プロパティからオプション設定を行います。

アプリケーションのフレームレート設定

アプリケーションのフレームレート設定

アプリケーションのプロパティでは「ランタイムオプション」からフレームレート設定をデフォルトの 50 から 60 へ変更。この時、PC 用の設定なら 60 で良いけど、モバイル用を意識した出力を行う場合、ハードウェアの仕様を考えて適切なフレームレートへ変更をします。

ハードウェアの動作仕様や環境に合わせるための設定ですから、モバイル用なら本当は 15 FPS 程度で良いかもしれません。他にも SWF での出力に 60 FPS は不要だと思うので自分なら 20 ~ 30 FPS 程度でまず作ってみるかも。

ちなみに今回は Java モバイルビルドを選択したのにフレームレートは 60 設定で作っています。これは筆者が結局 Java での出力にはあまり拘っていない証拠でもあります。機能縛りで作って見るという試みをやってるだけなので真剣にモバイル用に作ってるわけではありません。

参考外部資料/Wikipedia:リフレッシュレート

参考外部資料/Flash Playerのフレームレート

タイマーベース動作をオフに

タイマーベース動作をオフに

フレームのプロパティは今回、タイマーベース動作をオフにして作りました。このオプションをオンにした場合、Clickteam 標準動作とアニメーションの速度などがタイマーベースで動くようになります。

このタイマーベースオプション効果は標準動作を使わずスプライトの動作を自作した場合、タイマーベースを意識して設計してなければ意味がありません。つまり割り出したデルタから移動量に当てはめるロジックを自分で作ります。

タイマーベースで作ると、当たり前ですが過去に MMF2 の講座系でよく語られていた「変数への代入でタイミングを作る」と言う手法がまったく通用しなくなります。この作り方だとフレームレートが可変なので、期待した値でフレームレートを安定させることができなかった場合、動作は破綻します。

MMF2 的にはタイマーベース( TB )オプションをオフにした場合、完全にフレームベース( FB )でゲームを作っているということです。

TB で作るか FB で作るかについては基本的な設計段階で事前に決定しておく必要があるのですが、古いやり方を含め MMF2 は基本的には FB でゲームを作っていくツールだと考えれば良いと思います。このやり方が 2D でゲームを作る上で実装が楽だから、という事情もあります。

TB には利点があり FB にも利点はあるのですが、おそらく現在の主流は TB であり 3D のゲームとかは TB で作られていることが多いです。

TB か FB かの選択は「自分の信じる宗教・宗派の違い」に例えられるため、自分の立場をあまり強く主張しない方が良いのですが、MMF2 の現状だと FB で作る方がホントに楽だと思いますのでなるべく妥協してまず最初は FB で作りましょう。

そして FB で作った場合、FB の仕様として「製作者の想定していたフレームレートで動かない環境」では動作が遅くなったり早くなったりします。つまりフレームレートをコントロールできない環境下では動作が保証できません。

FPS 60 が欲しい、だけど FPS 50 でしか動かない環境のユーザとかがいたら、残念ながら FB で作っている以上そのユーザの環境は動作保障対象外です。これを TB で作ると FPS 50 程度ならあまり違和感なく動かせる。しかし MMF2 はエクステンションという「想定外」もあるので、 TB で作る場合使用するエクステンションの動作にまで配慮する必要があります。

ちなみに日本人が 60 FPS にこだわるのはコンシューマのリフレッシュレートが 60 だったことに由来するようです。海外では EU 系の古いテレビ規格である PAL が 50 だったため MMF2 もデフォルトが 50 になっていると聞いています( Clickteam はパリに本拠地がある)。PC 用のモニタは最近の液晶はワイドスクリーンが多くて、フルスクリーンだと 60 固定になっているらしいので、同期させたいなら FPS 60 をメインターゲットにするのは悪くない選択です。

FPS を固定してもかならず誤差はあるので、この辺はプログラマを中心にとっくの昔にいろんな議論や試行錯誤がなされていますが・・MMF2 はさすがにオーサリングツールの限界を感じさせます。本当に本当に TB で作りたい場合、MMF2 を捨てて開発言語などに手を染める必要があると思います。

関連 URL:タイマーベース動作とかについての新しい考察

あとはフレームのプロパティから今回設定したのは「すべてのオブジェクトに呼び出し時にロードオプションを適用」をオンにしてみました。どの程度信用できるオプションなのか分からないのですが、待機してるオブジェクトの数が多い場合このオプションが役に立つのかもしれませんってことで期待を込めて。

仮想の幅と高さの設定

仮想の幅と高さの設定

魔城伝説はゲーム画面が強制で縦にスクロールするシューティングゲーム。画面サイズは実ウィンドウを 640 * 480 とし、フレームの仮想の幅と高さを横は等倍、縦はひとまず 4 倍の 1920 px としました。

主要なオブジェクト(スプライト)の配置

アクティブオブジェクト(スプライト)を使ってプレイヤーに直接操作させるスプライトをゲームのスタート地点となるであろう場所に配置します。次にゲーム全体のイベント管理を行う専用のアクティブオブジェクトを配置。どちらもこの時点では見分けが付く程度の単なる四角い画像(アニメーションもさせない)が望ましいです。

基本オブジェクトの配置

基本オブジェクトの配置

筆者の作り方は普段ならオブジェクトイベントを多用するいわゆる「 Wiget (ウィジェット)」派です。イベントを組む際にオブジェクトイベントに活用できるかをまず考えて作っています。オブジェクトイベントを活用するのはイベントの再利用とかイベント関連オブジェクトの管理を兼ねます。

オブジェクトイベントには普通のイベントと違う多少の制限もあります。例えば識別子を含んだイベントをインポートできないので具体的には「オブジェクトグループ」を利用できません。あともう一つオブジェクトイベントの不便な点として、インポートされたオブジェクトは変数名の表示が強制でデフォルトに変えられてしまいます。

変数A、変数Bというのが日本語版 MMF2 におけるアクティブオブジェクトのデフォルトの変数名なのですが、実際のゲーム作製ではこの変数名を製作者の用途に応じた分かりやすい名前に変更する人が多いと思います。ところがせっかく便利になるようにこの変数名を編集しても、オブジェクトを他のオブジェクトイベントにインポートすると、オブジェクトイベント内では全部デフォルトで表示されてしまいます。苦労して付けた名前の意味がなくなってしまうのです。

たぶんこれも前述のオブジェクトイベントには「識別子(名前)」を含めたイベントがインポートができないという MMF2 の仕様に拠るものだと思います。この二つが案外不便な仕様なので、オブジェクトイベントはこの仕様を意識して作り方も工夫します。変数を大量に使いその管理を行うためのオブジェクトをまず専用に作って、その変数等イベント管理用オブジェクトにゲーム処理の中核となるオブジェクトイベントを作製するようにします。インポートさえしなければ変数名はオブジェクトイベントでも保持されるので、変数管理用のオブジェクトを一個作るというのはこういう意味も含んでいます。

グローバルイベントやオブジェクトイベントを活用する場合もう一つ重要な制限としてイベントの実行順の問題があります。イベントは

フレーム内イベント > グローバルイベント > オブジェクトイベント

この順で実行されるのが基本で、オブジェクトイベントが複数ある場合オブジェクトイベントの実行順は MMF2 のオブジェクトが持つ内部番号が古い順から実行されます。つまりフレームを新規に作成して、オブジェクトをぽんぽんぽんっとテンポ良くフレーム内へ配置できるのは便利なのでが、もうこの時点でオブジェクトイベントの実行順も決まってしまうのです。

一番最初に配置したオブジェクトにオブジェクトイベントを持たせた場合、グローバルイベントが終了後に一番最初に実行されるのがこのオブジェクトのオブジェクトイベントとなります。

問題はこれ以降オブジェクトを配置した順番なんて数が多い場合まともに覚え切れねーよってことです。事実上オブジェクトイベントの実行順は非常に管理が難しいです。そしてオブジェクトイベントの実行順をなんらかの方法で明示的にゲームループ中のイベントで変更できたら一番良いのですが、残念ながらそれができません。実行順が管理しきれないと何が問題になるかというとオブジェクトの移動とコリジョンの関係に問題が生じます。特に衝突判定を含む場合オブジェクトイベントの実行順を常に頭に入れておく必要があります。

筆者が作る場合なら、キーなどの押し下検出処理はフレーム内イベントで行い、特定のオブジェクトイベントを使ってコリジョンを検出するという順で組むようにしています。実行順は必ず把握する必要があるので、アクションゲームやシューティングを作るときは安易にオブジェクトイベントを使わず必ずイベントの実行順を意識して作ります。基本的にはフレーム内イベントでイベントグループを活用して全部作れば良いのですが、イベント行が長くなるのを好みません。

MMF2 はソースコードの閲覧性がイベント行が長くなればなるほど、オブジェクトの数が増えれば増えるほど閲覧性が悪くなる傾向にあります。逆に短い行で少ないオブジェクトなら大変イベントの見通しが良いので楽なのですが、作りこむとどう考えても条件やオブジェクトは数が多くなるので閲覧性は悪くなります。変数と変数の呼び出しとか依存関係は作った本人もよく忘れるので必ずメモを取ります。

デテクタを設ける

ゲーム仕様に沿った必要性からデテクタを設けます。

デテクタを操作し、衝突を検知させ位置の決定がされたら表示用のグラフィックスをデテクタと同じ場所に表示するようにします。アクションゲームでプレイヤーが操作するのは基本的にデテクタです。実際のゲーム完成時に表示され動いて見える絵は、デテクタの位置に従属しているだけです。実は今回最初に二つ配置したスプライトの一つがデテクタ用です。ゲームの作り始めは表示する画像のことなんかどうでも良いので、デテクタと障害物との関係構築にだけ一生懸命になってゲームエンジンをまず作り始めます。

デテクタってなによ?

デテクタというのは衝突判定用オブジェクトのことです。普段は非表示にして必要な衝突を検知させます。

デテクタを使うのはアクションゲーム等の「めり込み防止策」です。MMF2 以外でもアクションゲームを作ると間違った運用すれば「めり込み」は普通にありえるのですが、MMF2 で「めり込み」が特に言われるのはオーサリングツールとしてゲーム製作の簡単さをアピールしていたのに、この「めり込み」の防止策についてはいまのところ「高速ループ」以外あまり有効な手立てを見出せていないからです。

つまり MMF2 だからめり込むのではなくて、多くの場合座標移動とコリジョンを誤解してるし高速ループも使いこなせていないって結論になります。そして「高速ループ」が初心者には理解しにくいのは「高速ループ」の運用幅が広いからです。

高速ループは真っ先に覚えるべき?

いえいえ。

エクステンションには「めり込み防止専用エクステ」もあるのですが、残念ながら筆者もそれを使っているサンプルをあまり見たことはありません。ちなみに MMF2 日本語版を買ったばかりの頃、筆者は「高速ループ」の理解が一番めんどくさかったから後回しにしました。

日本語版 MMF2 で始めた初心者は他にも変数への代入やらエクステンション探訪やらヘルプや説明がタリネーよって部分をトライアンドエラーで順次理解したり解決していかなければならないので、順番としては「高速ループ」以外に先に覚えるべきことはいっぱいあるんです。「高速ループ」も覚えろとか言われてもすぐには無理ってもんです。

基礎概念では先に「アクションループ」で変数への代入に的を絞ってサンプルを出しましたが、そこから更に発展して今回 8 方向を自作するとなれば、ここでいよいよ「高速ループ」を使いこなす時なのです。実際に八方向を自作する前に、高速ループの基礎的な使い方をまず練習しましょう(でないといきなり説明されても理解できない可能性が高いです)。

練習はソースコードを眺めるよりもトライアンドエラーが重要です。そしてそれがあなたにとって複雑な問題ならなるべく単純化してから自分のペースで取り組みましょう。アクションループや通し番号がまだまだ怪しい方は高速ループの練習よりも先に変数への代入に取り組んだ方が進歩が速いと思います。

高速ループに挑戦しよう へ続く