最近いろいろな投稿をしていますが、楽にレトロ風2Dゲームを作るためのStarling2.x向けライブラリやHOW TOを蓄積していっていまして、その副産物が投稿内容となっております。
うんちくや思うところは後半に持ってきて、ドット絵風ゲーム・アプリを実現するのに適したStarling2.xの基本的な設定や細かいコード記述法を下記に記します。
2Dドット絵ゲーム向けStarling設定
- antiAliasing設定を切る
Starling.current.antiAliasing = 0;
全体のスムージング描画レベルを0にします。とはいえ、これはデフォルトで0です。間違ってあげないようにしましょう。
Starling.current.nativeStage.quality = StageQuality.LOW;
ついでに、nativeStage(Starlingでなく、昔からあるFlash側のDisplayObjectの方)の描画クオリティも下げてしまいしょう。なお、スマホであれば、ドット絵ゲーム向け関係なしで普段からStageQuality.LOWにしても大丈夫です。1ドットがPCに比べて細かいのでアンチエイリアスなしでも汚くみえませんし、その方が速く動きます。(全くnative側に表示をしないのが1番速いですが、表示していても更新がなければ60fpsキープはできます。 参考 : Staringスマホアプリ開発テクニック その 1 )
- Starling自体の表示エリアを調整する
Starlingの描画領域はviewPortプロパティで変更できます。2Dドット絵ゲームに限らずゲームコンテンツでは決まった解像度(たとえば 640*480など)で作って、それを端末の描画領域最大まで比率を保ったまま拡大する手法がよく使われます。そのためのクラスにRectangleUtil
という便利なものがあります。
Starling.current.viewPort =
RectangleUtil.fit(gameScreenRect, allScreenRect, ScaleMode.SHOW_ALL);
こちらの野中さんの記事に基本的な使い方が書いてあります。Starlingフレームワーク1.3の新しい機能
静的メソッドRectangleUtil.fit()メソッドは、第1引数の矩形領域を第2引数の矩形領域に、縦横比は変えずに納めるためのRectangleオブジェクトを返します。第1および第2引数は、Rectangleオブジェクトです。そして、第3引数には、ScaleModeクラスの定数で伸縮モードが渡せます(表002)。
この場合、Starlingの描画領域以外は何も表示しないことになるため、見た目が寂しいと感じる人もいるかもしれません。下記に、回避方法を考えます。
1つはStarlingの描画領域は画面全体のままとして、RectangleUtil.fitの演算結果はStalingのviewPortでなく、内部表示しているDisplayObjectContainerに適用する方法がありそうです。(試してませんができるはず。) もう一つはnative側のDisplayObject側で何か飾りを表示する方法です。その場合、無駄な電力消費を抑えるskipUnchangedFrames機能が使えなくなるのには注意です。(native側に表示更新がない前提であればStaring側のコードをちょっと改変すればなんとかできそうな気もしなくはない。。いずれ試します。)
- Starling自体の表示解像度を整数倍に吸着させる
上記の応用なのですが、端末の描画領域最大まで比率を保ったまま拡大
すると、1DOT表示が引き伸ばされ、ピクセルパーフェクトでなくなります。せっかくのDOT絵なので整数倍に拡大を限定して綺麗な表示としたいところです。実は、その設定ための引数がRectangleUtil.fitの第四引数にあります。
var pixelPerfect:Boolean = true;
Starling.current.viewPort =
RectangleUtil.fit(gameScreenRect, allScreenRect, ScaleMode.SHOW_ALL, pixelPerfect);
これで、上は1倍、2倍、、下は1/2倍、1/4倍、、とした表示に吸着させることができます。すばらしい、、のですが、DOT絵が原寸よりも小さい表示になる場合では、もはや何が表示されているのかわからなくなることがあります。ので、個人的にはpixelPerfect設定を使わず、上は整数倍のみ、下は限界の大きさまで拡大する、という方法をとることにしています。ここにそのソースを貼っておきます。setupViewPort()メソッドがその部分です。ViewportUtil.as
まあ、そもそも最近のスマホであれば縮小表示になることはなさそうですが。
人によっては、0.75倍や1.5倍などさらに中間を吸着拡大率として設定したい場合もあるかもしれませんね。
2Dドット絵ゲーム向けDisplayObject設定
- DisplayObjectのtextureSmoothingをNONEにする
dobj.textureSmoothing = TextureSmoothing.NONE;
正しくいうと、starling.display.Mesh
のtextureSmoothing
ですね。これで用意した画像素材がパキっとした見た目になります。注意点として、TextureSmoothing.NONE設定でないDisplayObjectが画面にまじると、その部分でドローコールが分割されるので、処理速度の低下につながります。すべての設定を忘れずに行う事が必要です。Mesh以外にも各種フィルタ、Buttonに同じプロパティがあります。
なお、DisplayObjectContainerにはこのプロパティがないのでMesh系のDisplayObjectに1つ1つ個別に設定しなくてはいけません。
FeathersなどUIコンポーネントを使う場合も、内部で生成するImageのTextureSmoothingがNONEになっていないので、コードに手入れが必要になります。他ライブラリでも同様。ここは痛いところ。
- Bitmapフォントのスムージング設定を切る
<font>
<info face="hogefont" size="20" smooth="0" /> <!-- smoothを0にする -->
意味合いは、上記と同じです。ドット絵フォントを用意しても、ボケる時はボケるので、間違いなく設定します。
BitmapFontのスムージング設定は、ソースXMLだけでなく、動的に変更も可能です。
bmpfont.smoothing = TextureSmoothing.NONE;
- DisplayObjectのpixelSnappingをtrueにする
こちらもボケ表示にしないためのプロパティです。Starling2.xから設定可能になりました。Mesh
とTextField
とButton
に同じプロパティがあります。textureSmoothingがNONEになっていればこちらは設定しなくても良さそうですが、そうであっても念のため設定しましょう。こちらもDisplayObjectContainerにはこのプロパティがありません。
- Blendmode設定をNONEにする
starling.current.stage.blendMode = BlendMode.NONE;
必須でもない感じですが、半透明素材を使わない事が確定している場合、上位コンテナのBlend設定をNONEにしてしまいましょう。(おそらく描画速度が速くなります。)
- displayObjectのx,y値を整数にする
dobj.x = ~~dobj.x; // Math.abs()と同じ効果
dobj.y = ~~dobj.y;
こちらも可能であれば対応しましょう。外部アニメーションライブラリ内のコードをこのように書き換える必要がでた事がありました。アニメーション系ライブラリでは何度もこの処理が呼ばれ、一般的にMathクラスを使わないほうが処理が早いため、このように特殊な書き方をしています。
演出によっては、8の倍数などに座標値を吸着させるとさらにそれっぽいです。
// 8の倍数に揃える 3bitシフトして戻すのが8で割って小数点以下を切り落として8をかけるのに相当
// +3してるのは真ん中あたりで吸着計算したいから
dobj.x = ((dobj.x + 3) >> 3) << 3;
うんちくなど
ドット絵レトロ風ゲームの良いところは、そこそこファン層がいて(年齢高めですが)、作るのに工数がかかならないところではないかなと思っています。少人数で作れるので、とんがった制作物ができますね。大規模開発ではできない事ができる。インディーズ向けです。
悪いところは古臭くて、演出やゲームシステムが地味になりがちなところでしょうか。完全に古いゲームを作ってはダメで新しいスタイルやツールを取り入れつつ、あくまで画面デザインや音響作成の1スタイルとしてレトロ風を選択するということが大事かなと個人的には思っています。
上記の長所短所を考慮して、下記のようなルールでつくりすすめることにしています。
<雰囲気は守りつつ地味にならない>
* 同時表示キャラ数やパターン数は実際のハードスペックをはるかに超えて良いことにする
* パーティクルシステムなども雰囲気を壊さずがんがん使う
* 発色数と解像度に制限はつける、雰囲気はここからくる
* スマホ対応前提なので、縦画面OK !
専用回路をつんだROMカセットで、通常の3倍のスプライト数と同時発色数を実現!
というイメージですね。この辺の塩梅を大事にします。実ハードスペック(ファミコン・スーパーファミコン・PCエンジン・メガドライブあたり)を超えつつも、それを念頭に置く事を忘れないようにします。
<アートを作る工数を劇的に削減>
* ドット絵描くのが大変なので、ランタイム側で勝手にそれっぽくみえるような描画ライブラリ整備していく
* モダンなアニメーションツール/レベルデザインツールをフル活用
俺が10分で書いた落書きがいい感じに動いている!
といった状態を目指します。凝り出して、3Dモデリングしたほうが楽だった、みたいな事にならないようにしないといけません。メッシュアニメーションなども取り入れます。
上記のルールを念頭に置きつつ、プラスでドローコールは1をキープ!(フィルタ適用で2かも?)という目標で、主に描画まわりのライブラリを作り進めています。
と、いった感じでたまにこんなのを投稿していきます。モダンな技術の習得も頑張りますが、こちらはじっくりゆるゆると作ります。