Cocos2d-xでとりあえず楽に端末ごとの解像度の違いを吸収

cocos2d-xで、端末ごとの解像度の違いを吸収する仕組みについて試してみました。
iOSAndroidのみ検証しましたが、他でも(多分)同じだと思います。

今回使用したバージョン

  • cocos2d-2.0-x-2.0.4

公式サイトにこんな資料があります。
http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Multi_resolution_support
このサイトやサンプルプログラムのHelloCppプロジェクトでは、端末の解像度によって3種類の大きさの画像を使い分ける設定をしています。(AppDelegate.cpp参照)

Retina端末も含めて、解像度にあった綺麗な画像を表示できますが、同じ画像を3種類ずつ用意しなくてはいけません。


今回は、とりあえず楽に実装するのをコンセプトとして、画像は1種類ずつのみとします。

320×480をゲーム画面のベースとし、そのサイズの背景画像を用意します。


AppDelegate.cppのapplicationDidFinishLaunchingメソッドに1行追加します。

bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
	
	CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 480, kResolutionShowAll);  // ←これを追加

背景を中心に配置します。
おまけとして、サイズが80×80ピクセルのスプライトも追加しました。

	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

	CCSprite* bgSprite = CCSprite::create("bg.jpg");
	bgSprite->setPosition( ccp(visibleSize.width * 0.5f,visibleSize.height * 0.5f) );
	this->addChild(bgSprite, 0);
	
	CCSprite *sprite1 = CCSprite::create("sprite.png");
	sprite1->setPosition(ccp(0,0));
	this->addChild(sprite1,10);
	
	CCSprite *sprite2 = CCSprite::create("sprite.png");
	sprite2->setPosition(ccp(visibleSize.width,visibleSize.height));
	this->addChild(sprite2,10);
	
	CCSprite *sprite3 = CCSprite::create("sprite.png");
	sprite3->setPosition((ccp(visibleSize.width * 0.5f,visibleSize.height * 0.5f)));
	this->addChild(sprite3,10);

座標指定はCCDirectorのgetVisibleSizeメソッドから取得した幅と高さから計算するようにしたほうがいいみたいです。

いくつかの端末で試した結果です。

iPod touch 第4世代(640x960)

iPad Retina(1536x2048)

Galaxy SII LTE SC-03D(480x800)

Nexus7(800x1280)

iPod touch 第4世代は元画像と縦横比が同じなのでピッタリですが、他の端末だと上下もしくは左右に空白ができます。
この空白の部分は描画エリア外なので、ゲームでは使えないエリアになります。
座標指定したスプライトはいずれもきちんと表示されています。


CCDirectorのsetDesignResolutionSizeメソッドで指定したkResolutionShowAllは、余白ができてしまいますが座標やスプライトの大きさの計算が簡単になるメリットがあると思います。
画面全体を描画エリアにするkResolutionNoBorderやkResolutionExactFitなどもありますが、これらを使用する場合は座標やスプライトの大きさに気をつける必要がありそうです。
kResolutionNoBorderを使う場合は座標の設定にCCDirectorのgetVisibleOriginを使う必要があるようですが、まだ詳しく試していません。