棱鏡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
客戶端接入流程
1.將Demo項目中Classes/GameProxy.h 複製到你的C++工程中頭文件存放的位置,如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() << "\ntoken : " << user.getToken() << "\nchannelId : " << 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 << "\ncustomParams: " << 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);
}
}
真機運行效果圖: