接入SDK
管理提醒: 本帖被 fm2010 设置为精华(2014-11-12)
一、Cocos2d-x环境的搭建
关于Cocos2d-x的环境搭建,网上相关的教程已经有很多了,在此就简单的介绍一下。
1.1 所需工具及软件
1、JDK(1.7版本)
2、Android SDK(直接在Eclipse里下载所需要的SDK版本)
3、Android NDK(r9d及以上)
4、Ant
5、Python(2.7版本)
6、Eclipse ADT
7、VS2012(Windows)或XCode(Mac OS)
8、Cocos2d-x-3.3alpha0(本项目所使用的版本)
1.2 配置环境
准备好如上软件后,配置好JDK与Python的环境变量,执行Cocos2d-x下的setup.py进行各个环境变量的设置,然后就可以使用cocos命令了。
例子:
创建工程:cocos new demo -p com.game.demo -l cpp -d d:\cocos
编译Android:cocos compile -p android -j 4
二、AnySDK环境的搭建
下载打包客户端及Framework,解压文件夹,安装AnySDK打包客户端。详细使用可查看官方文档。
三、实战项目的搭建
3.1 项目源码下载
从github上下载游戏项目,由于cocos2d目录是引用Cocos2d-x-3.3alpha0的github,要确保有下载下来。(注意:Cocos2d-x 3.3alpha0中的plugin、bindings-generator、cocos2d-console也是引用)
由于external目录里的库并不完全,所以要运行cocos2d-x的download-deps.py下载external库。
3.2 项目搭建
1. 将AnySDK的Framework导入项目
打开之前下载好的AnySDK文件夹,在AnySDK_Framework_C++里有三个文件夹,查看项目工程里的Application.mk(这里应该是proj.android/jni/Application.mk这个文件)里的STL库类型APP_STL := gnustl_static,所以这里要使用的就是protocols_gnustl_static文件夹。
将protocols_gnustl_static文件夹复制到EarthWarrior3D的proj.android目录下,重命名为protocols。然后将其中的res文件夹里的东西放到proj.android的res目录里。
2. 修改Android.mk文件配置Framework编译选项
1、头文件目录里添加protocols下的android和include目录。
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \ $(LOCAL_PATH)/../protocols/android \ $(LOCAL_PATH)/../protocols/include |
2、添加PluginProtocolStatic静态库
LOCAL_WHOLE_STATIC_LIBRARIES += PluginProtocolStatic |
3、引入模块库
|
$(call import-module,protocols/android) |
3. 添加新路径至ndk module path
本项目使用build_native编译,所以修改build_native.py文件:
|
if platform = = 'win32' : ndk_module_path = 'NDK_MODULE_PATH=%s;%s;%s/external;%s/cocos' % ( "./" ,cocos_root, cocos_root, cocos_root) else : ndk_module_path = 'NDK_MODULE_PATH=%s:%s:%s/external:%s/cocos' % ( "./" ,cocos_root, cocos_root, cocos_root) |
如果使用cocos compile命令编译,则是修改build-cfg.json文件:
|
"ndk_module_path" :[ "../cocos2d" , "../cocos2d/cocos" , "../cocos2d/external" , "" ], |
4. 导入框架自带的的jar包并勾选export选项
在Eclipse里导入游戏工程和libcocos2dx工程(cocos/platform/android/java),右键点击工程,选择Properties后选择Java Build Path,在面板上点击 Libraries,通过Add JARs...将libPluginProtocol.jar引进游戏工程。
PS:如果使用cocos compile命令编译,要将libPluginProtocol.jar放到libs目录下,还需要在Application.mk里面添加一句NDK_TOOLCHAIN_VERSION=clang。
5. 配置AndroidManifest.xml添加框架需要的权限
|
< uses-permission android:name = "android.permission.INTERNET" /> < uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" /> < uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" /> < uses-permission android:name = "android.permission.RESTART_PACKAGES" /> < uses-permission android:name = "android.permission.KILL_BACKGROUND_PROCESSES" /> |
四、项目程序编写
4.1 初始化AnySDK Framework
1. 初始化JavaVM
首先,要在游戏工程加载jni的时候为AnySDK Framework设置JavaVM引用。先找到JNI_OnLoad函数,此函数是jni被加载时会首先被调用的函数。
本项目工程将platform/android目录下的javaactivity.cpp的JNI_OnLoad函数注释掉,然后拷贝JNI_OnLoad函数到main.cpp里。
1、导入头文件并声明命名空间。
|
#include "PluginJniHelper.h" using namespace anysdk::framework ; |
2、并且添加上javaVM代码。
|
PluginJniHelper::setJavaVM(vm); |
2. 在JAVA层初始化AnySDK Framework框架
1、首先找到游戏工程的主Activity,本项目为AppActivity。
2、然后重写Activity的onCreate()方法,并新增如下代码来初始化AnySDK Framework:
|
import com.anysdk.framework.PluginWrapper; protected void onCreate(Bundle savedState) { super .onCreate(savedState); PluginWrapper.init( this ); } |
3、重写Activity生命周期相关方法,代码如下:
|
import android.content.Intent; @Override protected void onResume() { PluginWrapper.onResume(); super .onResume(); } @Override public void onPause(){ PluginWrapper.onPause(); super .onPause(); } @Override protected void onActivityResult( int requestCode, int resultCode, Intent data){ PluginWrapper.onActivityResult(requestCode, resultCode, data); super .onActivityResult(requestCode, resultCode, data); } @Override protected void onNewIntent(Intent intent) { PluginWrapper.onNewIntent(intent); super .onNewIntent(intent); } |
3. 创建好需要的JAVA类和C++类
创建新的C++的文件来编写AnySDK的逻辑代码,本项目创建了个PluginChannel类来实现用户系统和支付系统的功能,PluginChannel类需要继承UserActionListener和PayResultListener,重写其事件回调函数。
JAVA创建一个wrapper类,用来调用C++的函数。在PluginChannel.cpp里定义wrapper的函数(nativeInitPlugins)。
wrapper.java的定义:
|
public class wrapper { public static native void nativeInitPlugins(); } |
PluginChannel.cpp里nativeInitPlugins的定义:
|
extern "C" { JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_wrapper_nativeInitPlugins(JNIEnv* env, jobject thiz) { PluginChannel::getInstance()->loadPlugins(); } } |
4. 在C++层初始化AnySDK Framework框架
在PluginChannel的loadPlugins函数里编写初始化、加载插件、设置监听等逻辑,然后调用该函数来进行初始化。在onCreate函数里的PluginWrapper.init(this)之后添加如下代码来进行初始化:
|
wrapper.nativeInitPlugins(); |
在PluginChannel的loadPlugins函数里所要做的处理如下:
1、初始化appKey、appSecret、privateKey、oauthLoginServer参数。
|
std::string oauthLoginServer = "http://oauth.anysdk.com/api/OauthLoginDemo/Login.php" ; std::string appKey = "BC26F841-DAC5-9244-D025-759F49997A28" ; std::string appSecret = "1dff378a8f254ec8ad4b492cae72381b" ; std::string privateKey = "696064B29E9A0B7DDBD6FCB88F34A555" ; _agent = AgentManager::getInstance(); _agent->init(appKey,appSecret,privateKey,oauthLoginServer); |
2、加载所有插件。
|
_agent->loadALLPlugin(); |
3、设置各个插件的Debug模式和监听等。
|
_pluginUser = _agent->getUserPlugin(); if (_pluginUser) { _pluginUser->setDebugMode( true ); _pluginUser->setActionListener( this ); } _pluginsIAPMap = _agent->getIAPPlugin(); std::map<std::string , ProtocolIAP*>::iterator iter; for (iter = _pluginsIAPMap->begin(); iter != _pluginsIAPMap->end(); iter++) { (iter->second)->setDebugMode( true ); (iter->second)->setResultListener( this ); } |
5. 编写PluginChannel类需要的函数
PluginChannel类里的函数众多,这里就介绍下其中的几个函数。
1、login函数,通过getUserPlugin判断下是否有存在用户插件,存在则调用login函数弹出登陆界面。
|
void PluginChannel::login() { if (_pluginUser) { _pluginUser->login(); } } |
2、payment函数,因为AnySDK支持多种支付方式,所以通过getIAPPlugin获取所有的支付插件。使用map容器来添加支付所需的各种参数信息,调用支付插件的payForProduct进行支付。如果使用多种支付方式,还需要自己处理相关UI及界面。
|
void PluginChannel::payment() { if (_pluginsIAPMap) { std::map<std::string, std::string> productInfo; productInfo[ "Product_Price" ] = "1" ; productInfo[ "Product_Id" ] = "1" ; productInfo[ "Product_Name" ] = "豌豆荚测试a1" ; productInfo[ "Server_Id" ] = "13" ; productInfo[ "Product_Count" ] = "1" ; productInfo[ "Role_Id" ] = "1" ; productInfo[ "Role_Name" ] = "1" ; productInfo[ "Role_Grade" ] = "1" ; productInfo[ "Role_Balance" ] = "1" ; std::map<std::string , ProtocolIAP*>::iterator it = _pluginsIAPMap->begin(); if (_pluginsIAPMap->size() == 1) { (it->second)->setDebugMode( true ); (it->second)->payForProduct(productInfo); } else if (_pluginsIAPMap->size() > 1) { //多支付,游戏开发商自己处理相关UI及界面 } } } |
3、exit函数,通过isFunctionSupported判断下是否有存在exit函数,存在则调用函数来弹出退出界面。退出界面点击确定将回调kExitPage事件。
|
void PluginChannel:: exit () { if (_pluginUser && _pluginUser->isFunctionSupported( "exit" )) { _pluginUser->callFuncWithParam( "exit" ,NULL); } } |
4、退出游戏处理,在接收到退出游戏的回调事件后,释放PluginChannel的内存,调用cocos2d-x的Director类的end函数结束游戏。
|
void PluginChannel::onActionResult(ProtocolUser* pPlugin, UserActionResultCode code, const char * msg) { switch (code) { case kExitPage: //退出游戏回调 purge(); Director::getInstance()->end(); break ; } } |
在析构函数里销毁用户系统以及卸载所有插件。
|
PluginChannel::~PluginChannel() { destroy(); unloadPlugins(); } void PluginChannel::destroy() { if (_pluginUser && _pluginUser->isFunctionSupported( "destroy" )) { _pluginUser->callFuncWithParam( "destroy" ,NULL); } } void PluginChannel::unloadPlugins() { _agent->unloadALLPlugin(); } |
6. 在游戏C++代码中调用PluginChannel类
为了保证Win32工程可以正常运行,所有涉及AnySDK的代码都采用条件宏判断,在Win32工程下不进行编译。
本项目只修改游戏工程的MainMenuScene类,也就是只在主菜单的场景里添加AnySDK的功能。
1、添加PluginChannel头文件
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include "PluginChannel.h" #endif |
2、修改startgame_callback函数,点击START GAME的时候将会调用login函数来弹出登陆框。
|
void MainMenuScene::startgame_callback() { CCLOG( "login" ); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) CCLOG( "PluginChannel" ); bReady = true ; PluginChannel::getInstance()->login(); //调用渠道登陆 #else CCLOG( "startgame_callback" ); CocosDenshion::SimpleAudioEngine::getInstance()->stopBackgroundMusic(); GameLayer::isDie= false ; auto scene = (LoadingScene::audioloaded) ? HelloWorld::createScene() :LoadingScene::createScene(); Director::getInstance()->replaceScene(scene); CCLOG( "startgame_callback" ); #endif } |
3、修改update函数,通过isLogined函数判断登陆状态,当状态为登陆则跳转场景开始游戏。
|
void MainMenuScene::update( float dt){ pRate+=0.01; plane->setPosition3D(Vec3(visible_size_macro.width/2+50,480-20* sin (1.05*pRate),0)); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) if (PluginChannel::getInstance()->isLogined()&&bReady) //判断登陆状态 { CocosDenshion::SimpleAudioEngine::getInstance()->stopBackgroundMusic(); GameLayer::isDie= false ; auto scene = (LoadingScene::audioloaded) ? HelloWorld::createScene() :LoadingScene::createScene(); Director::getInstance()->replaceScene(scene); } #endif } |
4、修改recharge_callback函数,调用payment函数来显示支付界面。
|
void MainMenuScene::recharge_callback() { CCLOG( "recharge" ); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) CCLOG( "PluginChannel" ); PluginChannel::getInstance()->payment(); //调用渠道支付 #else #endif } |
5、重写onKeyReleased函数来监听按键事件,在Android按返回键的时候调用退出界面。
在init函数里调用如下代码开启按键监听:
|
setKeyboardEnabled( true ); |
重写onKeyReleased函数:
|
void MainMenuScene::onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) switch (keyCode) { case EventKeyboard::KeyCode::KEY_BACK: PluginChannel::getInstance()-> exit (); break ; } #endif } |
五、编译运行游戏
最后进行编译,在编译完工程后,就可以在手机或模拟器上安装apk运行游戏了,可使用测试账号(用户名:csdn,密码:csdn)进行登陆,游戏效果如下:
接入SDK的更多相关文章
- U8SDK——游戏接入SDK(只接入抽象框架)
上一篇文章我们说了整个U8 SDK抽象成的设计,那这篇文章,我们就来验证一下,他是否如我们期待的那样,简单灵活. 正如之前所说,对于每个游戏,只需要接入抽象层,而每个渠道SDK的接入,就是该抽象层的一 ...
- 教你快速高效接入SDK——总体思路和架构
题记:很多做游戏开发的人,估计都或多或少地接过渠道SDK,什么UC,当乐,91,小米,360......据统计国内市场当前不下于100家渠道,还包括一些没有SDK的小渠道.每个渠道SDK接入的方法呢, ...
- 教你快速高效接入SDK——服务器端支付回调的处理方式
转载自:http://blog.csdn.net/chenjie19891104/article/details/48321427今天着重把之前渠道服务器端SDK的时候,遇到的一个蛋疼的问题给解决了. ...
- ios项目接入sdk事项
使用cocos2d-x引擎创建的项目在xcode里可以看到都带有一个ios目录,把要接入的sdk的包含.framework库文件和.bundle的资源文件的父目录拖入到xcode项目里的这个ios目录 ...
- Unity快速接入SDK框架
先把工程源码贴出来: 链接:http://pan.baidu.com/s/1geDhtS3 密码:i0s9 最近接android ios的SDK 已经接了10多个 有点心得 分享一下 如果有更好想法求 ...
- 教你高速高效接入SDK——Unity统一接入渠道SDK(Android篇)
U8SDK的设计之初,就是为了可以支持各种游戏引擎开发的游戏,而不不过Android的原生平台.眼下一大半的手游,都是採用Unity3D和Cocos2dx开发,那么这里,我们就先来一步步给大家演示,用 ...
- 接入 SDK 结果翻车了?了解 SDK 的那些事
前段时间,二狗子的朋友圈被工信部发布的<关于下架侵害用户权益 App 名单的通报>给刷屏了.公告中指出有 90 款 App 未按照要求完成整改将会下架.而这 90 款 App 涉及全国各地 ...
- GrowingIO接入SDK简介
安装使用文档逐步操作 准备工作: 1.注册一个GrowingIO账号 2.申请一个域名(注意:不能是ip或host) 登陆gio平台: 1.安装SDK 2.根据项目选择对应的sdk:js,安卓,ios ...
- Unity - 接入Android SDK
在网络上,关于Unity与Android如何进行交互,雨松MOMO大神已经有两篇文章简单介绍了如何操作(1)Unity3D研究院之打开Activity与调用JAVA代码传递参数(2)Unity3D研究 ...
随机推荐
- Linux基础知识入门
[Linux基础]Linux基础知识入门及常见命令. 前言:最近刚安装了Linux系统, 所以学了一些最基本的操作, 在这里把自己总结的笔记记录在这里. 1,V8:192.168.40.10V1: ...
- angularjs学习笔记—事件指令
ngClick 适用标签:所有触发条件:单击 #html <div ng-controller="LearnCtrl"> <div ng-click=" ...
- 基于Http原理实现Android的图片上传和表单提交
版权声明:本文由张坤 原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/794875001483009140 来源:腾云阁 ...
- iOS工程结构
好的架构不是设计出来的,而是进化而来的! 写在前面 从2011年底开始学习iOS开发,到现在也已经快3年了,虽然中途没有一直进行iOS的开发(总是在Android和iOS间切换),但始终没 ...
- Effective Java实作Comparator - 就是爱Java
如果集合或数组内的对象,有1个以上不同的排序逻辑时,那该如何处理呢?尤其是当已经实现了Comparable,又不能变动原本的逻辑时,Mix会采用Comparator来处理. 阅读全文>>
- linux下的shell和脚本
1.各种Unix shell linux下的shell基本是从unix环境中的shell发展而来,贴一下wiki:其中我们常用的,可归类为Bourne Shell(/usr/bin/sh或/bin/s ...
- DateTime字段控件值显示短格式的做法
后台取dateTime格式,前台格式化就好了 <input type="text" name="txtPartyTime" id="txtPar ...
- hdu2082:简单母函数
题目大意: a,b,c,d...z这些字母的价值是1,2,3......26 给定 这26个字母分别的数量,求总价值不超过50的单词的数量 分析: 标准做法是构造母函数 把某个单词看作是,关于x的多项 ...
- Makefile学习(二)条件判断和内嵌函数
第七章:Makefile的条件执行 条件语句可是是两个不同的变量.或者变量和常量值的比较: 7.1例子: 对变量“CC”进行判断,其值如果是“gcc ”那么在程序连接时使用库“libgnu.so”或者 ...
- install samba on crux without net.
1. 解压文件 tar -xvfz samba-.tar.gz 2. 进入目录 cd samba- 3. 配置 ./configure 4. 编译 make 5. 安装 make install