エンジニア

Cocos2d-xをv3からv4にアップデートする

投稿日:2020年12月31日 更新日:

お世話になります。名古屋スタジオの藤澤です。
今回はCocos2d-x v3.2で作成したアプリをv4.0に移植した話を書いてみたいと思います。
(開発環境は Mac OS 10.15.7 で確認しています)

環境設定

CMakeのインストール

v3.17あたりからビルドにCMakeが使われるようになったためインストールする必要があります。
MacならHomebrewでインストールできます。

brew install cmake

Cocos2d-xの取得

公式のREADMEに従って最新バージョンを取得します。

git clone https://github.com/cocos2d/cocos2d-x.git
cd cocos2d-x
python download-deps.py
git submodule update --init

環境変数の設定

公式のREADMEに従ってsetupを実施します。

cd cocos2d-x
./setup.py
source FILE_TO_SAVE_SYSTEM_VARIABLE

もしくは、すでにプロジェクトが存在していてcocosコマンドを使わないのであれば以下の設定だけしてあげればビルドをすることができます。

export NDK_ROOT=/Users/xxx/Library/android-ndk-r21/
export ANDROID_HOME=/Users/xxx/Library/Android/sdk
export ANDROID_NDK_HOME=/Users/xxx/Library/android-ndk-r21/
export ANDROID_SDK_ROOT=/Users/xxx/Library/Android/sdk

export PATH=$PATH:/Users/xxx/Library/Android/sdk/cmake/xxx/bin

Androidのビルドでninjaというコマンドが必要だったので、Android SDKのcmakeのフォルダにpathを通してあげる必要がありました。
また、Android NDKはr16以上が必要とのことです。

プロジェクトの作成

今回は新規で作成したクリーンなプロジェクトに既存のコードを移植する方法をとりました。
公式のREADMEに従ってプロジェクトを作成します。

cocos new MyGame -p com.your_company.mygame -l cpp -d NEW_PROJECTS_DIR

Androidはこの時点でビルド、実行できるはずです。

cd proj.android
./gradlew assembleDebug
adb install app/build/output/apk/debug/xxx.apk

Xcodeのプロジェクト作成

この時点でXcodeのプロジェクトファイルはまだ作成されていないため、公式に書かれている通りCMakeで作成します。

mkdir ios-build
cd ios-build
cmake .. -GXcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos

作成されたxcodeprojを開いて、info.plistのCFBundleExecutableだけ指定してあげればビルド、実行できるはずです。
が、これだとXcodeのプロジェクトファイルがCMakeで管理された状態になっており、設定の変更を加えても勝手に元に戻ってしまいます。(設定の変更はCMakeLists.txtで行なう必要があります)

本来はCMakeLists.txtで管理していくのがよいのだと思いますが、複雑な設定などは非常にたいへんそうなので、CMakeとの連携を切ることにしました。

ALL_BUILDとZERO_CHECKのTARGETを削除、ファイルツリーのほうもALL_BUILDおよびCMakeLists.txtは要らないので削除します。(CMakeLists.txtはファイル自体は削除せずに参照だけ)

また、HEADER_SEARCH_PATHなどがローカルの絶対pathになってしまっているので、project.pbxprojファイルをエディタで開いて書き換えます。(いっぱいあるのでエディタで置換したほうがよいかと思います)

- HEADER_SEARCH_PATHS = (/Users/xxx/Documents/xxx/cocos2d/external/clipper/.);
+ HEADER_SEARCH_PATHS = "$(SRCROOT)/cocos2d/external/clipper/.";

コードの移植

ここまででクリーンな状態のプロジェクトは準備できたので、あとはコードを移植していきます。

Xcodeでのファイルの追加

Xcode側はCMakeの管理をやめましたので、普通にファイルをプロジェクトに追加すればOKです。

Androidでのファイルの追加

Android側はCMakeLists.txtにビルド対象のファイルを追加します。
CMakeListsの書き方は他に詳しい記事がたくさん存在していますのでそちらにお任せするとして、最低限の内容を以下に記します。

まず、ビルド対象にソースファイルを追加するために、60行目付近のGAME_SOURCE, GAME_HEADERを指定している箇所の下に、以下のように追記します。

# add cross-platforms source files and header files
list(APPEND GAME_SOURCE
     Classes/AppDelegate.cpp
     Classes/HelloWorldScene.cpp
     )
list(APPEND GAME_HEADER
     Classes/AppDelegate.h
     Classes/HelloWorldScene.h
     )

+ file(GLOB_RECURSE CLASSES_SOURCE RELATIVE ${CMAKE_SOURCE_DIR} "Classes/*.cpp")
+ file(GLOB_RECURSE CLASSES_HEADER RELATIVE ${CMAKE_SOURCE_DIR} "Classes/*.hpp")
+ set(GAME_SOURCE ${GAME_SOURCE} ${CLASSES_SOURCE})
+ set(GAME_HEADER ${GAME_HEADER} ${CLASSES_HEADER})

if(ANDROID)
    # change APP_NAME to the share library name for Android, it's value depend on AndroidManifest.xml
    set(APP_NAME MyGame)

次に、target_include_directoriesに以下のようにheader search pathを追加します。(Classes直下にしかファイルを配置していない場合は不要です)

