複数の解像度へ対応する

cocos2dxでの複数の解像度への対応のやり方
(今回はiPhoneについてのみ触れているが、Android機種にも対応できるはずである)

1.解像度に合わせて複数の大きさの画像を用意する

 一種類の画像を引き延ばして解像度対応を行うとiPhone6plusなどの解像度が大きい機種では画像がぼやけてしまう。かといってiPhone6plusの解像度に合わせた画像をiPhone5の解像度に合わせて縮小して表示するとメモリがもったいない。
 そこで、iPhone6以下で使用する画像と、iPhone6 plusやiPadで使用する画像の2種類を用意する。
*なおiPhone3G,iPhone3GSはシェアがほとんどないと考えたため今回は考慮しない。

各機種の解像度については以下のサイトを参考にした。
iOS - iPhone/iPad解像度早見表 - Qiita


  1. ProjectのResourcesディレクトリに新しく「M」ディレクトリと「L」ディレクトリを作成する。
  1. 「L」ディレクトリにはiPhone6Plusの解像度を基準とした画像を追加する。(iPhone6Plusは実際には1080x1920サイズにリサイズされるので、1080x1920サイズで作成する。)
  1. 「M」ディレクトリにはiPhone6の解像度を基準とした画像を追加する。(この際、Lサイズの画像を縮小させて画像を作ると楽。)
2.作成したディレクトリをXcode上で追加する。

Xcodeのproject navigator上でResourcesに「L」「M」ディレクトリを追加する。
この際、create folder referenceにチェックをつけておく。つけておけば青色のフォルダが追加されるはずである。
(create folder referenceはディレクトリの階層構造を参照できるようにするためである)

3.Classesにヘッダーファイルを追加する

 先ほど作ったディレクトリを使うためにClassesに新しく「AppMacro.h」を追加する。
追加したAppMacro.hを以下のように書き換える。

#ifndef _AppMacro_H_
#define _AppMacro_H_

#include "cocos2d.h"

typedef struct tagResource
{
    cocos2d::Size size;
    char directory[100];
}Resource;

static Resource mediumResource = { cocos2d::Size( 750, 1334), "M" };
static Resource largeResource  = { cocos2d::Size(1080, 1920), "L" };

static cocos2d::Size designResolutionSize = cocos2d::Size(750, 1334);

//画面サイズに応じてフォントのサイズを変更する
#define FONT_SIZE (cocos2d::Director::getInstance()->getOpenGLView()->getDesignResolutionSize().width / mediumResource.size.width * 48)

#endif
4.AppDelegate.cppにL、Mどちらのリソースを使用するかを選択するコードを追加する

AppDelegate.cppに先ほど作ったAppMacro.hをincludeしてからapplicationDidFinishLaunching()に以下のようにコードを追加する。

bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
        glview = GLViewImpl::create("My Game");
        director->setOpenGLView(glview);
    }
    

    //↓追加分/////////////
    //デザインサイズの設定
    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
    
    auto frameSize = glview->getFrameSize();
    
    std::vector<std::string> searchPath;
    
    if (frameSize.width > mediumResource.size.width) {
        //「L」ディレクトリのリソースを使用
        searchPath.push_back(largeResource.directory);
        director->setContentScaleFactor(MIN(largeResource.size.height / designResolutionSize.height, largeResource.size.width / designResolutionSize.width));
    }
    else
    {
        //「M」ディレクトリのリソースを使用
        searchPath.push_back(mediumResource.directory);
        director->setContentScaleFactor(MIN(mediumResource.size.height / designResolutionSize.height, mediumResource.size.width / designResolutionSize.width));
    }
    
    //リソースディレクトリを指定
    FileUtils::getInstance()->setSearchPaths(searchPath);
    
    //↑追加分///////

    
    // turn on display FPS
    director->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this
    director->setAnimationInterval(1.0 / 60);
    
    // create a scene. it's an autorelease object
    auto scene = GameScene::createScene();

    // run
    director->runWithScene(scene);

    return true;
}
5.以上の手順で解像度対応ができる

後は以下のように解像度を意識しないでスプライトやラベルを使える。fontsizeの指定は48pointを基準に倍率で指定する。

auto hogeSprite = Sprite::create("hoge.png");

auto fugaLabel = Label::create("text", "Font Name", FONT_SIZE * 1.5);

ResolutionPolicyについては後日記事を書くことにする。