iOS制作cocos2dx lua SDK

  • 初识cocos2dx框架
    • cocos2dx项目结构(cocos2dx 3.17)
  • 原生SDK
  • OC语言的桥接文件
  • lua语言的桥接文件
  • 使用
    • 一、导入SDK
    • 二、使用SDK
  • 总结
  • Demo

初识cocos2dx框架

本文不阐述cocos2dx细节,只谈谈作为一个iOS开发,想要制作cocos2dxSDK需要了解的知识。本文以lua语言开发的cocos2dx项目、OC开发的SDK为例。Demo在文末

cocos2dx项目结构(cocos2dx 3.17)

iOS平台项目目录.png

lua开发目录.png

需要明确的是

1.cocos2dx项目会导出多平台的项目,必然也有iOS平台的Xcode项目,所以我们是可以集成原生SDK到cocos2dx的iOS项目中的。

2.cocos2dx的开发都是在src/app目录下进行的,全程用lua语言编写,并且除了生成项目时框架会自动转化一部分OC代码使项目能正常运行以外,后续编写的任意lua代码不会映射到Xcode项目中生成对应的OC代码。所以比如想集成方用lua写个按钮然后在Xcode项目中找到对应地方调用原生SDK的想法是不成立的。在cocos2dx项目中生成Xcode的项目作用更多的就像一个启动器,启动后代码就黑盒的按照src/app目录下的代码流程开始运行,只通过Xcode项目无法干涉,无法实现自由调用SDK的目的。

所以想要cocos2dx开发用户能正常使用我们的SDK我们还需要进行一些特殊操作,总的来说就是我们需要准备如下几样东西。

  • 原生SDK
  • OC语言的桥接文件 (作用为处理lua桥接文件的调用事件,并调用原生SDK)
  • lua语言的桥接文件(作用为给集成方使用,集成进lua的代码里面调用OC语言的桥接文件)

下面就讲讲上述三种东西需要进行的工作

原生SDK

cocos2dx导出的iOS项目是MRC的。所以,如果你提供的原生SDK里面包含其他的第三方库或者ARC的.m文件是编译不通过的,如果这种文件的量很小可以通过逐个设置ARC的方式解决。如果量大不方便解决的话建议将这类文件打入静态库中,不管ARC还是MRC都是针对编译阶段的,不影响静态库。

如果你的SDK中有使用类别,那么在Other Linker Flags中添加了-Objc后依然还是会崩溃。此时我们需要添加的是-force_load 路径/xxx.framework/xxx来手动指向静态库。注意此处的xxx为framework双击进去的二进制文件的名字,一般情况该二进制文件名字与framework名字相同
再次注意路径不是指向framework为止,而是指向framework内部的二进制文件

其他在原生项目中集成SDK需要进行的配置照旧进行。

下文将假设SDK有如下内容进行

@interface Cocos2dxiOSLuaSDK : NSObject

+ (void)showDetailPageWithProductId:(NSString *)productId;

@end

@implementation Cocos2dxiOSLuaSDK

+ (void)showDetailPageWithProductId:(NSString *)productId{

    if (productId) {
          NSLog(@"lua 调用 iOSSDK成功 productId:%@", productId);
     }else{
          NSLog(@"lua 调用 iOSSDK成功 productId为空");
     }

}

@end

OC语言的桥接文件

跟平时开发一样创建OC文件,命名为Cocos2dxiOSLuaSDKBridge。并将Cocos2dxiOSLuaSDKBridge.m修改为Cocos2dxiOSLuaSDKBridge.mm
(命名无特殊要求,只要iOS开发者明白是OC桥接文件就行,改成.mm是因为如果有OC回调lua的需求的话必须改成.mm才能正常执行代码)

.h

@interface Cocos2dxiOSLuaSDKBridge : NSObject

//此处的方法作用为处理lua桥接文件的调用事件,并调用原生SDK

