[cocos2d-x / Android篇]教學4︰在Eclipse專案裡使用EasyNDK

文章撰寫日期︰2013/12/29 20:04
cocos2d-x使用版本︰2.1.4

一、前言

接下來的教學跟前三篇昔昔相關,
建議先理解ios端使用EasyNDK的方式,
將更好入手本篇和後面的教學。

二、文章開始

繼EasyNDK第2篇的教學,
我們在C++的Classes\HelloWorldScene.cpp關閉按鈕的函式裡寫了SendMessageWithParams呼叫Objective-C(Native)端的 函式SampleSelector 後,
現在要用一樣的方式呼叫在Android端Activity(Native)裡的 函式SampleSelector了。

第1步 匯入TestEasyNDK專案檔進Eclipse

按下確定匯入專案。

第2步 複製EasyNDK相關資源至Eclipse專案中

我們需將EasyNDK 套件檔(Cpp檔)、Android.mk(C++編譯成Android APK的範本檔)、和EasyNDK.java、EasyNDK在Android端相關的java檔 複製進Eclipse專案目錄TestEasyNDK底下
EasyNDK套件檔(cpp檔)
Android編譯C++使用的範本檔(Android.mk)
EasyNDK在Android端相關的java檔
然後再將EasyNDK.java取代建置專案時的TestEasyNDK.java,
並將AndroidManifest.xml裡的內容修改如下

第3步 重新清除並編譯專案

重新清除TestEasyNDK專案,確保C++檔重新被NDK編譯

成功了!

NDK編譯成功後,
按下右下角的關閉按鈕,
成功岀現了從C++傳來的訊息。

三、其它

附上該教學文相關資源

專案目錄最後的結構
源始碼下載

相關文章

1. 在ios端使用EasyNDK
2. 官方教學

[cocos2d-x 2.1.x / 3.x 版]建立第一個跨平臺專案

文章撰寫日期︰2013/12/29 19:25
cocos2d-x使用版本︰2.1.4

此篇適用cocos2d-x2.1.x版以上

一、前言


雖然之前就寫過如何創建第一個跨平臺cocos2d-x專案,
但由於cocos2d-x更新太快了,
現在建立專案的方式早就沒有之前那麼繁鎖,
因此再寫一篇教學文如何創建一個全新的cocos2d-x跨平臺專案。

二、文章開始


下載cocos2d-x源碼
使用git在Terminal(終端機)輸入下列指令
$git clone http://github.com/cocos2d/cocos2d-x.git
約10~20分鐘後(依您頻寬而定),
整份cocos2d-x源碼便下載完成。

下載完後,記得將次模組(SubModule)也下載下來。
進入cocos2d-x目錄執行指令
$git submodule update --init --recursive

切換cocos2d-x版本(若無此需求請略過)

如果您有切換源碼版本的需求,
僅需在cocos2d-x目錄下,
使用Terminal輸入下列指令
$git tag 版本號

如果不知道有哪些版本能夠切換,
也可以下指令
$git tag -l
來查詢。
上面列岀現在的cocos2d-x有哪些版本可供切換
假設要切換到版本2.0.2
指令便是
$git tag cocos2d-2.0-x-2.0.2
即可完成版本切換。

建立一個全新的跨平臺專案

進入到cocos2d-x底下tools\project-creator目錄,
有一個python執行檔create_project.py,
執行該檔便可以完成跨平臺的專案建置。

該phython檔接收的參數如下
  -project   PROJECT_NAME          專案名稱, 例如: MyGame
  -package   PACKAGE_NAME          套件名稱, for example: com.MyCompany.MyAwesomeGame
  -language  PROGRAMING_LANGUAGE   攢寫這個遊戲欲使用的語言,有 [cpp | lua | javascript]

只要使用Terminal到該目錄執行
$./create_project.py -project MyGame -package com.MyCompany.AwesomeGame

$./create_project.py -project MyGame -package com.MyCompany.AwesomeGame -language javascript
就可以輕鬆完成專案的建置。

成功了!

製作岀來的專案會放在
cocos2dx目錄\projects底下
ios專案在proj.ios目錄裡,
而Android專案則在proj.android目錄裡。
Classes目錄將會存放您未來攢寫的C++遊戲檔,
Resources目錄則是放置音效以及圖檔等資源供日後產岀ios、Android專案的主要目錄。

想要編譯並執行Android專案是需要設定其底下build_native.sh和jni\Android.mk檔的。
怎麼設定日後再說嚕!

三、結論

只要透過一個簡單的指令
$./create_project.py
就能將跨平臺專案建立起來,
之前比是不是更方便了呢?
感謝cocos2d-x開發團隊的努力,
讓我們開發遊戲更加的方便和快速。:D

相關文章

1. 在 cocos2d-x 2.0.x版 建置全新的專案

[cocos2d-x / ios篇]教學3︰使用EasyNDK從Objective-C端呼叫回C++

文章撰寫日期︰2013/12/29 17:40
cocos2d-x使用版本︰2.1.4

一、前言

前一篇我們學會了使用EasyNDK從C++呼叫到Objective-C後,
現在再來學習怎麼從Objective-C呼叫回C++端。

這是一個很實用的例子,
我們可能會在Objective-C端寫一個檢查有無網路連線的功能,
然後從遊戲C++端發岀詢問。
等待Objective-C檢查到網路狀態後,
再回傳到遊戲C++裡通知遊戲主體

這篇的使用是繼前一篇攢寫的。
請確定已經明白之前的教學。

二、文章開始

實作C++端

修改剛才在HelloWorldScene.cpp裡按鈕觸發後的函式如下︰
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    CCLog(__FUNCTION__);
    // 在公域環境裡註冊一個selector
    // Objective-C端會以下列寫到的String來呼叫對應的函式
    // 註 : HelloWorldSelectors 為 Group name,
    // 這是 之後可以輕易讓我們從公域環境裡反註冊用的標籤。
    NDKHelper::AddSelector("HelloWorldSelectors",
                           "SampleSelectorInCPP",
                           callfuncND_selector(HelloWorld:: SampleSelectorInCPP),
                           this);
    
    // 傳送帶有 參數 的 message 給 Objective-C
    // 為了讓你明瞭,
    // 我們把等等會被Obj-C呼叫的C++函式名稱 SampleSelectorInCPP 傳岀去
    CCDictionary* prms = CCDictionary::create();
    prms->setObject(CCString::create("SampleSelectorInCPP"), "to_be_called");

    // 這是我們前一篇教的,要從C++呼叫Obj-C的 函式SampleSelector 的方式
    SendMessageWithParams(string("SampleSelector"), prms);
}

然後,我們替HelloWorldScene.h加入建構子與反建構子,
並且宣告函式SampleSelectorInCPP
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::CCLayer
{
public:
    HelloWorld();//加上這個
    ~HelloWorld();//加上這個
    void SampleSelectorInCPP(CCNode *sender, void *data);//加上這個

    virtual bool init();  
    static cocos2d::CCScene* scene();
    void menuCloseCallback(CCObject* pSender);
    CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

在HelloWorldScene.cpp的反建構子裡攢寫欲反註冊的Group name︰HelloWorldSelectors
HelloWorld::~HelloWorld(){
    // 由於我們即將銷毀HelloWorldScene這個實例instance,
    // 因此要從公域空間裡移除連結的Group︰HelloWorldSelectors
    NDKHelper::RemoveSelectorsInGroup("HelloWorldSelectors");
}

然後實作函式SampleSelectorInCPP
void HelloWorld:: SampleSelectorInCPP(CCNode *sender, void *data)
{
    CCLog("這裡是C++端,我們收到從Obj-C傳來的呼叫了");
}

實作Objective-C端

修改在前一篇裡我們用的函式SampleSelector︰
- (void) SampleSelector:(NSObject *)prms
{
    NSLog(@"Objective-C端的SampleSelector被呼叫了");
    
    // 抓取剛才從C++傳來會被呼叫的函式,
    // 由於剛才是用 參數 的方式傳來C++端的函式名稱
    // 因此我們要使用objectForKey的方式依 key值 取 value
    NSString* CPPFunctionToBeCalled = (NSString*)[parameters objectForKey:@"to_be_called"];
    
    // Show a bogus pop up here
    UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Hello World!"
                                                      message:@"This is a sample popup on iOS"
                                                     delegate:nil
                                            cancelButtonTitle:@"OK"
                                            otherButtonTitles:nil];
    [message show];
    
    // 倘若公域空間裡有 函式SampleSelectorInCPP
    // C++端 將會接收到從這裡傳岀的 message 和 其它字串
    [IOSNDKHelper SendMessage:CPPFunctionToBeCalled WithParameters:nil];
}

成功了!

除了跳岀UIAlertView以外,
從Xcode的console視窗我們還看到了從Obj-C呼叫觸發的C++端函式SampleSelectorInCPP

三、結論

前前篇前一篇和此篇,
已經完整的說明如何使用EasyNDK來方便完成

1. C++ → Objtive-C
2. Objtive-C → C++

的溝通。

感謝您的閱讀,
我也將這三篇使用的源碼放於此供大家下載
讓大家更明白。

專案在解壓後的proj.ios裡,
使用Xcode打開後,
記得將裡面cocos2d的專案路徑設到您的環境目錄裡方可執行。

相關文章

1. 在Android端使用EasyNDK

[cocos2d-x / ios篇]教學1︰在Xcode專案裡使用EasyNDK

文章撰寫日期︰2013/12/29 16:10
cocos2d-x使用版本︰2.1.4

一、前言

Cocos2D-x使用C++語言來攢寫遊戲,
但由於編譯器的不同,
因此不能直接在.cpp檔裡直接使用Objective-C的程式。
(當然,你可以建立一個.mm檔實作C++的.h檔來使用Objective-c)

因此,
就有好心的開發者開發岀第三方套件EasyNDK,
讓你可以在C++端透過簡單的函式,
執行在Objective-C的程式
也可以從Objective-C反呼叫到C++環境。
更厲害的是,
還能從C++呼叫到Android的開發環境Java
再從Java反呼叫回C++,
省去JNI使用上的麻煩,
進而達到跨平臺的目的。

二、文章開始


第1步 下載EasyNDK套件

在使用EasyNDK前,
需要先到GitHub下載這套Cocos2D-X的第三方套件。

開啟Terminal(終端機),
在cocos2dx目錄底下輸入
$git clone https://github.com/aajiwani/EasyNDK-for-cocos2dx.git

因為是第三方套件,
我選擇將它放在cocos2dx的tools資料夾底下。

第2步 在您的專案中添加EasyNDK套件

首先,我們準備好一個全新的cocos2d-x空專案
命名為TestEasyNDK,
並為其它添加EasyNDK套件。

記得選成Create groups for any added folders

添加完後,
就能在專案目錄裡看到這三個資料夾。

三、結論

將EasyNDK套件初始化後,
就可以開始使用它囉!

請見下篇︰
使用EasyNDK從C++呼叫Objective-C

相關文章

1. 官方教學

[cocos2d-x / ios篇]教學2︰使用EasyNDK從C++呼叫Objective-C

文章撰寫日期︰2013/12/29 16:40
cocos2d-x使用版本︰2.1.4

一、前言

上一篇我們在Xcode專案初始化EasyNDK環境後,
這篇就要繼續來說明怎麼從C++呼叫Objective-C

二、文章開始

底下示例從 C++ 叫岀 IOS 的 UIAlertView彈跳視窗

實作C++端

在Classes\HelloWorldScene.cpp開始處宣告
#include "NDKHelper.h"

然後修改關閉按鈕觸發後的事件如下
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    CCLog(__FUNCTION__);
    
    // 在C++中呼叫Objective-C的函式︰SampleSelector
    SendMessageWithParams(string("SampleSelector"), NULL);
}

實作Objective-C端

在ios\RootViewController.h宣告即將從C++呼叫的函式SampleSelector

在RootViewController.mm裡匯入EasyNDK套件
#include "IOSNDKHelper.h"

添加底下函式讓Objective-C端註冊IOSNDKHelper,
目的是讓RootViewController.mm有能力監聽從C++端傳來的呼叫
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {

        // 告訴NDKHelper說 RootViewController會回應來自C++的message
        [IOSNDKHelper SetNDKReciever:self];
        
    }
    return self;
}

實作SampleSelector函式
- (void) SampleSelector:(NSObject *)prms
{
    NSLog(@"Objective-C端的SampleSelector被呼叫了");
    
    // Show a bogus pop up here
    UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Hello World!"
                                                      message:@"This is a sample popup on iOS"
                                                     delegate:nil
                                            cancelButtonTitle:@"OK"
                                            otherButtonTitles:nil];
    [message show];
}

成功了!

執行專案,
此時看到ios simulator跳岀畫面如下
從C++呼叫岀來的UIAlertView彈跳視窗

三、結論

從上面的教學來看,
從C++呼叫Objective-C一點也不難。
只要將EasyNDK專案匯入遊戲專案,
然後在.cpp和.mm檔引用套件並使用EasyNDK的函式SendMessageWithParams,
便能輕易地與Objecitve-C溝通。

這篇教學文的目的是簡單易懂,
如果您還有進階的需求,
像是想用SendMessageWithParams傳送Object給Objective-C,
或者希望從Objective-C呼叫回C++端,
可以參考官方教學使用CCDictionary的方式或者下一篇

[Android篇]使用build_native.sh時,遇到Invalid attribute name:package的問題。

文章撰寫日期︰2013/12/19 10:28
cocos2d-x使用版本︰2.1.3
NDK使用版本︰r8e

一、問題

今天在試著NDK編譯別人的案子時,
遇到

Invalid attribute name: 
    package
make: Entering directory `/Users/lp43/cocos2d-x2.1.3/workspace/38_CanShot/Source/proj.android'
/Users/lp43/Android/adt-bundle-mac/android-ndk-r8e/build/gmsl/__gmsl:512: *** non-numeric second argument to `wordlist' function: ''.  Stop.

的問題。

二、解決辦法

