急 Cocos2d-xの処理をAndroidとiOSで分ける LuaとJava/Objective-Cの間で関数を呼び出す


目次

1 はじめに
2 AndroidとiOSの場合で処理を分ける
3 LuaからJavaやObjective-CのAPIを呼ぶ
4 JavaやObjective-CからLuaの関数を呼ぶ
5 今後の予定

はじめに

本記事は、cocos2d-xおよびCocos Code IDEを導入し、AndroidやiPhoneの実機端末で動かした人で、Android、iOSといったプラットフォーム毎に処理を分けたい人向けの、覚書きです。例えば3rdパーティのランキングサービスとの結合で、AndroidとiOSでAPIが異なっており、Luaからは直接アクセスできない場合に有効です。

AndroidとiOSでLuaの処理を分岐する

GameScene.lua
...             
                if cc.Application:getInstance():getTargetPlatform() == cc.PLATFORM_OS_ANDROID then
                    -- Androidの場合の処理をここに書く

                elseif cc.Application:getInstance():getTargetPlatform() == cc.PLATFORM_OS_IPHONE or 
                    cc.Application:getInstance():getTargetPlatform() == cc.PLATFORM_OS_IPAD then
                    -- iOS(iPhone、iPad)の場合の処理をここに書く

                end
...

LuaからJavaやObjective-CのAPIを呼ぶ

Cocos Code IDE

GameScene.lua
... 
                -- 
                self.point = 100

                -- Androidの場合
                if cc.Application:getInstance():getTargetPlatform() == cc.PLATFORM_OS_ANDROID then
                    -- Lua->Javaブリッジのライブラリを読み込む
                    local luaj = require "src/cocos/cocos2d/luaj"
                    -- 呼び出す対象のJava関数が記述されているクラスを設定
                    local className = "org/cocos2dx/lua/AppActivity"
                    -- 対象のJava関数へ渡す引数データを設定
                    local args ={ self.point }
                    -- 呼び出すJava関数名を指定して、(I)整数型引数、V戻り値なしで呼び出す
                    luaj.callStaticMethod(className, "setScoreJava", args, '(I)V')

                -- iOS(iPhone、iPad)の場合
                elseif cc.Application:getInstance():getTargetPlatform() == cc.PLATFORM_OS_IPHONE or 
                    cc.Application:getInstance():getTargetPlatform() == cc.PLATFORM_OS_IPAD then
                    -- Lua->Objective-Cブリッジのライブラリを読み込む                    
                    local luaoc = require "src/cocos/cocos2d/luaoc"
                    -- 対象のObjC関数へ渡す引数データを設定
                    local args = { score = self.point }
                    -- 呼び出すObjC関数名を指定して呼び出す
                    luaoc.callStaticMethod("AppController", "setScoreObjC", args ) 
                end
...

(Lua→)Android Java

AppActivity.java
...
import org.cocos2dx.lib.Cocos2dxLuaJavaBridge;
...
public class AppActivity extends Cocos2dxActivity{
...
    public static void setScoreJava(final int type) {
             //call 3rd party Ranking API here, but do not forget runOnUiThread IF running into UI thread 
    }
}

(Lua→)iOS ObjC

AppController.h
...
// Cocos2dxからコールされる関数
+ (void)setScoreObjC:(NSDictionary *)dict;
...
AppController.mm
...
+ (void)setScoreObjC:(NSDictionary *)dict{
    if ([dict objectForKey:@"score"])
    {
        int input = [[dict objectForKey:@"score"] intValue];
        //call 3rd party Ranking API here
    }
}
...

JavaやObjective-CからLuaの関数を呼ぶ

Cocos Code IDE

GameScene.lua
...
    -- Java/ObjCからカスタムイベントを使って呼び出される
    local listener = cc.EventListenerCustom:create("callLuaFunc",
        function(event)
            ...
        end)
    local eventDispatcher = layer:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer)
...

-- Javaから呼び出されるグローバルなLua関数
function callLuaFunc(param)
    local evt = cc.EventCustom:new("callLuaFunc")
    cc.Director:getInstance():getEventDispatcher():dispatchEvent(evt)
end

return GameScene

Android Java(→Lua)

AppActivity.java
// Java->Lua
Cocos2dxLuaJavaBridge.callLuaGlobalFunctionWithString("callLuaFunc", "callLuaFunc");

iOS ObjC(→Lua)

AppController.mm
// ObjC->Lua
cocos2d::Director::getInstance()->getEventDispatcher()->dispatchCustomEvent("callLuaFunc");

今後の予定

ミニゲームで使える初期化、ゲーム開始、ゲームオーバー、再開といった状態変化の実装について説明します。