/*
cocos2dx框架限制,和lua交互的OC方法必须
1.是静态(+号)方法并且无返回值。
2.参数只能是无或者字典类型。
如果上述内容任意一项有误则在后续运行Xcode项目lua调用OC桥接函数时会报`INVALID METHOD SIGNATURE`错误

此处的方法命名无特殊要求,只要iOS开发者能明白是干什么的就行。
cocos2dx开发者不会关心这个名字,一般来说也看不到这个名字。
*/
+(void)Cocos2dxiOSLuaSDKBridgeSelector:(NSDictionary *)dic;

+(void)Cocos2dxiOSLuaSDKBridgeNoParameterSelector;

@end
.m

#import "Cocos2dxiOSLuaSDK.h"

#import "cocos2d.h"
#include "scripting/lua-bindings/manual/CCLuaEngine.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
#include "scripting/lua-bindings/manual/platform/ios/CCLuaObjcBridge.h"
#endif
USING_NS_CC;

@implementation Cocos2dxiOSLuaSDKBridge

+(void)Cocos2dxiOSLuaSDKBridgeSelector:(NSDictionary *)dic{

    NSString *productId = dic[@"productId"];

    [Cocos2dxiOSLuaSDK showDetailPageWithProductId:productId];
    
    //以下为OC根据传入的函数ID回调lua函数的逻辑
    int functionId = [[dic objectForKey:@"functionId"] intValue];
    
    LuaObjcBridge::pushLuaFunctionById(functionId);
    //将需要传递给 Lua function 的参数放入 Lua stack
    
    //返回参数,注意必须进行utf-8转换否则编译报错,如要传递多个参数请将此处字符串转为json字符串传递
    LuaObjcBridge::getStack()->pushString([[NSString stringWithFormat:@"productId=%@", productId] UTF8String]);
    LuaObjcBridge::getStack()->executeFunction(1);//1个参数
    LuaObjcBridge::releaseLuaFunctionById(functionId);//释放
}

+(void)Cocos2dxiOSLuaSDKBridgeNoParameterSelector{
  
  [Cocos2dxiOSLuaSDK showDetailPageWithProductId:nil];

}

@end

lua语言的桥接文件

创建一个跟SDK同名的lua文件,作为“lua语言的SDK”供cocos2dx开发者集成进游戏开发项目使用。(如不方便创建,直接创建一个txt文本改后缀名即可。)

文件内容如下

--固定句式
local targetPlatform = cc.Application:getInstance():getTargetPlatform()
--把样例内容替换成自己SDK的名字
local Cocos2dxiOSLuaSDK = class("Cocos2dxiOSLuaSDK")

--格式为上面声明的名字:函数名 命名无特殊要求,但是此处函数名是cocos2dx开发者会看到并调用的,请做到一眼就能明白作用的效果
function Cocos2dxiOSLuaSDK:showDetailPageWithProductId(productId, callback)
    print("call showDetailPageWithProductId start")
    if (cc.PLATFORM_OS_ANDROID == targetPlatform) then
        --此处为安卓SDK调用逻辑,因为对于cocos2dx开发者而言,不关心是什么平台
        --所以需要实现lua调用一个函数自动识别平台并调用对应SDK的目的(安卓/iOS 共用一个lua桥接文件),此处需要给安卓开发者预留空间
    end
    --固定句式
    if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) then 
        --固定句式
        local luaoc = require "cocos.cocos2d.luaoc" 
        --参数只能传字典或者不传,此处传入的回调函数并非函数而只是个标识符
        local args = {productId = productId, functionId = callback}
        --固定句式,第一个参数是OC桥接文件的类名,第二个参数是OC桥接文件中想要调用的方法名,第三个参数是传入的字典
        local ok, ret = luaoc.callStaticMethod("Cocos2dxiOSLuaSDKBridge","Cocos2dxiOSLuaSDKBridgeSelector",args)
        if not ok then
            print("luaoc showDetailPageWithProductId error:"..ret)
        end
    end
end

function Cocos2dxiOSLuaSDK:showDetailPage()
    print("call showDetailPage start")
    if (cc.PLATFORM_OS_ANDROID == targetPlatform) then

    end
    if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) then
        local luaoc = require "cocos.cocos2d.luaoc"
        local ok, ret = luaoc.callStaticMethod("Cocos2dxiOSLuaSDKBridge","Cocos2dxiOSLuaSDKBridgeNoParameterSelector")
        if not ok then
            print("luaoc showDetailPage error:"..ret)
        end
    end
