棱镜SDK简单介绍
若想让游戏上线,渠道接入步骤是不可缺少的,为了避免一对一接入渠道问题,我选择了棱镜SDK,由于棱镜是游戏与渠道SDK的中间层,为CP厂商屏蔽各个渠道SDK之间的差异,整个接入过程,不会改变各个渠道SDK的功能、特性、參数等,对玩家全然透明。
棱镜平台基本工作原理:http://dev.ljsdk.com/ljdocs/lj_principle.html
棱镜技术接入文档(cocos2d-x)::http://dev.ljsdk.com/ljdocs/lj_tech_integration_cpp.html
棱镜SDK下载:http://dev.ljsdk.com/ljdocs/lj_tech_general.html
client接入流程
1.将Demo项目中Classes/GameProxy.h 拷贝到你的C++project中头文件存放的位置,如Cocos2dx项目放入Classes文件夹, 将Classes/gameproxy.cpp 放入源代码文件夹,如Cocos2dx的Classes文件夹:
2.windows平台加入代码例如以下:
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" class HelloWorld : public cocos2d::CCLayer { public: // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::CCScene* scene(); // a selector callback void menuCloseCallback(CCObject* pSender); void setUserListener(); void loginCallback(CCObject* pSender); void logoutCallback(CCObject* pSender); void chargeCallback(CCObject* pSender); void payCallback(CCObject* pSender); void exitCallback(CCObject* pSender); void showInfo(const char* str); // implement the "static node()" method manually CREATE_FUNC(HelloWorld); private: cocos2d::CCLabelTTF* outputLabel; }; #endif // __HELLOWORLD_SCENE_H__HelloWorldScene.cpp
#include "HelloWorldScene.h" #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include "GameProxy.h" #endif USING_NS_CC; CCScene* HelloWorld::scene() { // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object HelloWorld *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 ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); CCLabelTTF* pLabel = CCLabelTTF::create("CoCos2d-x SDKTest", "Arial", 30); // position the label on the center of the screen pLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height - pLabel->getContentSize().height)); // add the label as a child to this layer this->addChild(pLabel, 1); this->outputLabel = CCLabelTTF::create("Output Here", "Arial", 20); this->outputLabel->setHorizontalAlignment(kCCTextAlignmentLeft); // position the label on the center of the screen this->outputLabel->setAnchorPoint(ccp(0, 0)); this->outputLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y)); this->addChild(this->outputLabel, 1); // add "HelloWorld" splash screen" CCSprite* pSprite = CCSprite::create("icon.png"); // position the sprite on the center of the screen pSprite->setPosition(ccp(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2)); // add the sprite as a child to this layer this->addChild(pSprite, 0); CCMenuItemFont *loginItem = CCMenuItemFont::create( "login", this, menu_selector(HelloWorld::loginCallback)); CCMenuItemFont *logoutItem = CCMenuItemFont::create( "logout", this, menu_selector(HelloWorld::logoutCallback)); CCMenuItemFont *chargeItem = CCMenuItemFont::create( "charge", this, menu_selector(HelloWorld::chargeCallback)); CCMenuItemFont *payItem = CCMenuItemFont::create( "pay", this, menu_selector(HelloWorld::payCallback)); CCMenuItemFont *exitItem = CCMenuItemFont::create( "exit", this, menu_selector(HelloWorld::exitCallback)); float borderWidth = 0; float currentYBorder = origin.y + visibleSize.height; float offset = borderWidth + loginItem->getContentSize().height/2; loginItem->setPosition(ccp(origin.x + loginItem->getContentSize().width/2 + borderWidth, currentYBorder - offset)); currentYBorder -= 2 * offset; offset = borderWidth + logoutItem->getContentSize().height/2; logoutItem->setPosition(ccp(origin.x + logoutItem->getContentSize().width/2 + borderWidth , currentYBorder - offset)); currentYBorder -= 2 * offset; offset = borderWidth + chargeItem->getContentSize().height/2; chargeItem->setPosition(ccp(origin.x + chargeItem->getContentSize().width/2 + borderWidth , currentYBorder - offset)); currentYBorder -= 2 * offset; offset = borderWidth + payItem->getContentSize().height/2; payItem->setPosition(ccp(origin.x + payItem->getContentSize().width/2 + borderWidth , currentYBorder - offset)); currentYBorder -= 2 * offset; offset = borderWidth + exitItem->getContentSize().height/2; exitItem->setPosition(ccp(origin.x + exitItem->getContentSize().width/2 + borderWidth , currentYBorder - offset)); CCMenu* pMenu = CCMenu::create(loginItem,logoutItem,chargeItem,payItem,exitItem,NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu,1,2); #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) this->showInfo(GameProxy::GetAndroidManifestMeta("XMGAME_PRODUCT_CODE")); #endif return true; } void HelloWorld::showInfo(const char *info){ this->outputLabel->setString(info); CCLOG("showinfo %s", info); } #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) class XMUserListenerImpl: public XMUserListener { private: HelloWorld * parent; public: XMUserListenerImpl(HelloWorld* parent) { this->parent = parent; } virtual void onLoginSuccess(XMUser user, const char *customParams) { // 游戏的登陆逻辑须要写在这里 // 当游戏调用 GameProxy::Login(params) 时,该函数会被调用 // 当中user对象为渠道登陆系统返回的用户相关參数,包括uid token 渠道号等 // 当中params为调用GameProxy::Login( params)时,传入的params // 确保该函数被调用后,用户能够正确地进入游戏 CCLOG("login success"); stringstream is; is << "uid : " << user.getUserId() << " token : " << user.getToken() << " channelId : " << user.getChannelId(); parent->showInfo(is.str().c_str()); GameProxy::SetXMRoleData("1", "hi", "10", "1", "1"); }; virtual void onLoginFailed(const char *reason, const char *customParams) { stringstream is; is << "login failed reason: " << reason << " customParams: " << customParams; parent->showInfo(is.str().c_str()); }; virtual void onLogout(const char *customParams) { // 游戏相关的用户登出注销逻辑须要写在这里 // 当渠道的用户中心界面中点击注销,该函数会被调用 // 当游戏调用 GameProxy::Logout(params) 时,该函数也会被调用 // 当中params为用户调用 GameProxy::Logout(params) 时传入的params // params能够用来传递一些游戏中的上下文,能够是随意字符串 // 确保游戏中不论什么时候,该函数被调用后,游戏能够正确登出 parent->showInfo("logout"); }; }; class PayCallBackImpl:public PayCallBack{ private: HelloWorld* parent; public: PayCallBackImpl(HelloWorld* parent) { this->parent = parent; } virtual void onPaySuccess(char *successinfo){ stringstream is; is << "sucess: " <<successinfo; parent->showInfo(is.str().c_str()); }; virtual void onPayFail(char *failinfo){ stringstream is; is << "payfailed: " << failinfo; parent->showInfo(is.str().c_str()); }; }; class ExitCallBackImpl:public ExitCallBack{ public: virtual void onGameExit(){ CCDirector::sharedDirector()->end(); }; virtual void onNo3rd(){ CCDirector::sharedDirector()->end(); }; }; #endif void HelloWorld::setUserListener(){ #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) GameProxy::SetUserListener(new XMUserListenerImpl(this)); #endif } void HelloWorld::loginCallback(CCObject* pSender) { #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) this->showInfo("logining"); HelloWorld::setUserListener(); const char *customParams = "login"; GameProxy::Login(customParams); #endif } void HelloWorld::logoutCallback(CCObject* pSender){ #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) const char *customParams = "logout"; GameProxy::Logout(customParams); #endif } void HelloWorld::chargeCallback(CCObject* pSender){ #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) const char *itemName = "元宝"; int unitPrice = 10; int defalutNum = 500; const char *callBackInfo = "this is callback info..."; const char *callbackUrl = "http://test"; GameProxy::Charge(itemName, unitPrice, defalutNum, callBackInfo, callbackUrl,new PayCallBackImpl(this)); #endif } void HelloWorld::payCallback(CCObject* pSender){ #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) int amount = 10; const char *unitName = "天币"; int count = 118; const char *callBackInfo = "this is callback info"; const char *callbackUrl = "http://test"; GameProxy::Pay(amount, unitName, count, callBackInfo, callbackUrl, new PayCallBackImpl(this)); #endif } void HelloWorld::exitCallback(CCObject* pSender){ #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) GameProxy::Exit(new ExitCallBackImpl()); #endif } void HelloWorld::menuCloseCallback(CCObject* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); #else CCDirector::sharedDirector()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif #endif }
3.android平台:
环境搭建:
将Demo项目中libs文件夹下jar包拷贝到游戏项目的libs文件夹下
将Demo项目中assets文件夹下的文件拷贝到游戏项目的assets文件夹下
Android.mk:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.InsetSDK.org" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8"/> <uses-feature android:glEsVersion="0x00020000" /> <application android:name="com.xinmei365.game.proxy.XMApplication" android:label="@string/app_name" android:icon="@drawable/icon"> <activity android:name=".InsetSDK" android:label="@string/app_name" android:screenOrientation="landscape" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:configChanges="orientation"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <meta-data android:name="XMGAME_CHANNEL_CODE" android:value="9f10f46c37214442ba473b5409a05ebf" /> <meta-data android:name="XMGAME_PRODUCT_CODE" android:value="lsjs" /> </application> <supports-screens android:largeScreens="true" android:smallScreens="true" android:anyDensity="true" android:normalScreens="true"/> <uses-permission android:name="android.permission.INTERNET"/> </manifest>Activity的Java代码:
public class InsetSDK extends Cocos2dxActivity{ protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); GameProxyNativeStub.init(this, GameProxy.getInstance(), new XMGLThreadRunner() { @Override public void runOnGLThread(Runnable pRunnable) { InsetSDK.this.runOnGLThread(pRunnable); }}); GameProxy.getInstance().applicationInit(this); GameProxy.getInstance().onCreate(this); } public Cocos2dxGLSurfaceView onCreateView() { Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this); // InsetSDK should create stencil buffer glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8); return glSurfaceView; } static { System.loadLibrary("cocos2dcpp"); } public void onStop() { super.onStop(); GameProxy.getInstance().onStop(this); } public void onDestroy() { super.onDestroy(); GameProxy.getInstance().onDestroy(this); } public void onResume() { super.onResume(); GameProxy.getInstance().onResume(this); } public void onPause() { super.onPause(); GameProxy.getInstance().onPause(this); } public void onRestart() { super.onRestart(); GameProxy.getInstance().onRestart(this); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); GameProxy.getInstance().onActivityResult(this, requestCode, resultCode, data); } }
真机执行效果图: