[cocos2dx][CocosBuilder] マルチ解像度対応がなんとなくわかった

 前回「わかんねー」と嘆いていたcocos2dxマルチ解像度対応ですが、CocosBuilderからの扱いも含めなんとなくわかった気がしました。
 まず、先日書いたこちらの記事(http://jumble-note.blogspot.jp/2014/02/cocos2dx.html)は間違いでした。訂正できるレベルではないので、もう一度記事をまとめたいと思います。間違った情報を盛大に流してしまい申し訳ないです。

 以前公式の情報がよくわからない、と書きましたが、公式の情報はどうやら間違いなさそうです。
Multi resolution support | Cocos2d-x

Resource Background Sizeに関して

 以前の記事では、「Resource Background Sizeはリソースサイズではなく対象としたい画面のサイズだよ」と書きました。が、「Resource」と名のつくように、「Resource Background Size」は背景リソースのサイズです。私が勘違いしていたのはここで、公式のサンプルコード等を見るとそれぞれのデバイスの解像度が指定されていたため、てっきり切り替え対象のデバイスの解像度を表しているものだと思っていました。
 この項目については、後ほど詳しく説明したいと思います。

ContentScaleFactorとResolutionPolicy

 cocos2dxにおける、マルチ解像度のキモとなるのはこの2つです。

  • ContentScaleFactor
     「Resource Background Size」と「Design Resolution」の比率です。画面には縦と横がありますから、この比率にも縦の比と横の比が存在します。縦の比と横の比の値のうち、小さい値をとるのが正解です。理由については後述します。
  • ResolutionPolicy
     「Design Resolution」を実際の画面サイズにマッピングする際に、どのようにマップするかを指定するものです。以下の値が指定できます。(括弧内はcocos2dx 2.x系での列挙名)
定数 アス比
保持
説明
SHOW_ALL
(kResolutionShowAll)
 画面とDesign Resolutionの比率の小さいに合わせて描画サイズを調整します。したがって、空いた領域には黒帯が入ります。黒帯OKの場合にはこれを指定しておけば問題ありません。
NO_BORDER
(kResolutionNoBorder)
 画面とDesgin Resolutionの比率の大きい方に合わせて描画サイズを調整します。したがって、はみ出る領域が生じます。Director(CCDirector)のgetVisibleOriginで実際に描画される領域の原点座標、getVisibleSizeで実際に描画される領域のサイズが返されますので、これらの値を使ってスプライトを配置していく必要があります。黒帯はでません。
FIXED_WIDTH
(kResolutionFixedWidth)
 幅に合わせて描画サイズを調整します。幅の比率や高さの比率によらず調整されるため、
    幅の比率 > 高さの比率: 左右が切れます。
    高さの比率 > 幅の比率: 上下に黒帯が入ります。
FIXED_HEIGHT
(kResolutionFixedHeight)
 高さに合わせて描画サイズを調整します。幅の比率や高さの比率によらず調整されるため、
    幅の比率 > 高さの比率: 左右に黒帯が入ります。
    高さの比率 > 幅の比率: 上下が切れます。
EXTACT_FIT
(kResolutionExactFit)
×  アスペクト比を無視して画面いっぱいに描画領域を広げます。アス比無視できるなら楽ですがゲームの場合は操作性が大きく変わるので使い道はなさそうです…
UNKNWON
(kResolutionUnknown)
×  ResolutionPolicy未設定の状態です。使うことはないでしょう。

 通常はNO_BORDERかSHOW_ALLを使うのが一般的なようです。ただし、NO_BORDERはContentScaleFactorや描画位置等を自分でしっかり管理しなければならないので、かなり面倒です。

ContentScaleFactorとResolutionPolicyはどのように機能するのか

 公式の画像が説明してくれているんですが、ちょっとわかりにくかったのでわかりやすいかもしれない図を載せます。ここではDesign Resolutionを(960, 640)と設定したとして説明します。以下はiPhone Retina 4インチの場合の挙動についてです。

 Aの場合を見てみましょう。AはResolutionPolicy::NO_BORDERで拡大しているので、左右が切れて高さが4インチディスプレイにぴったり合うように調整されます。この挙動で問題なのは、画像全体が拡大され左右が切れてしまうため、iPhone 3.5インチと4インチで表示が異なってしまうことです。

 Bの場合は、ResolutionPolicy::SHOW_ALLで調整しているので、上下に黒帯が入ります。SHOW_ALLは、Design Resolutionで切り取った後に比率を保ったまま拡大縮小します。したがって背景画像がDesign Resolutionよりも大きくても、はみ出た部分はカットされてしまいます。

 最後にCを見ましょう。ResolutionPolicy::FIXED_HEIGHTは高さに合わせて拡大縮小するので、この場合の挙動としてはSHOW_ALLと同じものになります。しかし、SHOW_ALLと違い、そのまま拡大縮小するわけではない(あくまで高さ基準でNO_NORDER的な挙動をする)ので、黒帯にならず背景画像が表示されます。大正解!

 しかし、面倒なことに、iPadではこう上手くはいきません。iPadでは、Resource Background SizeとDesign Resolutionの比はiPhoneと逆になるため、FIXED_HEIGHTで高さに合わせてしまうと黒帯が入ってしまいます。以下iPadの例です。

 Aの場合は、iPhone 4インチの場合同様、拡大表示されてしまうのが問題です。
 Bも同様で、黒帯が入ってしまいます。
 Cが正解です。表示しきれない部分は画像のみを表示します。

 このように、Resource Background SizeとDesign Resolutionの比でFIXED_HEIGHTとFIXED_WIDTHを切り替えるのが正しいようです

const float scaleW = resourceBackgroundSize.width / designResolution.width;
const float scaleH = resourceBackgroundSize.height / designResolution.height;

// 横(Landscape)の場合
const ResolutionPolicy policy = scaleH > scaleW ?
                              ResolutionPolicy::FIXED_HEIGHT :
                              ResolutionPolicy::FIXED_WIDTH;

// 縦(Portrait)の場合
const ResolutionPolicy policy = scaleW > scaleH ?
                             ResolutionPolicy::FIXED_HEIGHT :
                             ResolutionPolicy::FIXED_WIDTH;

 こんな感じです。

Resource Background Sizeとは!

 先述の通り、Resource Background Sizeは背景画像のサイズです。しかし、面倒くさがり屋な人は「1536x2272」みたいな画像を用意していることでしょう(このサイズはiOS全ての解像度で正しく表示できる画像サイズです)。その場合は、実際の背景画像サイズではなく、端末に表示したい画像サイズ――つまり端末の画面サイズを指定します。CocosBuilderを使うことが出来る場合は、端末に応じて適切な背景画像を指定することが(ほぼ)可能なので、その機能を用いて背景画像を指定すると綺麗にUIを設計することが出来ます(逆に、上記の1536x2272を使うと「画面下部に合わせたい!」みたいなUIを作るのに死ぬほど苦労します…)。

注意!

 今回の検証はiOS端末のみを用いて行っています。iOSの場合は解像度の種類が決まっているので比較的楽にぴったり合わせることが出来ますが、Androidではもう一悶着ありそうです。Androidはシミュレータが糞なので様々な解像度での検証が面倒です…後日少し調べて、この記事に追記する形でまとめることができたらと思います。

 また、この設定でうまく動いているように見えているだけで、実は正しくないといったことも考えられます。Androidで動かないかもしれないと書いたのもそのためです。この設定方法を使う場合は、その点に注意してください。

結論

 マルチ解像度対応めんどくせぇ

0 件のコメント :

コメントを投稿