- 初识cocos2dx框架
- cocos2dx项目结构(cocos2dx 3.17)
- 原生SDK
- OC语言的桥接文件
- lua语言的桥接文件
- 使用
- 一、导入SDK
- 二、使用SDK
- 总结
- Demo
初识cocos2dx框架
本文不阐述cocos2dx细节,只谈谈作为一个iOS开发,想要制作cocos2dxSDK需要了解的知识。本文以lua语言开发的cocos2dx项目、OC开发的SDK为例。Demo在文末
cocos2dx项目结构(cocos2dx 3.17)
需要明确的是
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功能,所以只需要按照上述内容填写即可实现桥接功能。
该文件路径如下,有需要可以看一下
使用
本小节将以一个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有回传。
总结
要制作cocos2dx lua SDK,需要三样东西
- 原生SDK
- OC桥接文件
- lua桥接文件
他们之间的调用关系如下
1.cocos2dx开发者调用lua桥接文件中的函数
2.lua桥接文件内部逻辑调用OC桥接文件函数
3.OC桥接文件函数调用原生SDK,并且根据传入的lua函数ID回调lua函数
左边的泳道表示代码是存在lua项目中的,右边的泳道表示代码是放在Xcode项目中的。
只要搞清楚了上面的关系,就能比较清楚的制作cocos2dx下lua语言使用的SDK了。
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
项目。