1. 程式人生 > >cocos2d-x -- 渠道SDK【稜鏡】接入(1)

cocos2d-x -- 渠道SDK【稜鏡】接入(1)

稜鏡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);

}

}


真機執行效果圖: