UnrealEngine4研究所

UnrealEngine4の研究/開発をしてます。ガルルソフトウェア研究所です。

2016年06月

Mac版ガンハウンド

おおお、動いた。色々苦労したが動いたぞー!

ファイル名の大文字、小文字が異なるところや、ファイルパスの区切り「/」「¥」「\」の違いなんかをうまく吸収するのに手間取ったけど綺麗に動いてる。しかも40FPSでてるな。同じCocos上で動いているのにもかかわらず、えらく動作速度が異なる。

・WindowsでCore i7 3500MHz で20FPS
・Mac book Air Core i7 2200MHzで40FPS

不思議だなぁ、Windows版のCocosが最適化されてなさすぎるのだろうか。

改修に必要だったポイントをいくつかメモ

・64ビット対応
ポインタが32bitから64bitに拡張されているので、引数にSint32 val = (Sint32)&Data;みたいなやや強引な渡し方でアドレスを渡しているところで辻褄が合わなくなってる。アドレスが64bitなので引数の32bit幅ではキャストできない。なんとなく覚えてるけど、1つの関数でなんでも受け取れる仕組みにしたところがこういうところで問題を起こす。昔からこういう書き方はよくない、って言われてたところだな。

・ARGBマクロが64bitに対応できてない
#define ARGB(a , b , c , d ) ((a<<24)|(r<<16)|(g<<8)|(b<<0))
Uint32 argb = ARGB(0xff,0xff,0xff,0xff);
こんな感じのマクロで値を生成する場合、渡されてくる値がそもそも64bit長のものである可能性があるので、それを32bit長の変数に入れられなくなってる。

■Cocosのキーボーのキーコード
 #define KEY_RIGHT Cocos23::KeyCode::Key_Right;

 Sint32 test[256];
 test[ KEY_RIGHT ] = 0;

まず、上記の場合はKeyCodeをTest配列の添字にすることができなかった。
なので、enumにすることで、添字化することができた。

enum {
 KEY_RIGHT = Cocos23::KeyCode::Key_Right;
}

これはWindowsではうまく行った。しかしMacでコンパイルするとうまくいかなかった。そもそも、enumに自動でキャストしてくれないのである。

enum {
 KEY_RIGHT = (Sint32)Cocos23::KeyCode::Key_Right;
}

だから、こんな感じで明示的にキャストしてやる必要があった。

そして画面がステージ1が動いた

gh_st1

おおお、Cocos2dxでデバッグ版が動いた・・・・・!

し、しかし遅いなああ。6.6FPSとは。。
移植度はさすがに自分で作ったライブラリだけあって、つじつまあわせは完璧。ほれぼれするほどにガンハウンドであるが、Cocosの特性を無視した移植になっただけあってむちゃくちゃ遅い。この後、デバッグ用の描画とかを外して少し処理速度を稼いで20FPSくらいにはなったが、それでもPSPの30FPSに及ばない。PCでcore-i7の3500MHzとPSPの266MHzで30FPSっていうかなりのパワー差があるにもかかわらず。

次は念願のMac版ガンハウンドの生成にチャレンジしてみようと思う。スマホ版はどうなるかな。メモリに乗り切るか心配ではあるが、最近のスマホはVita以上の性能があるので普通に動くかもしれない。とりあえずできるところまでやってみよう。

ライブラリがまとまり次第、ガンハウンドのソースと私製ライブラリ、Cocos用のラッパーをオープンしてみようと思う。ガンハウンド素材を作ったガンハウンドみたいな横スクロールアクションを作るパワーが再び貯まるまで、誰かの創作に期待したい。

タイトルが出た!

タイトルが出た!

Cocosをスプライトリクエスト方式で描画するラッパーがうまく動作した感じ!
画面サイズはPSPサイズの480x272をCocosの640x480に合わせてるので
はみ出しちゃってるが、さてさて、この先どうなるのか?


gh_coocs1st

こっから先に動かないーーーーーー!

gh_coocs2nd


あ、スマホ対応ばっかり意識してたので、ライブラリのキーボードとかコントローラーの
入力の部分を作ってなかった。

Cocos2Dxでガンハウンド

もともとWin32環境で動いていたガンハウンドをCocos2Dxで動かしてみよう。せっかく買ったMacでゲームをつくれる環境がほしいもんね。もともとPSPで動かしていた実績もあるので機種依存しないコードでできている自信はあるんだけど、DirectX用につくったゲームエンジン部分をCocosエンジンに載せ替える必要があるのが結構大掛かりではある。

ゲームエンジンと言っても、最終的にはOpenGLに集約されるので、入り口と出口の部分は割りと問題なさそうではあるが、そこに至るまでのポリゴンの形成とか、入力や出力の集約の仕方がCocosとはまったく考え方が違うので苦労しそう。

おおざっぱにわけてしまうとスプライトの表示方法には2通りあって、1つのスプライトと1つのテクスチャを1対1で使う方法と、1つのテクスチャから複数のスプライトを生成する方法の2通りある。前者はキャラクタの絵を書いたテクスチャを読み込んでインスタンス化し、それをコントロールする。UnityとかCocosは基本的にこの方法であって、便宜上名前をつけると「スプライト・インスタンス方式」とでも言っておこう。

プログラムで描くとイメージはこんな感じ。スプライトの大きさ=テクスチャの大きさになる。

Sprite("texture.png")->Draw();

で、僕の得意とする方法は、テクスチャは個別に読み込んで、スプライト側が参照するテクスチャを決めて表示する。イメージで言うとこんな感じ。

#define TextureIndex (0)
LoadTexture( TextureIndex , "texture.png");
Sprite( TextureIndex , u ,v , w , h )->Draw():

Draw()となっているが、実際には「こんなスプライト表示をしたい」というリクエストを送るだけで、リクエストを貯めこんだあと、描画のフェーズでまとめてOpenGLなりDirectXの求めるポリゴン形状に丸めて描画する。なので、これを便宜上「スプライト・リクエスト方式(※)」と言っちゃう。

スプライト・インスタンス方式の場合は、画面に出てくるキャラクタがしっかりと決まっていてあまり不定な要素がない場合にとても便利。例えばアングリーバードみたいにキャラと敵の数がステージごとに決まっていて最初に生成してしまった後は、それを操作しまくってゲームに仕立てあげる。

スプライト・リクエスト方式は、無数の敵キャラが時間に応じてどんどん出てくるようなシューティングの場合、あとから中ボスを足そう、敵キャラを間引こうっていう不定なキャラとか、仕様がかっちりしていない場合に柔軟に対応できる。

※Cocosも最終的にはノードに割り付けられたスプライトを順番に描いていくので、その場で描いているわけではない。

ギャラリー
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • 第6回ぷちコン入賞賞品がスゴい、開封の儀!
  • ライブドアブログ