[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()指令的。