いぬでもわかる

iOSやCocos2dxが好きでときどきAndroid。できるだけ毎日何かしら書く事を目標に頑張る。

setDesignResolutionSizeとsetContentScaleの動作

cocos2d-xでマルチディスプレイ対応をしようと思ったら外せないのがsetDesignResolutionSizeとsetContentScale。
いまいち何をしているのかわからず使って来た上、この2つのメソッドがどういった動きをするのか解説しているページもなかったので調べてみた。

リファレンスの情報は少ないので、基本は公式のマルチディスプレイ対応のドキュメント
http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Multi_resolution_support
と自分で動作を確認した結果です。
何か間違えがあれば指摘してもらえると嬉しいです。


まず、non-retina iPhoneでは320*480の座標系ですが、retina iPhoneでは640*960であるようにデバイスごとに異なる座標系の問題を解決します。
cocos2d-xは、デバイスごとに異なる画面の解像度ではなくDesign Resolutionと呼ばれるサイズをもとにした座標系を使います。
Design Resolutionを設定することで、開発者はデバイスごとに異なるデバイスサイズではなくDesign Resolutionのみを意識するだけでマルチディスプレイ対応したアプリの開発をすることができます。
Design Resolutionの設定は、setDesignResolutionSizeで行います。

  • CCEGLView::sharedOpenGLView()->setDesignResolutionSize(width, height, policy)
    • width
      • Design Resolutionの幅を設定
    • height
      • Design Resolutionの高さを設定
    • policy
      • デバイスサイズとDesign Resolutionのアスペクト比が異なる場合のDesign Resolutionの適用方針


policyは以下の3つの値を取ります。

  • policy
    • kResolutionExactFit
      • Design Resolutionのアスペクト比を保たず画面サイズにフィットする形で適用されます。
    • kResolutionNoBorder
      • アスペクト比を保ったまま、余白が出ないような形で適用されます。
    • kResolutionShowAll
      • アスペクト比を保ったまま適用されます。縦もしくは横に余白が発生します。


non-retina、retinaそれぞれのiPhone向けにDesign Resolutionを設定してみます。

//design Resolutionのサイズを320*480に設定します
CCSize designSize = CCSize(320, 480);
//画面サイズの取得
CCSize screenSize = pEGLView->getFrameSize();
CCSprite* backgroundImage;

//Design Resolutionの設定。
//iPhone5の場合は縦方向に余白が発生します。
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionShowAll);

if(screenSize.height > 480){
  //retina向けに高解像度の背景を用意
  backgroundImage = CCSprite.create("640_960.png");
}
else{
  backgroundImage = CCSprite.create("320_480.png");
}
backgroundImage->(ccp(designSize.width * 0.5f, designSize.height * 0.5f));
this.addChild(backgroundImage);


non-retinaのiPhoneでは正常に動作します。
しかし、このコードを実行してみるとわかりますが、retina iPhoneでは背景画像がはみ出て設定されます。
というのもDesign Resolutionに320*480を設定しているため高解像度の背景画像を設定するのでは、横方向に320ぶん、縦方向に480ぶんはみ出てしまいます。
そのため、non-retina同様320*480の画像を設定すれば奇麗に収まり表示されます。
しかし、retinaなのに低解像度の背景を設定するわけにはいきません。
そこで、setContentScaleの出番です。

  • CCDirector::sharedDirector()->setContentScaleFactor(scale)
    • scale
      • 設定する背景画像と設定したDesignResolutionとの比


用意した画像をDesignResolutionに合った形で表示を行えるように、画像の解像度とDesignResolutionとの比率を設定します。
一般的に設定しやすいために設定する背景画像の高さもしくは幅と、Design Resolutionの高さもしくは幅との比を設定します。
setContentScaleFactorを設定したコードは以下のようになります。

float ImageHeight;
if(screenSize.height > 480){
  //retina向けに高解像度の背景を用意
  backgroundImage = CCSprite.create("640_960.png");
  imageHeight = 960;
}
else{
  backgroundImage = CCSprite.create("320_480.png");
  imageHeight = 480;
}
//scaleの設定
CCDirector::sharedDirector()->setContentScaleFactor(imageHeight/designSize.height);
backgroundImage->(ccp(designSize.width * 0.5f, designSize.height * 0.5f));
this.addChild(backgroundImage);