顯示具有 javascript 標籤的文章。 顯示所有文章
顯示具有 javascript 標籤的文章。 顯示所有文章

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

[JSB-Android篇]XmlHttpRequest元件在Android端使用回傳reponse failed

無法查看此摘要。請 按這裡查看文章。

[JSB-IOS篇]遇到 error: failed to attach to process ID 0 resources

文章撰寫日期︰2013/08/24 04:20
文章修改時間︰2013/08/31 23:36
文章修改次數︰2
cocos2dx使用版本︰v 2.1.4
cocosBuilder使用版本︰v 3.0 alpha 5

一、問題

今天遇到Xcode回報
error: failed to attach to process ID 0 resources

導致cocos2dx專案在Xcode上一直無法啟動的問題。

二、解決辦法

我遇到的問題是Resources資料夾同時做為Group,
又同時做為References產生的問題。

在Stackoverflow有網有提到︰
I experienced the same problem, and after a while I found out that it was due to the fact that my XCode project included a Folder Reference to a folder named Resources.
It seems that XCode doesn't like that name.
Just removing the folder reference or renaming the folder solved the issue.
將藍色資料夾的Resources(References)移除即可解決問題。

如果這個問題解決不了你的狀況,
請再爬文,
因為看起來造成這個error的原因有很多。

2013/08/31
今天又遇到一次問題,
解決辦法是到
/Users/你的名稱/Library/Developer/Xcode/DerivedData
底下去把專案刪掉,IOS Simulator重新reset,
最後才告訴我在main.js裡多宣告了一個已被我刪除的require導致整隻程式run不起來。

[JSB-Androdi篇]遇到Errors running builder 'Integrated External Tool Builder' on project 'xxx'

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

一、問題

在專案初始化啟動後, Eclipse岀現下列狀況︰

Errors running builder 'Integrated External Tool Builder' on project 'xxx'.


二、解決辦法


將底下的這個工具(Invalid External Tool Builder)移除即可

未確定錯誤

error: failed to attach to process ID 0
(可能是JSB Binding專案有漏掉,重拉進來看看,不要用Reference,用Group)

找不到js檔案資源
可能是main.js裡require("xxxx.js")忘記打上根目錄
譬如 require("javascript/xxxx.js")

[cocos2dx-JSB篇]JSB教學-跨岀cocos2dx-Javascript的第一步!!(此篇為轉載文)

文章撰寫日期︰2013/08/24 01:54
cocos2dx使用版本︰v 2.1.4
cocosBuilder使用版本︰v 3.0 alpha 5
文章來源︰劉松的Github教學

前言

由國人自己研發的開源遊戲引擎Cocos2d-x,在很短的時間內就風靡全球,來自多個國家的開發者均參與貢獻代碼,其優秀毋庸置疑。但是,年輕的 Cocos2d-x正處於快速發展階段,圍繞其周邊的配套工具、文檔、教程等等均尚不完善。我本人在學習的過程中就體會過把Google、 StackOverflow、github以及官方論壇等等翻個底朝天都找不到相關資料的窘境。這也是本篇教程誕生的根本原因。

因我本人亦是剛剛加入Cocos2d陣營學習不久,加上自身能力有限,教程之中若有錯誤,還望不吝指出,我將及時更新修復錯誤。另外,本人熱愛開源,因此本教程亦設定為“開源教程”。希望能藉此拋磚引玉,讓更多的朋友參與到這個教程的編寫過程中來,共同學習和完善相關內容,讓更多人後來者受益。

一、Cocos2d-x JavaScript Binding簡單介紹

眾所周知,Cocos2d-x的主要開發語言是C++,而Cocos2d-x JavaScript Binding則是基於Cocos2d-x用JavaScript語法來編寫遊戲。 Cocos2d-x JavaScript Binding又常常被簡稱為JSB,其實現原理可簡單地總結為:Cocos2d-x內置了一套JavaScript的解析引擎SpiderMonkey,通過SpiderMonkey在引擎內部將JavaScript代碼“映射”為C++代碼,從而實現了用JavaScript語法調用Cocos2d-x的API來完成遊戲的邏輯的編寫。這意味著,JSB開發模式在依然保持了C++原生應用同樣的性能這個優點之外,還大大降低了開發語言的門檻。