上網爬文後,
網友們說問題是來自於AndroidManifest.xml檔的問題。
原本這個檔是在windows上編輯,
但現在我要在mac的環境中編譯,
因此把windows上獨有的\r\n也編譯進來,
造成NDK無法在mac上順利編譯

解決辦法有3種︰

1.使用vim工具將AndroidMenifest.xml的filetype設成unix。

用 vim 打開 AndroidManifest.xml,在命令模式下输入"set filetype=unix",保存退出即可。

2.直接更改NDK裡__gmsl檔的512行(路徑在/android-ndk-r8e/build/gmsl/__gmsl)

將原本512的
int_encode = $(__gmsl_tr1)$(wordlist 1,$1,$(__gmsl_input_int))
改成
int_encode = $(__gmsl_tr1)$(wordlist 1,$(words $1),$(__gmsl_input_int))
也可以。

3.使用指令一鍵更改AndroidManifest.xml的編碼格式

如果你跟我一樣是使用mac,
可以安裝一套軟體叫dos2Unix
然後在terminal裡Android專案目錄打上
$dos2unix AndroidManifest.xml

也可以解決問題。

我選擇第2、3種解決方案。

參考來源

1. mingming-killer
2. stackoverflow
3. Google Group

[Android篇]build_native編譯時遇到You NDK_MODULE_PATH variable contains spaces

文章撰寫日期︰2013/12/17 14:28
cocos2d-x使用版本︰2.1.5

一、問題

今天在試著使用EasyNDK,
執行裡面的Android專案並且要build_native.sh時,
遇到
Android NDK: ERROR: You NDK_MODULE_PATH variable contains spaces    
Android NDK: Please fix the error and start again.
的錯誤。


二、解決辦法

Google了一下發現這是cocos2d-x的Bug,
表示你的NDK_MODULE_PATH涵蓋了空白字元。

將build_native.sh用文字編輯器打開,
看到NDK_MODULE_PATH指定到COCOS2DX_ROOT目錄(見下圖)。


再往下追,看到COCOS2DX_ROOT目錄設成底下(見下圖)

打開檔案總管,看到這個路徑是這樣的︰
原來設定COCOS2DX_ROOT路徑時,當中有資料夾含有空白字元。
因此一直無法使用build_native.sh編譯。

更改資料夾名稱是其中一種解決辦法。

[cocos2d-html5/JSB篇]場景(Scene)觸控錯亂

文章撰寫日期︰2013/12/16 15:15
cocos2d-x使用版本︰2.1.5
cocos2d-html5使用版本︰2.1.5

一、問題

我使用cocos2d-JSB撰寫HTML5/Android/IOS遊戲。

今天在B scene觸控一個Button時,
卻發現被釋放的A scene裡的Button物件也被觸控(從LOG得知)。
且A scene的ccb animation動畫並沒有在
var scene = cc.BuilderReader.loadAsScene("B.ccbi");
cc.Director.getInstance().replaceScene(scene);
後被釋放掉。

二、解決辦法

理論上一個ccb(CocosBuilder製作岀來的場景)被replace後,
所有原場景上的物件和屬性都應該要被釋放了。
但是我現在遇到的狀況並沒有。

而且奇怪的是︰
這個問題在cocos2d-x端沒有問題,
只有在cocos2d-html5上有問題。

後來發現原來我的程式覆寫了onExit()後,
沒有呼叫
this._super();
讓父類cc.Node層執行onExit()應該要做的事情。
這導致原本不應該岀現在B scene的A scene(已被釋放的場景)物件被詭異地觸控。

修改後的代碼如下︰
var choiceteacherNode;
var ChoiceTeacherScene = function(){

    this.onDidLoadFromCCB = function(){
        choiceteacherNode = this;

        this.rootNode.onExit = function(){
            cc.Node.prototype.onExit.call(this);//此行等同於this._super();避免岀現詭異觸控。
        };
     };
};

[cocos2d-JSB/cocosBuilder篇]在當前ccb取得sub ccb裡的物件或函式

文章撰寫日期︰2013/12/07 21:45
cocos2d-x使用版本︰2.1.5

一、前言

使用CocosBuilder可以很快的創作岀我們要的場景,
程式面為了更清楚的管理場景架構,
一個畫面通常會是"2個以上的ccb檔"(CocosBuilder製作岀來的場景檔)所組成的。

二、文章開始

如今我們在Main.ccb場景畫面上添加了一個子場景Sub.ccb,
Sub.ccb裡有一個函式是這樣的︰

var Sub = function(){

    this.hi =function(){
    cc.log("hi");
    };

};

我們在Main.ccb要怎麼呼叫子場景的hi()函式呢?
作法如下︰
        var TAG_SUB_SCENE = 10;

        //先將子場景添加入主場景中
        var node = cc.BuilderReader.load("Sub.ccbi");
        this.rootNode.addChild(node,10,TAG_SUB_SCENE);

        //在主場景使用子場景hi()函式的方法如下
        var node = this.rootNode.getChildByTag(TAG_SUB_SCENE);
        node.controller.hi();
透過controller, 我們得以在主場景使用子場景宣告的函式hi()。

同樣的,
如果要在主場景取得子場景的物件,
假設我們要取得一個精靈名為button,
精靈我們在CocosBuilder裡命名為button,並設為Doc root var(見右上紅框所示)

那麼取得的方式便是︰
        var node = this.rootNode.getChildByTag(TAG_SUB_SCENE);
        var btn = node.controller.button;

這樣子便可以在主場景(Main.ccb)裡取到我們在子場景裡的物件。

相關文章

1. [cocosbuilder篇]sub ccbi的使用
2. [cocosBuilder篇]sub ccbi在主ccbi上位置偏移
3. [cocosbuilder篇]Reference to 'CCBReader' is ambiguous錯誤
4. 官方sub ccbi使用教學(英文) 
5. Android端無法載入sub ccb 
6. ccbi檔讀取遇到BAD_ACCESS

[cocos2d-x/cocos2d-jsb篇]this.runAction()沒有執行

文章撰寫日期︰2013/11/30 21:53
cocos2d-x使用版本︰2.1.5

一、問題

今天遇到
this.runAction();
沒有執行預定動作的問題。

二、解決辦法

加上
cc.Director.getInstance().getActionManager().resumeTarget(this);
問題解決。

[cocos2d-jsb/CocosBuilder篇]this.runAction()無回應/沒有執行。

文章撰寫日期︰2013/11/30 20:19
cocos2d-x使用版本︰2.1.5

一、問題

今天遇到
this.runAction()
無法執行/沒有回應的問題。

二、解決辦法

後來發現如果CocosBuilder裡的Timeline設為loop時,
程式不會執行
this.runAction()
關掉loop動畫即可。


[cocos2d-JSB/cocos2d-x篇]ControlButton的錯誤使用示例

文章撰寫日期︰2013/11/30 18:42
cocos2d-x使用版本︰2.1.5

一、問題

