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檔時宣告失敗。