cocos2d-x,cocos2d
稜鏡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"#endifUSING_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 instancebool 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 screenpLabel->setPosition(ccp(origin.x + visibleSize.width/2,origin.y + visibleSize.height - pLabel->getContentSize().height));// add the label as a child to this layerthis->addChild(pLabel, 1);this->outputLabel = CCLabelTTF::create("Output Here", "Arial", 20);this->outputLabel->setHorizontalAlignment(kCCTextAlignmentLeft);// position the label on the center of the screenthis->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 screenpSprite->setPosition(ccp(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2));// add the sprite as a child to this layerthis->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();};};#endifvoid 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() {@Overridepublic 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);}}
真機運行:
cocos2d-x+vs是不是就可以開發安卓的遊戲了?
cocos2d-x在win32平台上開發出來的代碼還需要交叉編譯後才能產生android可以使用的包,具體操作見這個文檔
wenku.baidu.com/...b.html
另:使用cocos2d-x引擎的優勢在於便於移植性。其開發出的C++代碼只要在各平台上只要稍加改動就可以使用。而單使用ECLIPSE或Xcode環境使用的語言分別是java和Object-c,如果直接讓它們相互轉換難度肯定要大的多。
cocos2d-x+vs是不是就可以開發安卓的遊戲了?
cocos2d-x在win32平台上開發出來的代碼還需要交叉編譯後才能產生android可以使用的包,具體操作見這個文檔
wenku.baidu.com/...b.html
另:使用cocos2d-x引擎的優勢在於便於移植性。其開發出的C++代碼只要在各平台上只要稍加改動就可以使用。而單使用ECLIPSE或Xcode環境使用的語言分別是java和Object-c,如果直接讓它們相互轉換難度肯定要大的多。