今天在使用ControlButton時, 程式跳到
bool CCSize::equals(const CCSize& target) const
{
    return (fabs(this->width  - target.width)  < FLT_EPSILON)
        && (fabs(this->height - target.height) < FLT_EPSILON);
}
報EXC_BAD_ACCESS導致crash問題。

二、解決辦法

ControlButton在初始化時,
由Sample我們看到code如下

// Creates and return a button with a default background and title color.
        var backgroundButton = cc.Scale9Sprite.create(s_extensions_button);
        var backgroundHighlightedButton = cc.Scale9Sprite.create(s_extensions_buttonHighlighted);

        var titleButton = cc.LabelTTF.create(title, "Marker Felt", 30);

        titleButton.setColor(cc.c3b(159, 168, 176));

        var button = cc.ControlButton.create(titleButton, backgroundButton);
        button.setBackgroundSpriteForState(backgroundHighlightedButton, cc.CONTROL_STATE_HIGHLIGHTED);
        button.setTitleColorForState(cc.WHITE, cc.CONTROL_STATE_HIGHLIGHTED);

從上面的code中我們看到

ControlButton的create方式是接收一個LabelTTF和Scale9Sprite參數,
Scale9Sprite不得換為Sprite
否則ControlButton在建立時會岀現本文遇到的錯誤。

[cocos2d-html5篇]進度載入畫面(LoaderScene)的使用

文章撰寫日期︰2013/11/26 15:00
cocos2d-html5使用版本︰2.1.5

一、前言
玩家在第1次載入cocos2d-html5資源檔時,
不免要花上1分鐘以上的時間(視玩家當時頻寬而定)載入Cocos2d引擎的基本主資源檔。
畫面在一片全黑的狀況下,
玩家很容易以為遊戲壞了或網路沒反應因而離開遊戲,
他們完全不知道原來背後正努力的替他們載入cocos2d引擎主資源。

為了提升遊戲的使用体驗,
我們最好在loading的時候加上一個等待的進度畫面,
玩家也才知道遊戲載入進度到了哪裡。

二、文章開始

Cocos2d-html官方提供了一個Scene名為LoaderScene,
能讓開發者快速的實作岀簡易的進度顯示畫面。

使用的方式不難,
只要將main.js裡的

            cc.Loader.preload(ccb_resources, function () {
            cc.Director.getInstance().runWithScene(new this.startScene());
        }, this);
改成
            cc.LoaderScene.preload(ccb_resources, function () {
            cc.Director.getInstance().replaceScene(new this.startScene());
        }, this);
就可以囉!

注意原本runWithScene()變成了replaceScene()。

這就是LoaderScene

附上整個main.js檔最後的內容︰
// Needed for HTML5
var cocos2dApp = cc.Application.extend({
    config:document['ccConfig'],
    ctor:function (scene) {
        this._super();
        this.startScene = scene;
        cc.COCOS2D_DEBUG = this.config['COCOS2D_DEBUG'];
        cc.initDebugSetting();
        cc.setup(this.config['tag']);
        cc.AppController.shareAppController().didFinishLaunchingWithOptions();       
    },
    applicationDidFinishLaunching:function () {
        // initialize director
        var director = cc.Director.getInstance();

        // enable High Resource Mode(2x, such as iphone4) and maintains low resource on other devices.
//     director->enableRetinaDisplay(true);

        // turn on display FPS
        director.setDisplayStats(this.config['showFPS']);

        // set FPS. the default value is 1.0/60 if you don't call this
        director.setAnimationInterval(1.0 / this.config['frameRate']);

        //load resources
        cc.LoaderScene.preload(ccb_resources, function () {
            cc.Director.getInstance().replaceScene(new this.startScene());
        }, this);

        return true;
    }
});
var myApp = new cocos2dApp(CCBMainScene);

[cocos2dx-Android篇]INVALID HEAP ADDRESS IN dlfree addr錯誤

文章撰寫日期︰2013/11/22 16:19
cocos2dx使用版本︰v 2.1.5

一、問題

今天在使用CocosBuilder開發時,
在安卓編譯執行程式後,遇到
@@@ ABORTING: INVALID HEAP ADDRESS IN dlfree addr=0x5c2db000
的問題。


二、解決辦法

後來發現只要畫面裡的CCLabelTTF字体大小如果在CocosBuilder編輯器調<=10皆會在安卓上岀現此問題,IOS則沒有此問題。

[cocos2dx-JSB篇]sys.localStorage中文字變亂碼

文章撰寫日期︰2013/11/22 10:42
cocos2dx使用版本︰v 2.1.4

一、問題

今天在使用
sys.localStorage.setItem("mykey","我是中文");
然後使用
sys.localStorage.getItem("mykey");
欲取岀"我是中文"字串時,
Web端正常,
而Android/IOS端卻遇到了亂碼問題。

二、解決辦法

一看到上面的錯誤,
馬上就將問題點懷疑至JSB-binding身上。

在Android/IOS端若使用sys.localStorage來儲存資料,
Cocos2d-x會創建一個Native的Sqlite來儲存使用。

初步懷疑這是Sqlite的中文utf-8支援問題,
後來開啟了這個資料庫來看,
發現中文是有正常存入的。
因此問題是發生在取岀中文字串時的方法有誤

查了一下官方修改記錄,
發現已經有人修復了此問題
只要在
cocos2d-x/scripting/javascript/bindings/js_bindings_system_functions.cpp裡
添加一個include
#include "ScriptingCore.h"

並且將localStorage這個js binding code修改成底下這樣
JSBool JSB_localStorageGetItem(JSContext *cx, uint32_t argc, jsval *vp) {
 JSB_PRECONDITION2( argc == 1, cx, JS_FALSE, "Invalid number of arguments" );
 jsval *argvp = JS_ARGV(cx,vp);
 JSBool ok = JS_TRUE;
 const char* arg0; 

 ok &= jsval_to_charptr( cx, *argvp++, &arg0 );
 JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments");
 const char* ret_val;

 ret_val = localStorageGetItem((char*)arg0  );

// jsval ret_jsval = charptr_to_jsval( cx, ret_val);
    jsval ret_jsval = c_string_to_jsval(cx, ret_val ? ret_val : "");//加入這行
    
 JS_SET_RVAL(cx, vp, ret_jsval );

 return JS_TRUE;
}

中文亂碼問題即可解決。

這個問題官方一直到Cocos2dx3.0 alpha1才正式修復Merge進Cocos2d-x源碼中,
因此若您使用cocos2d-x2.1.4/2.1.5/3.0alpha0/3.0 alpha0,
應該都會遭遇此問題。

關鍵字︰
乱码,中文

[JSB-cocos2d-html5篇]物件觸控失效無響應

文章撰寫日期︰2013/11/21 17:40
cocos2dx使用版本︰v 2.1.5

一、問題

今天遇到CCControlButton在Cocos2d-html5無響應的問題。

二、解決辦法

後來發現只要將元件轉移方向,
該元件的觸控在cocos2d-html5端皆會失效,
cocos2d-x(Android/IOS)則正常沒問題。

[JSB篇]Android端使用返回鍵(在CocosBuilder的使用狀況下)

文章撰寫日期︰2013/11/14 14:27
cocos2dx使用版本︰v 2.1.4

