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项目。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 黑茶,越来越受到诸多民众的喜爱,喜欢喝黑茶,不仅仅是因为黑茶特有的保健功效,更多的因为以下的这些优点: 导语 一、...
    馬荣軍阅读 308评论 0 0
  • 姑娘漂亮的耳廓,像一枚海螺
    桂花白阅读 268评论 0 0
  • 我终于还是败给了自己 曾经的我将自己想象的很强大,我以为自己可以足够自律,足够努力,就会像许多励志故事中所描述的那...
    原来是端阳呀阅读 117评论 0 0