ラベル cocos2d-x の投稿を表示しています。 すべての投稿を表示
ラベル cocos2d-x の投稿を表示しています。 すべての投稿を表示

2016年4月3日日曜日

【cocos2d-x】set design resolution size が機能しなかった原因

前回の記事で終了だとあんまりなので、少し追いかけてみました

まず、createWithFullScreenの実装:

bool GLViewImpl::initWithFullScreen(const std::string& viewName)
{
    CGRect rect = [[UIScreen mainScreen] bounds];
    Rect r;
    r.origin.x = rect.origin.x;
    r.origin.y = rect.origin.y;
    r.size.width = rect.size.width;
    r.size.height = rect.size.height;
    return initWithRect(viewName, r, 1);
}

途中経過は色々と省略していますが、上記のような感じで画面のサイズがフルスクリーンサイズって事ですね。これは、cocos2d-xのインタフェース仕様上それしか手段が無いので、まぁそうなりますよね。本当はデベロッパーが使いたいスクリーンサイズの近似値にすべきじゃないか?と思ったけど。その方が描画コストが浮きそうなので。Macなら最小640x400のはず(PC-9801と同じですね)。

で、次に問題のsetDesignResolutionSize。
まずは 全体grep でアタリをつけます。

$ grep -R designResolutionSize cocos2d/cocos
cocos2d/cocos/platform/CCGLView.cpp:        && _designResolutionSize.width > 0 && _designResolutionSize.height > 0)
cocos2d/cocos/platform/CCGLView.cpp:        _scaleX = (float)_screenSize.width / _designResolutionSize.width;
cocos2d/cocos/platform/CCGLView.cpp:        _scaleY = (float)_screenSize.height / _designResolutionSize.height;
cocos2d/cocos/platform/CCGLView.cpp:            _designResolutionSize.width = ceilf(_screenSize.width/_scaleX);
cocos2d/cocos/platform/CCGLView.cpp:            _designResolutionSize.height = ceilf(_screenSize.height/_scaleY);
cocos2d/cocos/platform/CCGLView.cpp:        float viewPortW = _designResolutionSize.width * _scaleX;
cocos2d/cocos/platform/CCGLView.cpp:        float viewPortH = _designResolutionSize.height * _scaleY;
cocos2d/cocos/platform/CCGLView.cpp:    _designResolutionSize.setSize(width, height);
cocos2d/cocos/platform/CCGLView.cpp:    return _designResolutionSize;
cocos2d/cocos/platform/CCGLView.cpp:    _designResolutionSize = _screenSize = Size(width, height);
cocos2d/cocos/platform/CCGLView.cpp:        return _designResolutionSize;
cocos2d/cocos/platform/CCGLView.cpp:        return Vec2((_designResolutionSize.width - _screenSize.width/_scaleX)/2, 
cocos2d/cocos/platform/CCGLView.cpp:                           (_designResolutionSize.height - _screenSize.height/_scaleY)/2);
cocos2d/cocos/platform/CCGLView.h:    Size _designResolutionSize;
cocos2d/cocos/platform/ios/CCGLViewImpl-ios.mm:    _screenSize.width = _designResolutionSize.width = [glview getWidth];
cocos2d/cocos/platform/ios/CCGLViewImpl-ios.mm:    _screenSize.height = _designResolutionSize.height = [glview getHeight];
cocos2d/cocos/platform/ios/CCGLViewImpl-ios.mm:    _screenSize.width = _designResolutionSize.width = [eaglview getWidth];
cocos2d/cocos/platform/ios/CCGLViewImpl-ios.mm:    _screenSize.height = _designResolutionSize.height = [eaglview getHeight];

んー...
正しい値が設定されていれば正常に動きそうですね。
CCGLView.cppという部分はプラットフォーム非依存っぽいので。

以下の _scaleX, _scaleY の算出直後にログを入れてみますか。
cocos2d/cocos/platform/CCGLView.cpp:        _scaleX = (float)_screenSize.width / _designResolutionSize.width;
cocos2d/cocos/platform/CCGLView.cpp:        _scaleY = (float)_screenSize.height / _designResolutionSize.height;

