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はやはり不採用ということで。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。

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

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