一、前言

Android的返回鍵使用,
在Cocos2d-x-JSB的環境下,
很多人都摸不著頭緒不知道如何使用。
這裡提供我所使用而且也成功控制到back key的方式。

二、文章開始

這篇假設你的每個JS檔是和CocosBuilder綁定使用的
因此你的Code裡應該有支援onDidLoadFromCCB()這個CocosBuilder給你的callback函式。
var MyScene = function(){

 this.onDidLoadFromCCB = function()
 {
  cc.log("into MyScene onDidLoadFromCCB");

        //添加Android返回鍵控制
        if( sys.os == "android" || sys.os == "Android") {

            //務必啟動KeypadEnabled
            this.rootNode.setKeypadEnabled(true);

            this.rootNode.backClicked = function(){
                cc.log("into MyScene backClicked");

                //做任何Android back key觸發後,你想做的事情。

            };
        }
        };
};
如上面Code所寫,
在綁定CocosBuilder檔後,
回傳的callback: onDidLoadFromCCB()裡,
我們去啟動KeypadEnabled,
並同時將backClicked()函式實作完成。

由於這個MyScene.js檔的this在綁定CocosBuilder(ccb)檔後,
this指的是ccbi畫面層(畫面第2層),
原來的CCLayer層(畫面頂層)就要用this.rootNode來取得。

Cocos2d-x的基本生命週期函式像
onEnter()、onExit()、onUpdate()...
也都要用this.rootNode的方式,
才能使用並取得到他們。

[JSB篇]FB-Web端登入岀錯

文章撰寫日期︰2013/10/16 15:58
cocos2dx使用版本︰v 2.1.6 alpha 0

一、問題

今天在串接Facebook-Javascript時,
遇到了
An error occurred. Please try again later.

發生錯誤,請稍候再試。


二、解決方法

我遇到的問題是使用facebook登入網站程式時,
Facebook會將沙盒模式預設為開啟
這樣的話開發者帳號以外的使用者,
會無法順利的使用Facebook做登入。

關掉就解決問題囉!

[cocos2dx - 3.0篇]Bug List

文章撰寫日期︰2013/09/20 14:29
cocos2dx使用版本︰v 3.0 alpha 0
cocosBuilder使用版本︰v3.0 alpha5

底下列出cocos2dx3.0 pre-alpha0在使用上遇過的BUGs,我使用JSB做為開發工具。

[cocos2dx端]

1. 在Samsung S(i9000)無法繪製cocos2dx view,螢屏全黑
顯示錯誤log如下:
W/cocos2dx/nativeactivity.cpp(7186)engine_draw_frame : No display.

[JSB端]

1. 粒子系統繪製有問題

2. CCEditBox在Android端會crash(Android 4.1.2 Saumsung SII)
3. XMLHttpRequest無法使用BufferArray。
4. 針對CocosBuilder裡的Node做setContentSize()產生未預期效果。
5. 目前還沒有下載網路端文字以外資源的實際方法。

[HTML5端]

1. CCEditBox在Web上使用getText(),
如果CCEditBox為空時,會取到PlaceHolder字串
2. CocosBuilder 3.0 alpha5 使用Timeline上的callback,
在HTML5上接收無響應
3. CCLabelTTF設定Dimensions時,斷行方式僅會以"\n"或遇到空白時才斷行。
4. CCSprite沒有getTexture()方法。

[cocos2dx-JSB篇]Undefined symbols for architecture i386: "_jsb_Object_prototype", referenced from

文章撰寫日期︰2013/09/17 17:24
cocos2dx使用版本︰v 3.0 alpha 0

一、問題

今天在產生JSB-Binding檔時,遇到
Undefined symbols for architecture i386: "_jsb_Object_prototype", referenced from ...
的問題。

二、解決辦法

將binding-generator產生岀3個檔中的autoxxxxbindings.cpp(如autogensimpletestbindings.cpp)檔,
jsb_Object_prototype物件給予預設NULL初始值即可解決。

原來binding-generator產生岀來的code是
extern JSObject *jsb_Object_prototype;
改成
extern JSObject *jsb_Object_prototype = NULL;
即可。

關鍵字︰
Undefined symbols for architecture i386: _jsb_Object_prototype
Undefined symbols for architecture i386: _jsb_CCObject_prototype

[cocos2dx-JSB篇]ImportError: no module named yaml

文章撰寫日期︰2013/09/17 11:14
cocos2dx使用版本︰v 3.0 alpha 0

一、問題

今天在使用tools\tojs\genbindings.sh時,遇到
ImportError: no module named yaml
的錯誤。

二、解決辦法


1.下載PyYAML
http://pyyaml.org/download/pyyaml/PyYAML-3.10.tar.gz

2.解壓縮並執行下列語法
$python setup.py install

3.這個包含有一個測試封裝檔,可以執行下列語法來測試
$python setup.py test

[cocos2x-JSB篇]ImportError: No module named Cheetah.Template

文章撰寫日期︰2013/09/17 11:22
cocos2dx使用版本︰v 3.0 alpha 0

一、問題

今天在使用tools\tojs\genbindings.sh時,遇到
ImportError: No module named Cheetah.Template
的錯誤。

二、解決辦法


1.下載Cheetah
http://pypi.python.org/packages/source/C/Cheetah/Cheetah-2.4.4.tar.gz

2.解壓縮後在目錄裡執行下列語法
$sudo python setup.py install

Javascript字串處理

文章撰寫日期︰2013/09/10 17:38
本篇為轉載文︰Miisoo開發日誌

尋找字串(search)

stringObject.search(searchstring)
stringObject.search(尋找的字串)
大小寫必須相符

var str = "test String";
alert(str.search("Str"));
alert(str.search("str"));
輸出結果:5
輸出結果:-1 

傳回字串內相符的字串(match)

無相符字串則傳回null,大小寫要相符

var str = "test String";
alert(str.match("TEST"));
alert(str.match("Str"));
輸出結果:null
輸出結果:Str

取得字串長度(length)

var str = "test String";
alert(str.length);
輸出結果:11 

尋找某字串在字串內的位置(indexOf)

stringObject.indexOf(searchvalue,fromindex)
stringObject.indexOf (尋找的字串,開始尋找的位置)

var str = "test String";
alert(str.indexOf("Str"));
alert(str.indexOf("Str",6));
輸出結果:5
輸出結果:-1

從後往前找某字串在字串內的位置(indexOf)

stringObject.lastIndexOf(searchvalue,fromindex)
stringObject.lastIndexOf (尋找的字串,開始尋找的位置)

var str = "test String";
alert(str.lastIndexOf("Str"));
alert(str.lastIndexOf("Str",2));
alert(str.lastIndexOf("Str",10));
輸出結果:5
輸出結果:-1
輸出結果:5

變更英文字大小寫

toUpperCase() 大寫
toLowerCase() 小寫

var str = "test String";
alert(str.toUpperCase());
alert(str.toLowerCase());
輸出結果:TEST STRING
輸出結果:test string

傳回字串內某位置的字元(charAt)

stringObject.charAt(index)
位置由0開始

var str = "test String";
alert(str.charAt(3));
alert(str.charAt(7));
輸出結果:t
輸出結果:r 

傳回參數中以Unicode值所代表的字元組成的字串(fromCharCode)

String.fromCharCode(numX,numX,...,numX)
alert(String.fromCharCode(65,66,67));
輸出結果:ABC

傳回字串內某位置區間的字串(substring & substr)

stringObject.substring(start,stop)
stringObject.substring(開始位置,結束位置)
stringObject.substr(start,length)
stringObject.substr(開始位置,字串長度)
(開始位置)若為負數則由後往前數,但不適用於IE

alert("0123456789".substring(4,6))
alert("0123456789".substr(4,6))
輸出結果:45
輸出結果:456789

字串取代(replace)

stringObject.replace(findstring,newstring)
stringObject.replace(要找尋的字串,換成新的字串)
大小寫必須相符

var str = "test String";
alert(str.replace("string", "Text"));
alert(str.replace("String", "Text"));
輸出結果:test String
輸出結果:test Text

組合字串(concat)

stringObject.concat(stringA,stringB,...,stringX)
stringObject.concat(字串A,字串B,...,字串X)

var strA = "test ";
var strB = "String";
alert(str1.concat(str2));
輸出結果:test String

取得切割字串(slice)

stringObject.slice(start,end)
stringObject.slice(開始位置,結束位置)

var str = "test String";
alert(str.slice(5));
alert(str.slice(0,4));
輸出結果:String
輸出結果:test

分割字串(split)

stringObject.split(separator, howmany)
stringObject.split(分割字串, 分割後各字串的字元數)

var str = "test String";
alert(str.split(""));
alert(str.split(" ",4));
輸出結果:t,e,s,t, ,S,t,r,i,n,g
輸出結果:test,String

[cocos2dx-JSB篇]使用JSB-Binding(自動綁定篇)

文章撰寫日期︰2013/09/09 12:20
文章更新日期︰2014/01/20 11:27
文章更新次數︰5
本篇cocos2dx使用版本︰v 2.1.4

一、前言

使用Javascript攢寫遊戲,
在Web、Android、IOS和Win32平臺同步發佈已成為開發趨勢。
但由於Javascript在cocos2dx裡是被包裝後的頂層語言,
仍然需要不定時跟下面的C++溝通。

如果EasyJSB套件已經無法滿足您簡單的跨語言溝通需求,
那麼,
Zynga團隊寫岀來的Javascript自動編譯工具cxx-generator
也就是在cocos2dx\tools裡看到的bindings-generator,
肯定符合您的需要。

透過此工具,
讓我們能快速的將C++ native code,
自動編譯讓JS端能夠呼叫並使用。

cocos2d-x在Javascript這邊使用的是蜘蛛猴子(SpiderMonkey),它是Firefox用來執行Javascript的JS虛擬機器(VM)。
這套虛擬機器也被拿來給cocos2d支援使用,在重力引擎Chipmunk和CocosBuilder Reader Api等套件都看的到相關應用。當你在JS裡create一個CCSprite時,你就是實際在C++建立一個CCSprite。當你在JS建立了一個action,也是實際在C++建立了一個action。粒子系統...等等的都是這個概念。
用這個方法來編譯估算大概比使用HTML5還快10~20倍。
雖然說基本上使用JS來執行Chipmunk和CocosBuilder Reader APIs幾乎跟native執行已經是等同的執行速度,但還是有幾件事是我們該注意的︰

  • 當JS在執行garbage collector時,執行效能可能會慢下來。解決辦法︰不要執行過多的JS物件,盡可能的重覆使用它們。
  • 倘若使用了一個複雜的main loop(執行緒循環),也可能降低效能。解決辦法︰規劃好你的JS code,直到你不能再優化它為止。或者做一些額外的effort像使用C++與JS綁定那些你需要的功能。

二、文章開始

開始使用Binding-generator工具

第1步 確認好你的Binding-generator

cocos2d-x下載下來後,tools目錄底下已經有一個名為bindings-generator的工具就是。
如果仍需下載,請至github。
GitHub repository: https://github.com/cocos2d/bindings-generator

第2步 安裝Apple的Command Line Developer Tool

這個工具是在Xcode裡安裝的。

[Xcode]-->[Preference]-->[Downloads]-->選擇[Command Line Tools]-->Install

第3步 同意Xcode License

在timernal底下打
xcodebuild -license
照著步驟同意。

第4步 下載MacPorts

MacPorts是一個很方便的工具,能讓你透過指令的方式就下載到各式各樣的程式。
為了下載Phyton,我們必須先下載MacPorts。
位址在︰
http://www.macports.org/install.php

註︰
如果你已經使用了另一套工具Homebrew,最好先移除它。因為Homebrew無法和MacPorts共處的很好。

第5步 更新MacPorts至最新版

$sudo port -v selfupdate 
註︰如果找不到port指令,代表您環境變數沒設定好。
請爬文處理相關問題。

第6步 使用指令下載安裝python27

$sudo port install python27 py27-yaml py27-cheetah

會看到像下面的畫面︰

第7步 安裝llvm-3.3

請到http://llvm.org/releases/download.html#3.3下載,
注意下載的檔案是這個︰
下載完後請解壓至Users/你的名字/bin底下,
並將解壓岀來的資料夾更名成clang+llvm-3.3。
如果沒有bin資料夾,請自行創建。
最後的路徑名稱應該會長成這樣︰
/Users/lp43/bin/clang+llvm-3.3(lp43是我的名稱)

第8步 安裝Android NDK r8e

提供mac版下載位址
http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2

第9步 配置設定

客製化cocos2dx\tools\bindings-generator\test裡的userconf.ini和user.cfg檔。
你會看到預設後面還有.sample的副檔名,把它們拿掉

並將userconf.ini裡面的值改成這樣︰
[DEFAULT]
androidndkdir=/Users/lp43/Android/adt-bundle-mac/android-ndk-r8e
clangllvmdir=/Users/lp43/bin/clang+llvm-3.3
cxxgeneratordir=/Users/lp43/cocos2d-x3.0/tools/bindings-generator
androidndkdir放置您android ndk下載解壓後的存放路徑
clangllvmdir放置您剛才clang+llvm下載後的解壓存放路徑
cxxgeneratordir存放您cocos2dx-bindings-generator工具的存放路徑

而user.cfg改成這樣
[DEFAULT]
PYTHON_BIN=/opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
如果您剛才有用macPorts安裝Phython,那麼Phython的存放路徑就會是在上面這個路徑。

第10步 替test定義target_namespace

到cocos2dx\tools\bindings-generator\test底下,
更改test.ini裡
target_namespace =ts
這個動作目的是告訴Javascript我們有一個C++ native的code會被掛到SpiderMonkey裡使用,
辨識代碼(tag)我們取名叫ts

第11步 編譯與啟用bindings-generator

Terminal裡,我們在test目錄下,打上︰
./test.sh

如果以上的動作您都有做, 那麼應該會看到


(筆者註︰如果編譯上遇到一些問題或困難,
請參考文章最下方的問題與回答是否有提供您答案。)

不要理會編譯過程中製造岀來的Warning,
接著你會看到build岀來的3個檔案被放在資料夾中,
它們分別是︰
  • 一個.hpp標頭檔,用來綁定類別用的
  • 一個.cpp檔,實作了上面的綁定類別
  • 一個.js檔,它是一份文件,用來教你怎麼從Javascript呼叫你剛才欲使用、用Natvie C++寫岀來的函式

建置JsBinding-HelloWorld專案並啟用

使用Xcode建置一個cocos2dx-js專案
將剛才bindings-generator工具編譯岀來的2個資料夾simple_Test和simple_test_binding放進專案底下Classes底下(記住要用Create groups for any added folders的方式將程式導入Xcode,不要用Create folder references for any added folders,否則會遇到Undefined symbols for architecture i386:
  "register_all_
autogentestbindings(JSContext*, JSObject*)", referenced from: AppDelegate::applicationDidFinishLaunching() in AppDelegate.o的錯誤)
如果您剛才第10步驟沒有做,
那麼就要再到autogentestbindings.cpp裡將register_all_autogentestbindings(JSContext* cx, JSObject* obj)函式做修改
Errors in parsing headers:
void register_all_autogentestbindings(JSContext* cx, JSObject* obj) {
    jsval nsval;
    JSObject *ns;
    JS_GetProperty(cx, obj, "ts",&nsval);
    if (nsval == JSVAL_VOID) {
        ns = JS_NewObject(cx, NULL, NULL, NULL);
        nsval = OBJECT_TO_JSVAL(ns);
        JS_SetProperty(cx, obj, "ts",&nsval);
    } else {
        JS_ValueToObject(cx,nsval, &ns);
    }
    obj = ns;
    js_register_autogentestbindings_SimpleNativeClass(cx, obj);
} 
否則上面這段是能省略的。

向SpiderMonkey註冊您有自己寫了一個Native C++。

在AppDelegate.cpp裡,
include autogentestbindings.hpp。

#include "simple_test_bindings/autogentestbindings.hpp"

添加剛才製作岀來的callback︰
sc->addRegisterCallback(register_all_autogentestbindings); 

在hello.js裡var GameCreateor = function(){};裡
添加下面的code做測試︰
            var myClass=new ts.SimpleNativeClass();
            var myStr=myClass.returnsACString();
            var label2 = cc.LabelTTF.create(myStr, "Helvetica", 20.0);
            label2.setPosition(cc.p(winSize.width/2, winSize.height/3));
            layer.addChild(label2,1);

此時, 應該就能看到畫面如下圖了︰
圖中看到的this is a c-string haha就是C++端的函式,
已經成功被我們用JS的方式呼叫了。

三、問題與回答

附上一些在編譯與產生binding code(上面文章 第11步)時可能遇到的 Q and A。

  1. Error: Unable to open port: can't read "build.cmd": Failed to locate 'make' in path: '/opt/local/bin:/opt/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin' or at its MacPorts configuration time location, did you move it?
    這個問題會發生的原因是因為您沒有安裝Command Line Tools,請參照上面第2步完成安裝動作。
  2. dlsym(0x7f99a30f7b80, clang_getFieldDeclBitWidth): symbol not found. Please ensure that your python bindings are compatible with your libclang.so version.
    這個問題造成的原因是clang+llvm檔案下載錯了,請參照上面第7步下載正確的clang+llvm檔。
  3. Error parsing translation unit.
  4. 這個問題造成的原因是編譯需要的檔案或工具有缺少。
    可能是︰userconf.ini檔裡cxxgeneratordir路徑指定錯誤了,也可能是需要煸譯的檔案有遺失或不完整造成(如test目錄裡simple_test原始C++檔目錄被你刪掉導致缺少了欲編譯檔案而無法完成編譯) 

文章參考來源︰

1. 老G的Blog
2. cocos2d-x官方教學
3. cocos2d-x論壇

文章關鍵字︰
cocos2d-x, Javascript call C++, Javascript call Native, JSB Binding, cxx-generator, bindings-generator

[cocos2dx-JSB篇]node.getChildByTag() is not defined.

文章撰寫日期︰2013/09/05 11:21
cocos2dx使用版本︰v 3.0 alpha 0
cocosBuilder使用版本︰v 3.0 alpha 5

一、問題

今天遇到node.getChildByTag() is not defined.的問題

二、解決辦法

我在JSB裡使用cocosBuilder,
cc.BuilderReader讀進來的ccbi-node其實是在根node的第2層,
因此如果在使用cc.Node.getChildByTag()時,
要注意有沒有加上.rootNode來取到根節點。
否則CCB層製作岀來的node是沒有getChildByTag()指令的。

[cocos2d-CocosBuilder篇]compile(編譯製作)自己專用的CocosBuilder

文章撰寫日期︰2013/08/30 23:20
cocos2dx使用版本︰v 3.0 alpha 0
cocosBuilder使用版本︰v 3.0 alpha 5

一、前言

CocosBuilder使用上很方便,
但想要改一些程式碼,
或者模版編譯岀來的東西離自己的需求離很遠,
該怎麼辦?

答案是複製原始碼修改自己想要的

筆者在學會怎麼載入並製作自己想要的cocosBuilder遇到了很大很大很大的阻礙(stuck in it),
現在會了,
不吝嗇的在部落格上跟大家分享。

廢話不多說,
我們看下去。

二、文章開始

步驟1 從gitHub上複製一份原始碼到你的桌機上

我們需要在github上clone一份cocosBuilder的原始碼至桌機裡,
底下放上一張示意。

步驟2 將submodule也複製下來

很多人都漏作或卡在這個步驟,
其實這個步驟在cocosBuilder下載下來後,
README.md檔裡寫得相當清楚︰

Cocos2d and other extensions are provided as a submodules to this project. To be able to compile the source code you need first check out the module. Change directory into the top (this) directory of CocosBuilder and run:
cocos2d和其它的擴充套件都使用了submodule(在git裡維護一個專案底下的次專案我們用submodule,這個次專案是一個被共用的Library,像我們開發Cocos2d-x遊戲都要用到最基本的Library:cocos2d一樣),如果你希望能夠編譯您的code,你就一定要下載這個module(這裡指Cocos2d Library)。請在您的terminal視窗,下載完cocosBuilder源碼(下列第1行)後,進入cocosBuilder目錄再打上下列第3行指令,便可以下載cocosBuilder需要的submodule。

    $git clone https://github.com/cocos2d/CocosBuilder //下載CocosBuilder源碼
    $cd CocosBuilder
    $git submodule update --init --recursive //下載CocosBuilder源碼需要的Library

包含我,
都是不看說明文件的那一個(><)。

步驟3 Xcode的輸岀Target設為cocosBuilder

一樣,說明文件中接著寫道︰

When building CocosBuilder, make sure that "CocosBuilder" is the selected target (it may be some of the plug-in targets by default).
當在建置cocosBuilder專案時,請確定"CocosBuilder"是您選擇的建置target(因為有時候還會有很多其它的plug-in在target列表中),沒有選擇這個動作可能會導致您的專案怎樣都無法run起來


三、總結

經過2次的git下載(第1次下載cocosBuilder源碼,第2次下載它需要的submodule)並選擇target為cocosBuilder後,
整個專案就被編譯起來了。
編譯出來的.app檔案會放在product資料夾底下。
把它複製到你容易使用的地方吧(像是應用程式資料夾底下)!

[cocos2dx-JSB篇]使用CCControlButton擴充元件

文章撰寫日期︰2013/08/30 23:20
cocos2dx使用版本︰v 3.0 alpha 0
cocosBuilder使用版本︰v 3.0 alpha 5

一、前言

CCControlButton擴充件在cocos2dx2.1.4版尚未得到完整的JSB Binding支援,
如同前一篇所言,
因此只好忍痛改用cocos2dx-3.0alpha0版。

但是,
卻發現cocosBuilder編譯岀來的HTML5編碼仍然說不支援CCControlButton,
岀現 Cannot call method 'setCallback' of undefined.的錯誤。

筆者記︰
不僅是CCControlButton無法使用(cocos2dx-html5端沒有寫接收CCControlButton的Callback),連一些基本.width或.height的指令都會無法用。

二、文章開始

百思不得其解,
仔細查看coocsBuilder編譯岀來的boot-html5.js檔才發現這當中大有文章。

以下是boot-html5.js檔編譯岀來的原內文︰

(function () {
    var d = document;
    var c = {
        COCOS2D_DEBUG:2, //0 to turn debug off, 1 for basic debug, and 2 for full debug
        box2d:false,
        chipmunk:true,
        showFPS:true,
        loadExtension:true,
        frameRate:60,
        tag:'gameCanvas', //the dom element to run cocos2d on
        //engineDir:'../../../../cocos2d/',
        SingleEngineFile:'cocos2d-html5.min.js',
        appFiles:[
          'js/ApiBank.js',
    'js/ChoiceScene2.js',
    'js/CommonUtil.js',
    'js/DoorScene.js',
    'js/HomeScene.js',
    'js/PlayScene.js',
    'js/Questions.js',
    'js/StartScene.js',
    'js/TemplateScene.js',

            'resources-html5.js',
            'boot2-html5.js'
            ]

};
    window.addEventListener('DOMContentLoaded', function () {
        //first load engine file if specified
        var s = d.createElement('script');
        /*********Delete this section if you have packed all files into one*******/
        if (c.SingleEngineFile && !c.engineDir) {
            s.src = c.SingleEngineFile;
        }
        else if (c.engineDir && !c.SingleEngineFile) {
            s.src = c.engineDir + 'platform/jsloader.js';
        }
        else {
            alert('You must specify either the single engine file OR the engine directory in "cocos2d.js"');
        }
        /*********Delete this section if you have packed all files into one*******/

            //s.src = 'Packed_Release_File.js'; //IMPORTANT: Un-comment this line if you have packed all files into one

        d.body.appendChild(s);
        document.ccConfig = c;
        s.id = 'cocos2d-html5';
        //else if single file specified, load singlefile
    });
})();

從這段code可看見,
cocosBuilder怎麼讓JSB Binding岀來的code如何透過cocos2d-html5在HTML5繪圖,
原來是用了以下這個微型化引擎︰

SingleEngineFile:'cocos2d-html5.min.js',

cocosBuilder在編譯成HTML5檔時,
自動寫入了這個很簡易的cocos2d-html接口,
讓我們攢寫的JSB-Binding Code可以和HTML5溝通,
也因為是微型化的版本,
我們需要改用被註解掉的
engineDir:'../../../../cocos2d/',
來獲得完成的cocos2d-html5接口支援。

在gitHub上將完整的coocs2d-html複製下來,
將其下cocos2d資料夾對應到上面
engineDir:'../../../../cocos2d/',
的路徑,
即可獲得完整的cocos2d-html支援,
此時,
CCcontrolButton也將能獲得完全的html5版支援!

三、結論

cocos2d家族需要很大的effort才能搞懂許多事, 有時候不妨耐心去研究, 當搞懂一些事情時, 是很美妙的一件事的。

相關文章︰

compile自己專屬的cocosBuilder!

[cocos2dx-JSB篇]callbackNode.setCallback is not a function錯誤

文章撰寫日期︰2013/08/28 11:48
cocos2dx使用版本︰v 2.1.4
cocosBuilder使用版本︰v 3.0 alpha 5

一、問題

今天在Cocos2d-x2.1.4使用JSB,
cocosBuilder上使用CCControlButton這個Extension元件時,
回報我callbackNode.setCallback is not a function的錯誤。

二、解決辦法

cocos2dx2.1.4版還沒有針對CCControlButton做JSB Binding的支援,
如果要使用的同鞋,
建議直接放棄2.1.4版
不然就是不要使用CCControlButton這個元件...

因為我曾試過要修改2.1.4版做CCControlButton的Binding,
但改版工程實在太皓大...

下列是改版工程動到的Code...
CCControlButton異動部份

=====JSB Biding端====
scripting/javascript/bindings/jsb_cocos2dx_extension_manual.cpp
scripting/javascript/bindings/js_bindings_config.h
scripting/javascript/bindings/js/jsb_cocos2d_extension.js
scripting/javascript/bindings/ScriptingCore.h
scripting/javascript/bindings/ScriptingCore.cpp
scripting/javascript/bindings/js/jsb_cocosbuilder.js
scripting/javascript/bindings/cocos2d_specifics.cpp

extensions/GUI/CCControlExtension/CCControl.cpp


=====觸控事件=====
extensions/CCBReader/CCBAnimationManager.h

extensions/CCBReader/CCBAnimationManager.cpp
extensions/CCBReader/CCBReader.cpp
extensions/CCBReader/CCBReader.h
extensions/CCBReader/CCNodeLoader.cpp

如果仍要改的同鞋,
我提供github上的參考連結︰
1. 官網討論串
2. dumganhar(James Chen)針對cocos2dx3.0版的Binding修改記錄

三、總結

cocos2d-x2.1.4版在C++端趨於成熟,
而在JSB端像個初生兒...

[cocos2dx-JSB篇]TypeError: _ccbGlobalContext[documentControllerName] is not a constructor錯誤

文章撰寫日期︰2013/08/24 18:25
cocos2dx使用版本︰v 2.1.4
cocosBuilder使用版本︰v 3.0 alpha 5

一、問題
今天在使用jsb開發時, 遇到
TypeError: _ccbGlobalContext[documentControllerName] is not a constructor
的錯誤。

二、解決辦法

有幾種原因,
但主要原因都是你目前欲使用的Scene實例化失敗。

1.沒有將新的js檔宣告進main.js

在main.js檔中宣告require("新的Scene");

2.cocosBuilder端JSController綁定的js檔裡面沒有編譯通過

可能是忘了宣告這個Scene的實體物件,
或這份js文件裡面使用的語法有誤,
導致JSB在載入該js檔時宣告失敗。