算出直後に
printf("_scaleX=%f, _scaleY=%f", (double)_scaleX, (double)_scaleY);
という感じでログ出力を入れてみたところ、
_scaleX=3.333333, _scaleY=3.333333

ん?
結果は正しそう。
320x240 の 3.3333倍 ということはだいたい1066x800。
スクリーンサイズはおそらく1280x800(イメージはretinaだから2560x1600)なので。
しかし、先ほどの画像(下図)のフォント部分のサイズは3.3333倍されてはいない。
フリーハンドで寸借したところ大体210x80ぐらい?
(retinaだから1/2なので105x40ぐらい?)
フォント表示の処理はこんな感じ。

    auto sprite = Sprite::create("res/spfont.png");
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    this->addChild(sprite, 0);

単純にスプライトとしてフォント画像を読み込んで配置しているだけですね。
気になったので、念のため visibleSize と origin の値をログに出してみた。

visibleSize.width=320.000000
origin.x=0.000000
visibleSize.height=240.000000
origin.y=0.000000

うん、問題ありません。
余談ですが、座標基準が中央のゲームエンジンってゲーム作る人のセンスが欠落したダメなヤツだと思っています。実際そういうエンジン(というかCocoaのAPIの事ですね)を使ったことが何度かありますが、回転が楽なことを除き全ての点で左上基準と比べてゲームの作り易さに欠けると思うので。ゲーム以外だと中央基準の方が作り易いと思うので、ゲームを作らない人がどちらかというとゲーム開発向けのAPIを作るとこういう齟齬仕様が生まれ易いのではないかと想像している(ゲームの話に戻すと、アーケードゲームのスプライトに回転機能がつき始めた頃、回転機能を思いっきり駆使した意欲作みたいなゲームがありましたが、使えるとしたらそういうゲームぐらいではないだろうか。ゲーム自体はあまり面白くなかったけど。なお、3Dになってからのことは分からないです)

んー...?
試しにsetScaleX, setScaleYで3.3333倍にズームしてみようか。
拡大された(驚愕)
つまり、setDesignResolutionSizeというのは、「座標系は合わせてやる」(拡大/縮小までしてやるとは言っていない)という機能なのか。

これは酷い。
まぁ、OpenGLをゼロから調べて使うよりは楽かもしれませんが、この手のクソ仕様は今後ももりもり出てきそうで怖いな。

という訳で、cocos2d-xのモジュールは、メインのコントロール部分とOpenGL部分のモジュール以外は全部削除して使うことにして、可能な限りcocos2d-x標準機能は使わないようにするのがベストかな。(あと、ラッパーライブラリみたいなものは必須ですね)

これならcocos2d-xを使わない方が楽なので、cocos2d-xはやはり不採用ということで。

【cocos2d-x】そして、伝説へ(set design resolution size does not work)

前回記事で、ドヤ顔でcocos2d-x導入編の記事を書いてみた訳ですが、解像度の設定がどうも意図した通りに動いていないらしい。
前回記事の図
glviewを
glview = GLViewImpl::createWithFullScreen("iblock");
で作成して、
glview->setDesignResolutionSize(320, 240, ResolutionPolicy::SHOW_ALL);
で、320x240を引き延ばして画面いっぱいに表示という風にしたつもりです。
が、どう見てもQVGAの荒さが感じられない...

試しに、320x240でWindowモードにしてみる。
glview = GLViewImpl::createWithRect("iblock", Rect(0, 0, 320, 240));

すると、下図のような感じになりました。
分かり易くするために、真ん中に表示されている画像を 128x48 ピクセルの SUZUKI PLAN FONT に変更しています。

では、この状態でもう一度フルスクリーンモードにしてみると...

うぉ!
文字がちっさいw
つまり、setDesignResolutionSizeが効いていないっぽい。
setDesignResolutionSizeが効いていれば、ウィンドウモードで起動した時と同じ比率で引き伸ばされた画像が表示される筈なので。

cocos2d-xだと、Macのフルスクリーンサポートは未だ不完全ってことなのかな。
cocos2d-xのソースを追っかけるのも怠い。
こういうことがよくあるからC++じゃなくてCで書いて欲しかった。C++は書く分には楽で、保守スパンが短いアプリとかならC++で書くべきだと思っているけど、他人が書いた未知のコードを追いかける時は、Cの方が楽なので。(アプリの保守スパンが短いというのは、最近の事情を勘案すると語弊があるかもしれませんが、銀行などの基幹系システムなどで利用されている20年もののプロダクトコードとかと比べればまだまだ浅漬け程度かなと)

cocos2d-xとは別の策を探るべきかな。
スマホ向けライブラリということで、PC向きに使うには未だ時期尚早だったのかもしれません。(Webで見つかるコードが割と互換性が無いものが多い点から見て、まだAPI仕様がかなりドメスティックに変わっているようなので、まだまだ安定していないようですし)
あと、コンパイルが遅すぎるのも怠い。

という訳で私のcocos2d-x利用の模索はここで一旦終了です。
早かったなぁー

やっぱり、VGSでPCサポートを完璧にするのが楽かな...

2016年4月2日土曜日

【cocos2d-x】導入〜解像度設定

この前、HTML5で作った Invader Block を cocos2d-x を使って PC に移植して、もうちょっと演出周りを凝らせてみて、Steamで販売してみようかと思い立つ。

VGSを使っても良いんですけど、PC用のVGSはサンドボックス用途での利用しか考えていなくて、WindowsはともかくOSXとLinuxもサポートしようとなると、現状の実装(SDL)では割と不満があります。(デフォルト状態で動かないのが一番の難点かと思います)

かといって、OSXとLinuxのネイティブ描画も凝らせようとするとそれだけで半年ぐらい浪費してしまう。という訳で、面倒なグラフィックス周りは既存ライブラリの力を借り、音声周りだけは vgs-bgm-decoder を使う方向で作るのがベターかなと。

そして、C/C++で書けて、Windows, Mac OSX, Linuxをサポートしているライブラリはcocos2d-xの一択ではないかと思います。(本当はランタイムはC++じゃなくてCの方が好みですが、CだとVGS以外に無さそうなので、この際、C++でも(C++13ぐらいまでのものなら)いいやと妥協)

という訳で、まずは導入。
git clone https://github.com/cocos2d/cocos2d-x.git
cd cocos2d-x
python download-deps.py
git submodule update --init
多分、全部で300MBぐらいあります。
デカイ...
気長にダウンロード。

そして setup & プロジェクト作成(iblockとかsuzukiplanといった部分は良しなに)
./setup.py
cocos new iblock -p com.suzukiplan.iblock -l cpp -d ~/cocos2d-x
cd ~/cocos2d-x/iblock
そして、OSX向けにコンパイル&実行してみる。
cocos run -p mac
これがまた長い...

が、無事 Hello, World! が起動。

ここまでなら README.md に書いてある通りのことだから、ブログに書いても芸が無いので、PCゲーム向けということで 320 x 240 (QVGA) の解像度 で フルスクリーン にしてみます。

WindowsでDirectXを使ったことがある人なら分かると思いますが、それだけでも実は結構面倒くさかったりするのですが、2行変更しただけでイケました。



変更箇所1: 44行目(createWithFullScreenを使う)
glview = GLViewImpl::createWithFullScreen("iblock");

変更箇所2: 59行目(setDesignResolutionSizeで解像度を設定)
glview->setDesignResolutionSize(320, 240, ResolutionPolicy::SHOW_ALL);

左右が少し黒く切れていますが、これは想定通り。
※Macの解像度は1280x800(Retinaなら2560x1600)なので、QVGAをアスペクト比を保った状態で画面いっぱいに引き伸ばすと、左右に余白が生まれる

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...