end

return Cocos2dxiOSLuaSDK

cocos2dx框架自带的luaoc.lua文件提供了方便的lua桥接OC功能,所以只需要按照上述内容填写即可实现桥接功能。

该文件路径如下,有需要可以看一下


image.png

使用

本小节将以一个cocos2dx开发者的视角来集成iOS SDK。

一、导入SDK

1.下载SDK
下载的SDK应该包含上面提到的三个内容

  • 原生SDK
  • OC语言桥接文件
  • lua语言桥接文件

2.导入SDK
①.导入原生SDK和OC桥接文件到Xcode项目中(一般是iOS目录下),并根据说明文档配置项目,以保证项目能编译通过。
②.导入lua语言桥接文件到cocos2dx开发项目中(一般是src/app/models目录下)

二、使用SDK

1.在需要使用SDK的lua文件头部引用lua桥接文件

--引号部分为lua桥接文件路径,根据实际情况修改
local Cocos2dxiOSLuaSDK = require("app.models.Cocos2dxiOSLuaSDK")

2.调用lua桥接文件的内容,实现调用原生SDK的目的

local productId = "1234567890"
Cocos2dxiOSLuaSDK:showDetailPageWithProductId(productId)

如有需要可以直接把src/app/views/MainScene.lua替换为如下内容以便后续查看效果

local MainScene      = class("MainScene", cc.load("mvc").ViewBase)
local Cocos2dxiOSLuaSDK = require("app.models.Cocos2dxiOSLuaSDK")

function MainScene:onCreate()
    --此处只声明了,未调用,调用由OC进行
    local function wakeUpCallBack(result)
        cc.Label:createWithSystemFont("OC拉起lua回调,回传内容:"..result, "Arial", 40)
            :move(display.cx, display.cy - 100)
            :addTo(self)
    end

    local button1 = cc.MenuItemImage:create("PlayButton.png", "PlayButton.png")
        :onClicked(function()
            local productId = "1234567890"
            Cocos2dxiOSLuaSDK:showDetailPageWithProductId(productId, wakeUpCallBack)
        end)
    local button2 = cc.MenuItemImage:create("start.png", "start.png")
        :onClicked(function()
            Cocos2dxiOSLuaSDK:showDetailPage()
        end)
    cc.Menu:create(button1)
        :move(display.cx, display.cy + 100)
        :addTo(self)

    cc.Menu:create(button2)
        :move(display.cx, display.cy + 200)
        :addTo(self)
end

return MainScene

3.run Xcode项目查看效果

start键为不传参数调用SDK, play键为传递参数调用SDK并且OC有回传。

效果.gif

总结

要制作cocos2dx lua SDK,需要三样东西

  • 原生SDK
  • OC桥接文件
  • lua桥接文件

他们之间的调用关系如下
1.cocos2dx开发者调用lua桥接文件中的函数
2.lua桥接文件内部逻辑调用OC桥接文件函数
3.OC桥接文件函数调用原生SDK,并且根据传入的lua函数ID回调lua函数

调用关系

左边的泳道表示代码是存在lua项目中的,右边的泳道表示代码是放在Xcode项目中的。

只要搞清楚了上面的关系,就能比较清楚的制作cocos2dx下lua语言使用的SDK了。

Demo

地址:Cocos2dx_lua_iOSSDK_Demo

重点内容:
1.frameworks/runtime-src/proj.ios_mac/ios/Cocos2dxiOSLuaSDK路径下的OC桥接文件 Cocos2dxiOSLuaSDKBridge
2.src/app/models路径下的 lua桥接文件 Cocos2dxiOSLuaSDK.lua
3.src/app/views 路径下的 使用样例文件 MainScene.lua

如果需要运行查看效果则直接运行frameworks/runtime-src/proj.ios_mac/路径下的HelloWorldNew.xcodeproj项目。

你可能感兴趣的:(iOS制作cocos2dx lua SDK)