另外,由於Cocos2d家族的另一支新秀Cocos2d-HTML5也繼承了Cocos2d家族相同的API結構,這就使得我們可以將由JSB編寫的代碼很輕鬆地移植到Cocos2d-HTML5,從而實現了橫跨原生客戶端和瀏覽器的全新的遊戲開發模式。這一特性優勢,也是目前與JSB並行存在的Cocos2d-x Lua Binding所不能比擬的。雖然相比Lua Binding而言JavaScript Binding目前還顯得不太成熟,但我認為後者一定是未來。

在講述Cocos2d-x JavaScript Binding開發實踐之前,我們不得不提到CocosBuilder。相信很多人都至少聽說過這款功能強大的工具,其集成了所見即所得的場景編輯器、動畫編輯器、智能紋理打包以及JavaScript綁定相關配置功能,讓開發工程師不再需要跟任何視覺相關的環節打交道,從而專注於遊戲的邏輯控制部分,使得遊戲開髮變得更加簡單。下面就將結合我的實際使用經歷來講解Cocos2d-x JavaScript Binding結合CocosBuilder的跨平台遊戲開發實踐。

二、開發環境配置

本節內容我大量參考和翻譯了國外的一篇文章《Setup a cross platform project with CocosBuilder and Cocos2d-x》(須翻牆),這篇文章裡所描述的項目目錄結構較為合理,我個人認為非常適合用作跨平台開發和調試的通用結構。我將這篇文章的主要內容摘錄翻譯下來,並結合這篇教程的需要做了一些修改,同時也方便了英文不好的朋友。

1、在Mac終端下載Cocos2d-x最新版本並解壓(此時最新版本為2.1.4)。 我更習慣用命令工具列,參考下面:

$  cd #回到根目录,也可以放在别的目錄
$  wget https://cocos2d-x.googlecode.com/files/cocos2d-x-2.1.4.zip
$  unzip cocos2d-x-2.1.4.zip
提示:以上過程解壓後的目錄應該是cocos2d-x-2.1.4,你可能改下目錄名,也可以保持不變。下面的內容將會把這個目錄名用{cocos2d-x}代替。比如,我的{cocos2d-x}實際指代的是/Users/liusong/cocos2d-x

2、使用cocos2d-x自带的工具创建工程。

$  cd {cocos2d-x}/tools/project-creator
$  ./create_project.py -project MyGame -package com.MyCompany.AwesomeGame -language javascript  #創建一個名叫MyGame的跨平台工程,會在{cocos2d-x}/projects/目錄下自動生成MyGame工程代碼
$  cd ../../projects/MyGame  #切换到工程目錄
$  rm -rf Resources/     #刪除默認生成的資源目录,後面會用到CocosBuilder生成的資源目錄
提示:這裡創建的工程名稱MyGame會在後續教程中頻繁出現,如果你不是使用這個名稱,那麼請注意在後面自行更改

3、下載、安裝、配置CocosBuilder的最新版(此時最新版為3.0 alpha4)。

在這裡我推薦使用Git來clone源碼的方式來下載CocosBuilder,因為目前CocosBuilder尚在發展中,並不太完善和穩定,下載源代碼的好處是今後遇到問題時可以自己通過追蹤源代碼來解決,也可以及時合併最新的補丁而不用等官方發布新版。
$  cd #回到根目錄,也可以放在别的目錄
$  git clone https://github.com/cocos2d/CocosBuilder.git
$  cd CocosBuilder
$  git submodule update --init --recursive
$  open ./CocosBuilder/CocosBuilder.Xcodeproj  #打开CocosBuilder的Xcode工程

在打開的Xcode工程中,確認左上角的scheme是CocosBuilder而不是其他,直接點擊“Run”,經過一段時間的編譯運行後CocosBuilder將會被打開。這時候,你可以在CocosBuilder根目錄下的build文件夾中看到Xcode生成的CocosBuilder.app文件。今後如果有需要啟動CocosBuilder,就可以直接打開這個來啟動,無須再在Xcode中編譯運行,除非是你修改過CocosBuilder的源碼。這個我們後面會提到。 

在打開的CocosBuilder界面中新建一個CocosBuilder工程(File->New->New Project),注意這裡的命名一定和之前的項目名稱一樣,並且要保存在工程目錄。如下圖所示:

保存時會提示是否覆蓋,請點擊“Replace”確認覆蓋。如下圖:
提示:如果你操作時沒有出現這個提示,那麼一定是你的名稱或保存目錄位置有錯,請刪除剛才創建的內容重新操作。

以上操作完畢後,你會看到在MyGame目錄下新增了MyGame.ccbproj文件和Resources目錄。 MyGame.ccbproj是CocosBuilder的工程文件,而Resources則是默認的資源存放路徑。

還記得我們之前創建項目工程後刪掉的Resources目錄嗎?這裡又重新補上了,因為我們下來都要用CocosBuilder來組織和生成遊戲資源。注意這個資源路徑設置僅僅是默認的,為了方便教學我們不做修改,如果你需要修改,​​請打開菜單File->Project Settings進行修改。
打開Resources目錄可以看到,裡面已經有一些文件。這是CocosBuilder在創建工程時默認為我們添加的,我們這個教程將直接使用這些默認的資源來進行演示,所以我們予以保留。如下圖:

接下來,點擊菜單(File->Publish Settings)打卡發佈設置界面,激活所有平台。默認情況下,iOS和HTML5的發佈設置都是選中狀態,我們只需要再勾選上中間的Andr​​oid。請注意每個選項中以Published-開頭的設置,那代表著你用CocosBuilder製作的遊戲資源或代碼將會被存儲到那些對應的目錄裡。圖示:
最後點擊菜單(File->Publish)進行發布,這個發布行為會自動生成上面提到的三個Published-開頭的文件夾。打開看看,會發現裡面有一些文件,那都是剛才由CocosBuilder自動生成的。仔細觀察會發現,不同平台目錄下的文件會有所差異,這就是CocosBuilder的強大之處,它可以根據你的設置來針對不同平台的特徵自動處理資源兼容和適配問題。另外,原來資源目錄Resources下的ccb文件均被發布成了ccbi的二進製版本,以供程序代碼直接調用。


4、修改工程配置以連接CocosBuilder

修改AppDelegate.cpp
$  cd {cocos2d-x}/projects/MyGame #切换到项目根目錄
$  vim Classes/AppDelegate.cpp
最後,修改applicationDidFinishLaunching的內容如下:
bool AppDelegate::applicationDidFinishLaunching()
{
  // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());

    CCSize designSize = CCSizeMake( 480,320);
    CCSize resourceSize = CCSizeMake( 960,640);
    CCSize screenSize = CCEGLView::sharedOpenGLView()->getFrameSize();

    std::vector<std::string> resDirOrders;

    TargetPlatform platform = CCApplication::sharedApplication()->getTargetPlatform();
    if (platform == kTargetIphone || platform == kTargetIpad)
    {
        std::vector<std::string> searchPaths = CCFileUtils::sharedFileUtils()->getSearchPaths();
        searchPaths.insert(searchPaths.begin(), "Published-iOS");
        CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
        if (screenSize.height == 1536)//iPad-hd
        {
            CCLog("resources-ipadhd");
            resourceSize = CCSizeMake(2048, 1536);
            resDirOrders.push_back("resources-ipadhd");
        }
        else if (screenSize.height == 768)//iPad
        {
            CCLog("resources-ipad");
            resourceSize = CCSizeMake(1024, 768);
            resDirOrders.push_back("resources-ipad");
        }
        else if (screenSize.height == 640)//iPhone 4/4s/5
        {
            CCLog("resources-iphonehd");
            resourceSize = CCSizeMake( 960,640);
            resDirOrders.push_back("resources-iphonehd");
        }
        else//iPhone 3GS
        {
            CCLog("resources-iphone");
            resourceSize = CCSizeMake(480, 320);
            resDirOrders.push_back("resources-iphone");
        }
    }
    else if (platform == kTargetAndroid || platform == kTargetWindows)
    {
        if (screenSize.height > 720)
        {
            resourceSize = CCSizeMake( 960,640);
            resDirOrders.push_back("resources-large");
        }
        else if (screenSize.height > 568)
        {
            resourceSize = CCSizeMake(480, 720);
            resDirOrders.push_back("resources-medium");
        }
        else
        {
            resourceSize = CCSizeMake(320, 568);
            resDirOrders.push_back("resources-small");
        }
    }

    CCFileUtils::sharedFileUtils()->setSearchResolutionsOrder(resDirOrders);
    pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionNoBorder);

    // turn on display FPS
    pDirector->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);

    ScriptingCore* sc = ScriptingCore::getInstance();
    sc->addRegisterCallback(register_all_cocos2dx);
    sc->addRegisterCallback(register_all_cocos2dx_extension);
    sc->addRegisterCallback(register_all_cocos2dx_extension_manual);
    sc->addRegisterCallback(register_cocos2dx_js_extensions);
    sc->addRegisterCallback(register_CCBuilderReader);
    sc->addRegisterCallback(jsb_register_chipmunk);
    sc->addRegisterCallback(jsb_register_system);
    sc->addRegisterCallback(JSB_register_opengl);
    sc->addRegisterCallback(MinXmlHttpRequest::_js_register);
    sc->addRegisterCallback(register_jsb_websocket);

    sc->start();

    CCScriptEngineProtocol *pEngine = ScriptingCore::getInstance();
    CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);
    ScriptingCore::getInstance()->runScript("main.js");

    return true;
}
全部修改完成後保存,退出編輯。

仔細對比不難發現,這裡所做的修改,是在應用啟動的時候根據設備類型和屏幕分辨率來設置資源搜索路徑。這個步驟的設置常常會被忽略掉,我本人也曾經在這裡浪費掉很多時間。究其原因,是CocosBuilder給人留下了“自動適配多種分辨率”印象,從而下意識地認為這個適配工作將會由引擎來自動完成,而實際情況卻不是這樣。

CocosBuilder可以以某個分辨率下的資源為準,通過自動縮放來為生成適配其他分辨率的資源,但遊戲中如何加載這些不同的資源卻需要手工設置規則。

修改iOS工程配置

$  open proj.ios/MyGame.Xcodeproj/ #打开iOS工程

打開後,分別做以下三件事:
可以看到Resources分組下的main.js, res, src是顯示紅色的,這些文件或文件夾在此前的步驟裡已經連帶Resources目錄刪除而不存在,但其引用關係依然在,所以我們將其選中並右鍵點選“delete”刪除。



將此前由CocosBuilder自動生成的Published-iOS文件夾拖拽到Xcode中。注意要放在MyGame的根節點下,並且要在彈出的窗口中去掉第一個"Copy items into …"選項前面的勾選狀態,然後選中“Create folder references for any added folders”。這兩個操作非常重要,其含義是在MyGame的Xcode工程中對Published-iOS文件夾建立一個“引用”關係,而不是將此文件夾的內容複製到工程中。這樣的好處是,今後Published-iOS目錄中有任何變動都會及時地反應到MyGame,而無須再次手動添加到工程。


注意Xcode左上角的scheme區域的左側,如果顯示的是cocos2dx,請點擊該按鈕將其手動改為MyGame。如果本就是MyGame則無須修改。另外,右邊的iOS Device也需要重新點選為一個具體的模擬器,如圖,我選擇的是iPhone 6.1 Simulator。


完成以上步驟後,點擊左上角Run按鈕,Xcode將會開始編譯並自動啟動模擬器來啟動和運行MyGame。看看效果,就是此前在CocosBuilder所生成的默認畫面。

修改Android工程配置[待更新,欢迎提交]


配置HTML5环境

HTML5版本中加載資源需要通過HTTP請求來完成,所以必須要有一個WebServer。你可以將Published-HTML5中的所有文件都上傳到你已有的服務器,也可以在本地搭建一個。本教程將不會涉及WebServer的內容,所以採用本地環境來搭建。 Python中有個快速搭建的命令:
$  cd {cocos2d-x}/projects/MyGame/Published-HTML5
$  python -m SimpleHTTPServer &
提示:python -m SimpleHTTPServer會在本機啟動一個WebServer,監聽8000端口,其默認目錄即是執行命令所在的當前目錄。因此註意要切換到你的Published-HTML5目錄下執行。

當屏幕出現類似如下提示時表示WebServer啟動成功:
Serving HTTP on 0.0.0.0 port 8000 ...

這時候打開瀏覽器,輸入http://localhost:8000即可在瀏覽器中啟動由CocosBuilder為我們自動生成的遊戲。

至此,我們的開發環境已經全部搭建完成,從此,我們就可以開始一種全新的、完全在CocosBuilder中進行遊戲開發的開發體驗了。接下來,我們會以CocosBuilder為MyGame工程默認創建的資源為基礎,通過示例講解如何在CocosBuilder中進行JSB的開發。