target_link_libraries(${APP_NAME} cocos2d)
target_include_directories(${APP_NAME}
        PRIVATE Classes
+                PRIVATE Classes/xxx/
+                PRIVATE libs/xxx/
        PRIVATE ${COCOS2DX_ROOT_PATH}/cocos/audio/include/
)

ソースコードの修正

クラス名やメソッド名などが変わっている部分がありますので修正していきます。
基本的にビルドエラーになる箇所を順に潰していけば大丈夫ですが、以下につまづきそうな点を書いておきます。

  • v3系でDeprecatedだったクラスやメソッドが削除されているので修正が必要(setTouchEnabledなど)
  • Scale9SpriteやEditBoxがcocos2d::extensionからcocos2d::uiに変更
  • BlendFuncがbackend::BlendFactorに変更
  • GLProgramStateがbackend::ProgramStateに、Texture2D::PixelFormatがbackend::PixelFormatになるなど OpenGL関係はbackendに移動
  • CC_PROPERTYの定義が変わってgetメソッドにconstをつける必要あり

その他、cURLを使っている場合cocos2d/external/CMakeLists.txtを修正しないとリンクエラーになりました。(curl関連を先頭のほうに移動しています)

add_library(external empty.cpp)

+ if(NOT LINUX)
+     if(BUILD_EXT_CURL)
+         add_subdirectory(curl)
+         target_link_libraries(external ext_curl)
+     endif(BUILD_EXT_CURL)
+     add_subdirectory(png)
+     target_link_libraries(external
+         ext_png
+     )
+ endif(NOT LINUX)

if(BUILD_EXT_BOX2D)
    add_subdirectory(Box2D)
    target_link_libraries(external ext_box2d)

〜(略)〜

endif()

- if(NOT LINUX)
-     if(BUILD_EXT_CURL)
-         add_subdirectory(curl)
-         target_link_libraries(external ext_curl)
-     endif(BUILD_EXT_CURL)
-     add_subdirectory(png)
-     target_link_libraries(external
-         ext_png
-     )
- endif(NOT LINUX)

if(LINUX)
    add_subdirectory(linux-specific/fmod)
    target_link_libraries(external

また、ビルドは通るが実行時に問題になる箇所として以下のような修正が必要になりました。

  • TIFFサポートが廃止されTIFF画像が表示できない(こちら で削除された箇所を戻すことで対応可能です)
  • Node::resumeがvirtualになったため意図せずオーバーライドしてしまい挙動が変わる
  • SceneにデフォルトでCameraがaddされるようになったため、getChildren().at(0)でNodeを取得していた場合に目的のNodeが取得できなくなった
  • ScrollViewのビューポートの範囲外のNodeが描画されてしまう(こちら の修正で回避できます)
  • RenderTextureの使用方法が変わったのかタッチイベント中にRenderTextureを使うとクラッシュする(utils::captureNodeを使うとよいようです)
  • FileUtils::fullPathForFilenameでファイルが存在しない場合の戻り値が変わった

外部SDKの移植

外部SDKの追加もiOS側は従来どおりXcodeで行なえばOKですが、Android側はCMakeListsに記述します。
以下はsqlcipherを追加するときのサンプルです。

  1. sqlcipherのフォルダにCMakeLists.txtを追加する
cmake_minimum_required(VERSION 3.6)

project(sqlcipher)

set(SQLCIPHER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

add_library(sqlcipher SHARED IMPORTED GLOBAL)
set_target_properties(sqlcipher PROPERTIES
    IMPORTED_LOCATION "${SQLCIPHER_ROOT_PATH}/lib/${ANDROID_ABI}/libsqlcipher.so"
    IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
    LINKER_LANGUAGE "CXX")
  1. プロジェクト直下のCMakeLists.txtにsqlcipherを追加する
    add_library(${APP_NAME} SHARED ${all_code_files})
+     add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libs/android/sqlite3)
    add_subdirectory(${COCOS2DX_ROOT_PATH}/cocos/platform/android ${ENGINE_BINARY_PATH}/cocos/platform)
    target_link_libraries(${APP_NAME} -Wl,--whole-archive cpp_android_spec -Wl,--no-whole-archive)

+     set(CMAKE_CXX_FLAGS "-DSQLITE_HAS_CODEC=1")
 endif()

target_link_libraries(${APP_NAME} cocos2d)
+ target_link_libraries(${APP_NAME} sqlcipher)
target_include_directories(${APP_NAME}
        PRIVATE Classes
+                PRIVATE libs/android/sqlite3/include/
        PRIVATE ${COCOS2DX_ROOT_PATH}/cocos/audio/include/
)

プロジェクト設定の移植

最後にプロジェクトの設定やリソースファイルを移植して移行完了です。

  • XcodeのBuild SettingsやInfo.plist, Capabilitiesの内容
  • App IconsとLaunch Screen
  • AndroidManifestとbuild.gradleや gradle.propertiesの設定
  • proguardの設定
  • ResourceフォルダとAndroidのresフォルダのリソース

おわりに

冒頭でv4.0に移植したと書きましたが、実はまだv4.0を組み込んだバージョンはリリースされていません……。
ですので、今回書いた以外にも色々問題が残っているかもしれませんが、多少なりともお役に立てば幸いです。

採用情報

ワンダープラネットでは、一緒に働く仲間を幅広い職種で募集しております。

-エンジニア
-

© WonderPlanet Inc.