U8SDK——Cocos2dx游戏快速接入U8SDK(接入篇)
最近抽了点时间,折腾了下cocos2dx中接入U8SDK的Demo。同时,简单封装了下,使得在cocos2dx中能够快速地接入U8SDK。
先说下大体的思路。和之前说的在Unity中接入U8SDK一样,在Cocos2dx中接入U8SDK,我们也分为两步,一个Android中的部分,另 一个是Coccos2dx中的部分。同时,我们希望尽可能地封装不同平台之间数据的传递,以及接口的调用。使得大部分游戏基于这个封装,都可以最快地 速度来完成U8SDK的接入。
- 新建一个Android工程,作为U8SDK和Cocos2dx的一个中间工程(U8SDK_Cocos2dx),主要负责U8SDK的接口调用封装,参数传递和解析等。这个工程,对于所有游戏都试用。
- 在Cocos2dx中封装JNI调用,以及和Android中交互的数据格式等的定义和解析。同样地,这部分对于所有游戏也都适用。游戏中只需要调用这里提供的相关接口,以及实现相应的回调即可完成接入。
这篇文章,我们先来总体看看,对于一个新的Cocos2dx的开发的游戏,怎么根据我们的封装,快速完成U8SDK的抽象层的接入,从而直接打出母包,再通过一键打包工具,打出最终的多个渠道包。
首先, 我们使用cocos new 新建一个Cocos2dx(我这里使用的是Cocos2dx 3.x版本)工程,名为HelloCocos。
然后,解压u8sdk_cocos2dx.zip文件到HelloCocos/Classes目录下:
紧接着,我们新建两个按钮,一个登录,一个支付。 再新建一个Label,显示当前的登录状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
this->labelUsername = Label::createWithTTF("U8SDK", "fonts/Marker Felt.ttf", 24); // position the label on the center of the screen this->labelUsername->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height - this->labelUsername->getContentSize().height)); // add the label as a child to this layer this->addChild(this->labelUsername, 1); ui::Button* btnLogin = ui::Button::create("login_normal.png", "login_selected.png"); btnLogin->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y + 30)); btnLogin->addClickEventListener(CC_CALLBACK_1(HelloWorld::loginClickCallback, this)); // add the sprite as a child to this layer this->addChild(btnLogin, 0); ui::Button* btnPay = ui::Button::create("pay_normal.png", "pay_selected.png"); btnPay->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y - 30)); btnPay->addClickEventListener(CC_CALLBACK_1(HelloWorld::payClickCallback, this)); // add the sprite as a child to this layer this->addChild(btnPay, 0); ~~~~~~ 然后,我们就可以开始U8SDK的接入了。 1、HelloWorldScene.h中的HelloWorld类,继承U8SDKCallback抽象类,实现该类中的几个回调接口,代码 如下: ~~~~~~ #ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "ui/CocosGUI.h" #include "u8sdk/U8SDKInterface.h" class HelloWorld : public cocos2d::Layer,U8SDKCallback { private: cocos2d::Label* labelUsername; public: // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); void loginClickCallback(cocos2d::Ref* pSender); void payClickCallback(cocos2d::Ref* pSender); // a selector callback void menuCloseCallback(cocos2d::Ref* pSender); virtual void OnInitSuc(); virtual void OnLoginSuc(U8LoginResult* result); virtual void OnSwitchLogin(); virtual void OnLogout(); // implement the "static create()" method manually CREATE_FUNC(HelloWorld); }; #endif // __HELLOWORLD_SCENE_H__ |
2、HelloWorldScene.cpp中init方法的最后,我们调用U8SDK的初始化方法:
U8SDKInterface::getInstance()->initSDK(this);
同时,这里要实现第一步中添加的U8SDKCallback中的回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
void HelloWorld::OnInitSuc() { CCLOG("SDK初始化成功..."); //一般不需要做什么处理 } void HelloWorld::OnLoginSuc(U8LoginResult* result) { CCLOG("SDK登录并认证成功...%s",result->userId.c_str()); this->labelUsername->setString(result->sdkUsername); if (result->isSwitchAccount) { //TODO:这里退回到登录界面,并且SDK是已经登录成功状态,不用再弹出SDK的登录界面 } else { //TODO:登录认证成功,获取服务器列表,进入游戏服... } } void HelloWorld::OnSwitchLogin() { CCLOG("切换帐号成功..."); //TODO:退回到登录界面,并弹出SDK登录界面(调用U8SDKInterface::getInstance()->login()) } void HelloWorld::OnLogout() { CCLOG("SDK帐号退出成功..."); this->labelUsername->setString("U8SDK"); //TODO:退回到登录界面,并弹出SDK登录界面(调用U8SDKInterface::getInstance()->login()) } |
3、定义登录按钮和支付按钮的点击事件,登录点击的时候,触发登录;U8SDKInterface::getInstance()->login();支付按钮点击的时候,触发支付:U8SDKInterface::getInstance()->pay(params);完整的代码,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
#include "HelloWorldScene.h" USING_NS_CC; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image, which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , origin.y + closeItem->getContentSize().height/2)); // create menu, it's an autorelease object auto menu = Menu::create(closeItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1); ///////////////////////////// // 3. add your codes below... // add a label shows "Hello World" // create and initialize a label this->labelUsername = Label::createWithTTF("U8SDK", "fonts/Marker Felt.ttf", 24); // position the label on the center of the screen this->labelUsername->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height - this->labelUsername->getContentSize().height)); // add the label as a child to this layer this->addChild(this->labelUsername, 1); ui::Button* btnLogin = ui::Button::create("login_normal.png", "login_selected.png"); btnLogin->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y + 30)); btnLogin->addClickEventListener(CC_CALLBACK_1(HelloWorld::loginClickCallback, this)); // add the sprite as a child to this layer this->addChild(btnLogin, 0); ui::Button* btnPay = ui::Button::create("pay_normal.png", "pay_selected.png"); btnPay->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y - 30)); btnPay->addClickEventListener(CC_CALLBACK_1(HelloWorld::payClickCallback, this)); // add the sprite as a child to this layer this->addChild(btnPay, 0); //NDKHelper::addSelector("U8Selectors", "onU8LoginResult", CC_CALLBACK_2(HelloWorld::onU8LoginResult, this), this); U8SDKInterface::getInstance()->initSDK(this); return true; } void HelloWorld::OnInitSuc() { CCLOG("SDK初始化成功..."); //一般不需要做什么处理 } void HelloWorld::OnLoginSuc(U8LoginResult* result) { CCLOG("SDK登录并认证成功...%s",result->userId.c_str()); this->labelUsername->setString(result->sdkUsername); if (result->isSwitchAccount) { //TODO:这里退回到登录界面,并且SDK是已经登录成功状态,不用再弹出SDK的登录界面 } else { //TODO:登录认证成功,获取服务器列表,进入游戏服... } } void HelloWorld::OnSwitchLogin() { CCLOG("切换帐号成功..."); //TODO:退回到登录界面,并弹出SDK登录界面(调用U8SDKInterface::getInstance()->login()) } void HelloWorld::OnLogout() { CCLOG("SDK帐号退出成功..."); this->labelUsername->setString("U8SDK"); //TODO:退回到登录界面,并弹出SDK登录界面(调用U8SDKInterface::getInstance()->login()) } void HelloWorld::loginClickCallback(Ref *pSender) { CCLOG("Btn Login Clicked...U8 Login..."); U8SDKInterface::getInstance()->login(); } void HelloWorld::payClickCallback(Ref *pSender) { CCLOG("Btn Pay Clicked...U8 Pay..."); U8PayParams* params = U8PayParams::create(); params->productId = "1"; params->productName = "元宝"; params->productDesc = "购买100元宝,赠送20元宝"; params->price = 100; params->buyNum = 1; params->coinNum = 300; params->serverId = "10"; params->serverName = "地狱之恋"; params->roleId = "u8_24532452"; params->roleName = "麻利麻利吼"; params->roleLevel = 15; params->vip = "v15"; //去服务器获取游戏中商品的订单号以及扩展数据,这里测试 params->orderID = "345435634534"; params->extension = "test111"; U8SDKInterface::getInstance()->pay(params); } void HelloWorld::menuCloseCallback(Ref* pSender) { Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif } |
4、 将HelloCocos生成proj.android导入到eclipse中,然后将U8SDK2和U8SDK_Cocos2dx工程生成的jar包(分 别是u8sdk2.jar和u8sdk_cocos2dx.jar)拷贝到HelloCocos安卓工程的libs目录下。然后,将生成的 AppActivity.java,本来是继承Cocos2dxActivity的,改为继承U8CocosActivity。
同时,将AndroidManifest.xml中的application节点中,加上android:name=”com.u8.sdk.U8Application”
最后,为了能够在Android中编译并运行,我们还需要将U8SDK包含的这些Cpp文件,添加到Android.mk中,最终的文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) $(call import-add-path,$(LOCAL_PATH)/../../cocos2d) $(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external) $(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos) $(call import-add-path,$(LOCAL_PATH)/../../Classes/jansson) LOCAL_MODULE := cocos2dcpp_shared LOCAL_MODULE_FILENAME := libcocos2dcpp LOCAL_SRC_FILES := hellocpp/main.cpp \ ../../Classes/AppDelegate.cpp \ ../../Classes/HelloWorldScene.cpp \ ../../Classes/jansson/value.c \ ../../Classes/jansson/utf.c \ ../../Classes/jansson/strconv.c \ ../../Classes/jansson/strbuffer.c \ ../../Classes/jansson/pack_unpack.c \ ../../Classes/jansson/memory.c \ ../../Classes/jansson/load.c \ ../../Classes/jansson/hashtable.c \ ../../Classes/jansson/error.c \ ../../Classes/jansson/dump.c \ ../../Classes/NDKHelper/CallFuncNV.cpp \ ../../Classes/NDKHelper/NDKCallbackNode.cpp \ ../../Classes/NDKHelper/NDKHelper.cpp \ ../../Classes/u8sdk/U8SDKData.cpp \ ../../Classes/u8sdk/U8SDKNativeCallback.cpp \ ../../Classes/u8sdk/U8SDKInterface.cpp \ LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \ $(LOCAL_PATH)/../../cocos2d/cocos/ui # _COCOS_HEADER_ANDROID_BEGIN # _COCOS_HEADER_ANDROID_END LOCAL_STATIC_LIBRARIES := cocos2dx_static LOCAL_STATIC_LIBRARIES += cocos_ui_static # _COCOS_LIB_ANDROID_BEGIN # _COCOS_LIB_ANDROID_END include $(BUILD_SHARED_LIBRARY) $(call import-module,.) $(call import-module,ui) # _COCOS_LIB_IMPORT_ANDROID_BEGIN # _COCOS_LIB_IMPORT_ANDROID_END |
到这里,接入就算完成了。我们可以使用cocos compile -p android 命令来编译Android平台,之前的操作如果稍有不慎,这里编译的过程中,也许会遇到一些错误,不过,看着啥错误,一一解决即可。
编译成功之后,在proj.android的bin目录下会生成一些apk文件,将HeroCocos-debug.apk拷贝到U8SDK打包工具目录下,替换原来的u8.apk
然后,运行package.bat,选择需要打包的渠道,然后就开始打包了,打包完成之后,在output目录下生成当前渠道SDK的渠道包,比如最终UC的包:
本文出自 U8SDK技术博客,转载时请注明出处及相应链接。
本文永久链接: http://www.uustory.com/?p=1886