三、在CocosBuilder中進行遊戲開發

打開MyGame的CocosBuilder工程(也可以用圖形界面的菜單選項打開File->Open):
$  open {cocos2d-x}/projects/MyGame/MyGame.ccbproj

其界面大致介紹如下圖:

在左側的資源列表區,我們可以看到兩個以MainScene開頭的文件,一個是ccb,一個是js。
ccb文件類似PhotoShop的PSD文件,我們開發遊戲過程中的場景、精靈、動畫等都可以在ccb文件中進行編輯。另一個js文件無須多講,這就是遊戲的邏輯代碼,以JavaScript來編寫。

MainScene.ccb是CocosBuilder的默認入口,即遊戲啟動後第一個加載的場景。如果你想用其他文件作為默認入口,只需打開工程設置(File->Project settings)修改“Start ccb-file name”即可。在工程設置窗口,還可以看到其他選項,第一個“Resources paths”前面已經講過,設置資源路徑,第二個默認勾選的“JavaScript based project”表示是否使用JSB開發模式,如果你的遊戲不採用JSB,就可以去掉這個勾選。第三個默認入口已經講過,最後一個選項是設置遊戲支持的屏幕旋轉方向,默認是橫屏。

我們來到CocosBuilder界面中下面的編輯區,“Default Timeline”表示這是當前ccb的默認時間軸,點擊這裡會彈出新建和編輯timeline等選項,每個ccb文件都可以創建多個timeline,並且可以將多個timeline連接起來,具體可見點擊界面底部的“No chained timeline”的彈出菜單。


點擊選中CCLayer節點,右側會顯示這個層的各種屬性設置選項。我們注意到最頂部的“Code Connections”中“JS Controller”,這就是ccb文件和JavaScript自動連接的重要選項,它為當前這個層定義了一個JavaScript的控制器類的名稱,這樣我們就可以在程序代碼中來直接操作這個層裡面的資源或節點。

再往下,點擊選中CCLabelTTF節點,右側的“Code Connections”中“JS Controller”被禁用,第二個選項則定義了這個文本控件的名稱helloLabel。類似地,我們再選中最後一個CCMenuItemImage節點,這是一個按鈕控件,右側下面的CCMenuItem區域也已經為這個按鈕定義好了其點擊時觸發的方法名稱onPressButton,這樣我們也只需在JavaScript代碼中定義此方法即可。

在左側資源列表區雙擊打開MainScene.js,這裡的內容就可以看到MainScene的類定義、按鈕點擊​​時調用的onPressButton的方法定義及成員變量helloLabel的用法。到這裡,我們應該就基本明白了在CocosBuilder中進行遊戲開發的大致流程,我簡單總結如下:

1)在ccb中組織美術資源,創建動畫、特效
2)根據需要設置相關節點的屬性以備代碼連接
3)編寫JavaScript程序實現遊戲邏輯
4)發布,然後分別在Xcode、Eclipse和瀏覽器中調試結果

提示:以上第4步的調試工作也可以在CocosPlayer中進行,但CocosPlayer僅支持iOS和Android模擬器,考慮到HTML5平台調試的問題,本教程將暫不涉及CocosPlayer。

通常情況下,一個遊戲開發過程中有關場景、動畫和特效等視覺上的工作都是由團隊中的美術來負責完成的,因此ccb這些文件理論上來說應該由美術來完成編輯再交由開發工程師來調用,但我更推薦工程師也要學會使用CocosBuilder中場景、動畫和特效編輯等功能的用法,或者索性由二者共同完成。因為CocosBuilder目前尚不完善,美術在學習和使用過程中可能會遇到一些問題,另外資源的組織方式也是會對遊戲的性能產生影響的,這時候就需要工程師能夠協助把關,共同實現最優的解決方案。

看完了默認的示例,我們接下來將基於這個例子的資源和代碼逐步深入講解一些遊戲開發中常見問題的實現。

1、響應觸屏事件

觸屏事件是遊戲開發中必不可少的,是玩家和遊戲產生交互的基礎。我們將以MainScene為例來講解如何響應玩家的觸屏事件,目標是實現玩家點擊屏幕任意區域後在helloLabel這個文本區域內顯示其點擊位置的坐標。

需要特別強調下,一個已知的問題是Cocos2d-x和CocosBuilder中對於事件定義的標準存在差異,這導致了我們必須通過修改Cocos2d-x中CCBReader的源代碼才能正確地響應各種事件。具體修改方式如下:
$  vim {cocos2d-x}/extensions/CCBReader/CCLayerLoader.cpp
將
#define PROPERTY_TOUCH_ENABLED "isTouchEnabled"
#define PROPERTY_ACCELEROMETER_ENABLED "isAccelerometerEnabled"
#define PROPERTY_MOUSE_ENABLED "isMouseEnabled"
#define PROPERTY_KEYBOARD_ENABLED "isKeyboardEnabled"
替換為:
#define PROPERTY_TOUCH_ENABLED "touchEnabled"
#define PROPERTY_ACCELEROMETER_ENABLED "accelerometerEnabled"
#define PROPERTY_MOUSE_ENABLED "mouseEnabled"
#define PROPERTY_KEYBOARD_ENABLED "keyboardEnabled"

這個問題已經存在了較長的時間,但至今最新版本依然沒有得以解決。
做完以上修改後,我們回到CocosBuilder。雙擊打開MainScene.ccb,選中根節點(CCLayer),我們在右側最下面的CCLayer屬性設置中可以看到四個選項,其各自的含義解釋如下圖:

我們預期的是想讓MainScene響應觸屏事件,因此默認選項不用更改即可,其他三項鼠標事件、重力感應事件和鍵盤事件沒有用到則暫且不管。

現在來到代碼中,雙擊打開MainScene.js,在文件最後一行下面增加如下代碼:
MainScene.prototype.onDidLoadFromCCB = function()
{
    cc.log('MainScene ccb file has been loaded!');

    this.rootNode.onTouchesBegan = function( touches, event) {
        // 将触屏开始事件转发给控制器 (this)
        this.controller.onTouchesBegan(touches, event);
        return true;
    };

    this.rootNode.onTouchesMoved = function( touches, event) {
        // 将触屏移动事件转发给控制器 (this)
        this.controller.onTouchesMoved(touches, event);
        return true;
    };

    this.rootNode.onTouchesEnded = function( touches, event) {
        // 将触屏结束事件转发给控制器 (this)
        this.controller.onTouchesEnded(touches, event);
        return true;
    };
};

MainScene.prototype.onTouchesBegan = function(touches, event)
{
    // 修改文本内容
    this.helloLabel.setString("TOUCH START: "+parseInt(touches[0].getLocation().x)+", "+parseInt(touches[0].getLocation().y));
};

MainScene.prototype.onTouchesMoved = function(touches, event)
{
    // do some staff here
};

MainScene.prototype.onTouchesEnded = function(touches, event)
{
    // do some staff here
};

以上代碼中,onDidLoadFromCCB方法會在ccb文件加載完成後自動調用,類似iOS中的viewDidLoad。我們在onDidLoadFromCCB中分別將三種觸屏事件轉發給控制器自定義的方法去處理。在觸屏開始事件的處理方法onTouchesBegan中,我們將觸屏位置信息轉換成文本顯示在屏幕上,實現了我們的目標。另外兩個onTouchesMoved和onTouchesEnded暫時沒有用上,但我們應該能就此理解它們的用法了。

2、HTTP網路請求

為了更好地演示XMLHttpRequest的用法,我們利用前面配置HTML5環境時開啟的WebServer來提供一個HTTP服務接口,該接口直接返回一段JSON格式的字符串,JavaScript將在接收到接口返回的數據時進一步解析處理。

$  cd {cocos2d-x}/projects/MyGame/Published-HTML5
$  echo '{"data":"I am from the remote server"}' > test.json

以上操作在WebServer的根目錄創建了一個test.json文件,內容是一段JSON格式的文本。我們的目標是玩家點擊屏幕上的按鈕時向http://localhost:8000/test.json發起一個HTTP請求,並將返回數據中data字段的內容打印在屏幕上。

同樣,雙擊打開MainScene.js,將MainScene.prototype.onPressButton的方法修改如下:
// Create callback for button
MainScene.prototype.onPressButton = function()
{   
    // Rotate the label when the button is pressed
    //this.helloLabel.runAction(cc.RotateBy.create(1,360));

    //新增以下代碼
    var theHelloLabel = this.helloLabel;
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (xhr.readyState==4) {// 4 = "loaded"
            if (xhr.status==200) {// 200 = "OK"
                var response = JSON.parse(xhr.responseText);
                cc.log(response);
                theHelloLabel.setString(response.data);
            } else {
                cc.log("Problem retrieving JSON data:" + xhr.statusText);
            }
        }
    };
    //发起一个GET请求
    xhr.open("GET", "http://localhost:8000/test.json");
    xhr.send(null);
};

3、多分辨率適配方案[待更新,歡迎提交]
4、WebSocket[待更新,歡迎提交]
5、Plugin-X整合綁定[待更新,歡迎提交]
6、自定義第三方庫的綁定[待更新,歡迎提交]
7、在線資源更新解決方案[待更新,歡迎提交]

[cocos2dx-JSB篇]javascript裡使用XmlHttpRequest中文顯示成亂碼問題

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

一、問題

這幾天遇到了使用XMLHttpRequest元件時,
C++傳來的UTF-8格式中文字到Javascript端產生亂碼,
但英文、數字沒問題的BUG。


二、解決辦法

PO文到官網論壇,
網友建議重新編制成BASE64碼,
後來經cocos2dx開發者James Chen協助下,
我修改了XMLHttpRequest.CPP檔,
讓中文從C++端傳給Javascript端得以正常顯示。

[cocos2dx-JSB/HTML5篇]在各個瀏覽器上播放音檔

文章撰寫日期︰2013/08/18 13:31
文章修改日期︰2013/11/30 16:25
文章修改次數︰5
cocos2dx使用版本︰v 2.1.4 / v 2.1.5
cocosBuilder使用版本︰v 3.0 alpha 5

一、前言

Codec support in modern desktop browsers
Browser Ogg Vorbis MP3 WAV
FireFox 3.6+ ✓ ✓
Safari 5+ ✓ ✓
Chrome 6 ✓ ✓
Opera 10.5+ ✓ ✓
Internet Explorer 9 (beta) ✓ ✓

由於每個瀏覽器能播放的音檔格式皆不同,
Cocos2d-HTML5 也幫我們處理了這個問題。

二、本文開始


以下文章來自raywenderlich

Gratuitious Music and Sound Effects

You’re pretty close to having a workable (but extremely simple) game now. You just need to add some sound effects and music (since what kind of game doesn’t have sound!) and some simple game logic.
這個遊戲就快要完成了(但貌似還非常簡單),現在你還需要做的就是替這個遊戲添加聲音和特效(哪個遊戲沒有特效!)和一些簡單的遊戲邏輯。

First, update Cocos2DSimpleGame\Src\resource.js to add the sound effects:
首先,先更新在Cocos2DSimpleGame\Src\resource.js裡的這個聲音特效檔︰

var dirArt = "Art/";
var dirSounds = "Sounds/";
 
var s_player = dirArt + "player.png";
var s_monster = dirArt + "monster.png";
var s_projectile = dirArt + "projectile.png";
 
var s_bgMusic = dirSounds + "background-music.mp3";
var s_bgMusicOgg = dirSounds + "background-music.ogg";
var s_bgMusicCaf = dirSounds + "background-music.caf";
 
var s_shootEffect = dirSounds + "pew-pew-lei.mp3";
var s_shootEffectOgg = dirSounds + "pew-pew-lei.ogg";
var s_shootEffectWav = dirSounds + "pew-pew-lei.wav";
 
var g_ressources = [
 
    {type:"image", src:s_player},
    {type:"image", src:s_monster},
    {type:"image", src:s_projectile},
 
    {type:"sound", src:s_bgMusic},
    {type:"sound", src:s_bgMusicOgg},
    {type:"sound", src:s_bgMusicCaf},
 
    {type:"sound", src:s_shootEffect},
    {type:"sound", src:s_shootEffectOgg},
    {type:"sound", src:s_shootEffectWav}
 
];

Note that both the background music and sound effects are each saved in three different formats: mp3, ogg, and wav. This is because not all browsers support all formats, so by adding all three we will have the highest possible chance of the player being able to hear something. Cocos2D will detect what the browser supports and use the appropriate file – as long as they have the same filename.
注意︰這邊看到每一個背景音樂、聲音特效都被分別儲存了3種格式︰mp3、ogg和wav。主要是因為並非每種瀏覽器都能播放所有的音檔格式,所以準備3種格式的音檔,最能確保聲音播放是沒問題的。Cocos2D會偵測使用者用的瀏覽器支援了哪種適合的檔案-只要檔名都一樣就找的到。

var audioEngine = cc.AudioEngine.getInstance();
This gets a global reference to the audio engine so you can use it later. Then add this line to the end of onEnter:
這行取得到公域參照︰audio引擎,因此接下來的code你可以開始使用這個物件。把這行加到onEnter函式的最後一行吧!

audioEngine.playMusic(s_bgMusic, true);
audioEngine.playEffect(s_shootEffect);
Save the file and refresh your browser, and now you should have some groovy tunes!
存檔,重整您的瀏覽器,現在您將聽到優雅動人的音樂!

備註︰
audioEngine.playMusic如果直接傳參數xxx.mp3,
Cocos2d-html5就不會自動的幫你找xxx.ogg檔播放。
請宣告變數
var s_bgMusic = "xxx.mp3";

再用
audioEngine.playMusic(s_bgMusic, true);
播放,
這樣才會在Firefox上自動找xxx.ogg檔播放。

三、我的試驗心得

使用playMusic()時,
Cocos2d-html5會幫我們在背後自動判斷該音檔是否能夠在瀏覽器播放,
假設現在我們要播abc.mp3,
Cocos2d-html5發現Firefox不能播mp3,
那麼Cocos2d-html5會再去找有沒有abc.ogg或abc.wav檔來播放。

但是,
cocos2d-html選擇前,
會先去resources-html5.js資源裡去找是否有宣告此資源可用。

因此,
即使您有放置abc.ogg檔在資源目錄下,
但卻沒在resources-html5.js檔裡宣告。
Firefox仍會無法播音!

CocosBuilder3.0 Alpha5 目前仍沒有將ogg檔宣告進resources-htm5.js的資源檔中,這個問題會導致Firefox一直無法聽到音檔。唯一的做法就是去修改CocosBuilder源碼,請CocosBuilder輸岀HTML5資料夾時,也一併將ogg檔添加進resource-html5.js裡。

修改的方法(以CocosBuilder 3.0 Alpha5 為例)

在CocosBuilder源碼檔案CocosBuilder\Publishing\CCBPublisher.m裡

1. 60行: 函式initWithProjectSettings中
    // Setup extensions to copy
    copyExtensions = [[NSArray alloc] initWithObjects:@"jpg",@"png", @"pvr", @"ccz", @"plist", @"fnt", @"ttf",@"js", @"json", @"wav",@"mp3",@"m4a",@"caf", nil];
改成
    // Setup extensions to copy
    copyExtensions = [[NSArray alloc] initWithObjects:@"jpg",@"png", @"pvr", @"ccz", @"plist", @"fnt", @"ttf",@"js", @"json", @"wav",@"mp3",@"ogg",@"m4a",@"caf", nil];//添加ogg副檔

2. 774行: 函式publishGeneratedFiles中
if ([ext isEqualToString:@"plist"]) type = @"plist";
            else if ([ext isEqualToString:@"png"]) type = @"image";
            else if ([ext isEqualToString:@"jpg"]) type = @"image";
            else if ([ext isEqualToString:@"jpeg"]) type = @"image";
            else if ([ext isEqualToString:@"mp3"]) type = @"sound";
            else if ([ext isEqualToString:@"ccbi"]) type = @"ccbi";
            else if ([ext isEqualToString:@"fnt"]) type = @"fnt";
改成
if ([ext isEqualToString:@"plist"]) type = @"plist";
            else if ([ext isEqualToString:@"png"]) type = @"image";
            else if ([ext isEqualToString:@"jpg"]) type = @"image";
            else if ([ext isEqualToString:@"jpeg"]) type = @"image";
            else if ([ext isEqualToString:@"mp3"]) type = @"sound";
            else if ([ext isEqualToString:@"ogg"]) type = @"sound";//加入這行
            else if ([ext isEqualToString:@"ccbi"]) type = @"ccbi";
            else if ([ext isEqualToString:@"fnt"]) type = @"fnt";
編譯並執行CocosBuilder,
會發現輸岀的HTML5資料夾resources-htm5.js檔裡, 都含蓋.ogg檔了!