cocos2dx-js 开发
本文轉(zhuǎn)載于:http://lib.csdn.net/article/cocos/12811
如何學(xué)習(xí)
如何開始學(xué)習(xí)Cocos2d-JS?我我覺得比較好的方式是:
1)看測試?yán)?#xff1a;測試?yán)?/p>
2)看API文檔:
-
在線API索引(中文版)
-
下載版API索引
3)看源碼
另外還有大神錄制了進(jìn)階視頻教程:Cocos2d-JS進(jìn)階視頻教程,里面關(guān)于自學(xué)的藝術(shù)還是講的挺好的,在這里我就不累贅了。
?
如何開始
如何開始很簡單了,就兩條:
-
搭環(huán)境
-
編碼
如果你是做純web的游戲,搭建環(huán)境很簡單:
-
下載引擎包
-
下載Python2.7.6,Ant,如果沒有安裝java,請(qǐng)去下載jdk至少1.7的版本
-
配環(huán)境:無疑就是配置java環(huán)境、python環(huán)境、ant環(huán)境變量。基本上就是在系統(tǒng)環(huán)境變量path加入相關(guān)的bin目錄地址。不會(huì)的自行g(shù)oogle吧。
-
創(chuàng)建項(xiàng)目:cocos new -l js ProjectName
-
開始編碼:sublime、webstorm等等用你喜歡的開發(fā)工具吧。
官網(wǎng)也有相關(guān)文章:用Cocos Console工作流開發(fā)網(wǎng)頁/原生平臺(tái)游戲(JSB開發(fā)環(huán)境簡介)
?
如何編碼
如何編碼?如果團(tuán)隊(duì)協(xié)作,遵循團(tuán)隊(duì)的編碼規(guī)范咯。這里我只是簡單說一點(diǎn)點(diǎn):
1. 關(guān)于project.json文件的配置信息
debugMode: 0 //0 不顯示任何錯(cuò)誤信息 //1 顯示cc.assert, cc.warn, cc.log showFPS : true //為真會(huì)在屏幕左下方顯示游戲幀率 id: gameCanvas //游戲畫布的id renderMode: 0 // 0 : 自動(dòng)選擇渲染引擎:webGl、canvas// 1 : canvas // 2 : WebGL(在webgl模式下drawNode會(huì)存在嚴(yán)重的鋸齒) // modules : 游戲引用的模塊 // 模塊的名字可以在frameworks/cocos2d-html5/moduleConfig.json // 里面找到,所以后期在上線的時(shí)候可以選擇自己用到的模塊引入來減少js文件的大小2.?關(guān)于CCBoot.js
CCBoot.js是入口js文件,所以你很有必要認(rèn)真看一看其中的代碼,比如其中提供一些可用的工具:
//創(chuàng)建元素 cc.newElement//監(jiān)聽事件 cc._addEventListener//循環(huán)操作 cc.each//繼承 cc.extend cc.isFunction cc.isNumber cc.isString cc.isArray cc.isUndefined cc.isObject...//原生的渲染引擎: CanvasRenderingContext2D/WebGLRenderingContext cc._renderContext//包裹游戲畫布的外層div cc._gameDiv / cc.container比如一些你可能想要修改的東西:
包裹游戲的外層div的id名字:
//大約CCBoot.js的1864行:localContainer.setAttribute('id', 'Cocos2dGameContainer');初始加載的時(shí)候的畫布顏色:
//大約CCBoot.js的641行: canvasNode.style.backgroundColor = "black";在frameworks/cocos2d-html5/core/platform/目錄下也有很多東西,主要是平臺(tái)相關(guān)的東西。
如簡單操作dom的工具miniFramework.js里面的:
cc.$屏幕適配相關(guān)的東西’CCEGLView.js’里面的:
cc.view.adjustViewPortcc.view.setDesignResolutionSizecc.view.resizeWithBrowserSize ...文件加載相關(guān)的CCLoader.js:
Cocos2d-JS的文件加載是通過文件后綴的,如后綴名為["png", "jpg", "bmp","jpeg","gif", "ico"]的文件會(huì)通過cc._imgLoader來加載,理解了這里可以用于后期自定義文件加載插件。
還有一些編碼上面的東西放在下面再說。
?
關(guān)于音頻
音頻,在移動(dòng)端上一直是個(gè)巨坑的問題。能自動(dòng)播放,不能自動(dòng)播放、不能循環(huán)播放、根本就不播放等等簡直就是處處都是坑啊。
開始游戲中的音頻用的是cocos里面的封裝的音頻函數(shù),會(huì)對(duì)音頻文件進(jìn)行預(yù)加載、預(yù)處理。但是這里有個(gè)嚴(yán)重的問題,那就是加載的時(shí)候很容易卡在音頻那里,而且循環(huán)播放也有問題。于是決定用會(huì)原生的audio標(biāo)簽。
<audio id="gameAudio" src="res/gameMusic.mp3" loop="loop" ></audio>看起來應(yīng)該是不錯(cuò)的樣子,但是當(dāng)我們?cè)趇phone4s微信內(nèi)置瀏覽器里面測試的時(shí)候發(fā)現(xiàn)這個(gè)audio標(biāo)簽居然占據(jù)頁面空間(不是說加了controls這個(gè)屬性才會(huì)占空間么,坑啊!),于是自然而然想到的解決方案就是none掉:
<audio style="display:none" id="gameAudio" src="res/gameMusic.mp3" loop="loop" ></audio>感覺好像輕易解決了這個(gè)問題,于是開始編寫一堆音頻處理的代碼。編寫完畢之后,拿起iphone試一試,我去啊iphone上音頻不能循環(huán)播放了啊,能不能再坑點(diǎn)!這個(gè)問題困擾了好久不知道什么原因,拿著代碼去找?guī)煾等グ?#xff01;師傅只有一句話:ios上面音頻如果不顯示或者在屏幕之外有可能就會(huì)出問題哦!終于把display:none去掉一切又好了。孩子你還是太年輕了啊!對(duì)于占據(jù)空間的問題我們現(xiàn)在只能把音頻標(biāo)簽作為body最后一個(gè)child節(jié)點(diǎn),依然沒有很好的解決方案。
對(duì)于音頻的自動(dòng)播放,目前只發(fā)現(xiàn)在iphone6 plus是可以的(iphone 6沒有所以沒試過),所以只能通過用戶觸摸事件來加載。如果在HTML標(biāo)記中使用了autoplay屬性,將會(huì)忽略這個(gè)屬性,并且不會(huì)在加載頁面時(shí)播放此文件,對(duì)于 preload 屬性,同樣會(huì)忽略。唯一能解決的就是用戶進(jìn)入頁面是,讓用戶觸發(fā) touch 事件,并且只能在touch事件的回調(diào)里面加載才有效。
var $audio = document.getElementById('gameAudio'); //用戶點(diǎn)擊屏幕的任何一個(gè)地方就去加載音頻 document.addEventListener('touchstart', function(e){ $audio.load(); },false);//在某個(gè)cc.MenuItemImage/cc.MenuItemSprite/onTouchBegan的回調(diào)里面執(zhí)行播放操作 try{ $audio.play(); }catch(e){}音頻的暫停:
try{ $audio.pause(); }catch(e){}音頻的停止:
try{ $audio.currentTime = 0; $audio.pause(); }catch(e){}如果是多個(gè)音頻文件,可以使用音頻audio sprite,所有的音頻綜合到一個(gè)單音頻流中,然后播放此流的各個(gè)部分。
var audioData = {bg: {start: 0, length: 1}, run: {start: 1.3, length: 1.5} };要播放bg這段聲音:
try{ $audio.currentTime = audioData.bg.start; $audio.play(); }catch(e){}當(dāng)播放結(jié)束時(shí):
$audio.addEventListener('timeupdate', function() { if (this.currentTime >= audioData.bg.start + audioData.bg.length) { this.pause();} }, false);需要注意的是,更改 currentTime 并不是百分百正確的。假設(shè) currentTime 設(shè)為 3.2,而實(shí)際得到的卻是 3.4。每個(gè) audio sprite 之間需要少量的空間,以避免尋找到另一個(gè) sprite 的頭部。
?
一些工具
-
精靈圖制作:TexturePacker
相當(dāng)好用的精靈圖制作工具,雖然收費(fèi),但是可以申請(qǐng)免費(fèi)的密鑰,具體申請(qǐng)地址自己查吧。
用它制作精靈圖的時(shí)候注意一個(gè)地方就可以了:
勾上這個(gè)Reduce border artifacts,它會(huì)讓你的精靈圖邊緣沒有鋸齒,其它的配置地方我基本上都是默認(rèn)的。
-
位圖字體制作:Bitmap Font Generator
位圖字體其實(shí)是一張圖片,然后記錄每個(gè)文字的位置和大小,因此字體的大小在生成的時(shí)候已經(jīng)定義了,所以在用的時(shí)候最好不要改變字體的大小,如果改變了大小會(huì)對(duì)圖片進(jìn)行縮放,可能會(huì)出現(xiàn)鋸齒。
用Bitmap Font Generator這個(gè)軟件制作的字體會(huì)生成一個(gè)png文件和一個(gè)fnt文件。選擇左上方的Options->Font settings:
?
設(shè)置字體格式和字體大小。其它基本上都是默認(rèn)設(shè)置就好了。
可以在主界面上面一個(gè)個(gè)點(diǎn)擊選擇需要制作的文字,也可以把要選擇的字體放在一個(gè)txt文件里面(txt文件編碼為Utf-8),然后選擇菜單欄的Edit->Select chars from file來選擇要制作的文字。
Bitmap Font Generator還支持從image文件生成字體紋理圖,選擇菜單欄的Edit->Open Image Manager->Image->Import image(注意路徑里面不要有中文)
Id那里填寫對(duì)應(yīng)文字的ASCII碼,如我上傳的圖片里面的文字是2,其對(duì)應(yīng)的ASCII碼是50。如果不知道某個(gè)文字的ASCII碼,可以去這里查:ASCII碼對(duì)照表。
選擇好之后點(diǎn)擊菜單欄Options->Export options:
?
-
字體精簡:FontCreator
為什么需要加載字體?因?yàn)橛袝r(shí)候頁面上會(huì)有不同大小的特殊字體,用位圖又比較麻煩,加載整個(gè)字體庫又太大了,于是我找到了這個(gè)軟件。
選擇菜單欄File->New Project,填寫你的字體名字和字體樣式。然后選擇菜單欄File->Open,打開你要精簡的字體。(在新建項(xiàng)目的時(shí)候有一個(gè)Include outlines/Don’n include outlines的選項(xiàng)。如果選擇Include outlines它會(huì)默認(rèn)幫你添加一些字符)
如果是可以直接看得到的字符,我可以直接在原有的字體文件中選中這個(gè)字符,然后復(fù)制粘貼到我的項(xiàng)目里面對(duì)應(yīng)的位置上去,如果不是的話,我們可以通過下面的方法添加進(jìn)去。
ctrl+f鍵查找某個(gè)字符,如我們要添加的字是“我”,然后選擇Glyph Properties
復(fù)制Codepoints里面的參數(shù),然后選中自己的項(xiàng)目,選擇菜單欄Insert->Charaacters,把剛才復(fù)制的Codepoints粘貼到對(duì)應(yīng)的位置。
這時(shí)你會(huì)發(fā)現(xiàn)在你項(xiàng)目字符的最后會(huì)添加一個(gè)灰色方塊,回到原始字體那里,選中那個(gè)字直接復(fù)制粘貼到剛才添加的那個(gè)方塊里面就可以了:
在上面的圖里面你可以看到有很多灰色的方塊,看看里面顯示的字符,如果你用不到你可以直接點(diǎn)Delete鍵把它刪掉。
除了用這個(gè)軟件外,最近發(fā)現(xiàn)一個(gè)工具也可以用來精簡壓縮字體,感興趣的可以試試:字蛛——中文字體自動(dòng)化壓縮工具
?
-
地圖制作:Tiled Map Editor
這個(gè)其實(shí)在我們的項(xiàng)目中沒有用到,所以在這里提一下而已,有用到的可以自己去琢磨一下。
項(xiàng)目發(fā)布
項(xiàng)目發(fā)布意味著什么?簡單來說就意味著資源壓縮、代碼合并。首先來說下資源壓縮吧。
?
讓你愛恨交加的closure compiler
不是說Cocos2d-JS么?怎么會(huì)扯到closure compiler。如果你想要發(fā)布你的Cocos2d游戲,我覺得就不得不說說closure compiler這玩意,這也是為何安裝jdk的時(shí)候要求要jdk7以上的版本了。
在cocos項(xiàng)目發(fā)布的時(shí)候,有一個(gè)命令是cocos compile -p web -m release --advanced,后面加了一個(gè)advanced的參數(shù),這種模式下面使用的是closure compiler的高級(jí)js壓縮模式,壓縮比例驚人,同時(shí)會(huì)優(yōu)化js的執(zhí)行,因此壓縮之后的js性能也會(huì)得到一定提升。但是想要用這個(gè)高級(jí)壓縮模式可是有坑的,很可能你會(huì)發(fā)現(xiàn)你的代碼經(jīng)過這種壓縮模式壓縮之后就報(bào)錯(cuò)了。
所以你最好去closure compiler官網(wǎng)(google出品,所以需要FQ)看一看,這里我只提簡單的幾點(diǎn)。
需要保留變量名的,要么用@expose關(guān)鍵字申明,要么使用[]來引用,如:
/** @expose */ window.MM; /** @expose */ M.add; /** @expose */ M.add.Pos;//or window['MM']; MM['add']; MM['add']['Pos']比如在ajax請(qǐng)求數(shù)據(jù)的時(shí)候的請(qǐng)求參數(shù)和響應(yīng)參數(shù),你要寫成這樣:
//request data //加引號(hào) {'name': 'dddd', 'id': '123'} //response data //通過數(shù)組的方式取值 data['list']; data['list']['userName']記住,任何你需要讓它在壓縮之后能保持原樣輸出的你都應(yīng)該這樣寫。如果要了解更多你可以去它官網(wǎng)看看,或者看一看cocos2d-js的源碼,里面有很多應(yīng)對(duì)closure compiler高級(jí)壓縮模式的注解。
?
plist文件合并
一次請(qǐng)求是比較耗費(fèi)資源的,所以我們把plist文件合并在一個(gè)文件里面來加載,同時(shí)也對(duì)plist進(jìn)行了壓縮,下面是加載解析合并后的plist文件的插件源碼:
/*** 將plist合并成一個(gè)加載*/ cc._pjsonLoader = {KEY : {frames : 0,rect : 0, size : 1, offset : 2, rotated : 3, aliases : 4,meta : 1,image : 0},_parse : function(data){var KEY = this.KEY;var frames = {}, meta = data[KEY.meta] ? {image : data[KEY.meta][KEY.image]} : {};var tempFrames = data[KEY.frames];for (var frameName in tempFrames) {var f = tempFrames[frameName];var rect = f[KEY.rect];var size = f[KEY.size];var offset = f[KEY.offset];frames[frameName] = {rect : {x : rect[0], y : rect[1], width : rect[2], height : rect[3]},size : {width : size[0], height : size[1]},offset : {x : offset[0], y : offset[1]},rotated : f[KEY.rotated],aliases : f[KEY.aliases]}}return {_inited : true, frames : frames, meta : meta};},load : function(realUrl, url, res, cb){var self = this, locLoader = cc.loader, cache = locLoader.cache;locLoader.loadJson(realUrl, function(err, pkg){if(err) return cb(err);var dir = cc.path.dirname(url);for (var key in pkg) {var filePath = cc.path.join(dir, key);cache[filePath] = self._parse(pkg[key]);}cb(null, true);});} }; //注冊(cè)這個(gè)插件,前面說過cocos文件加載是通過文件后綴名來判斷使用哪個(gè)加載器來加載的,所以這里會(huì)加載后綴名為.pjson的文件 cc.loader.register(["pjson"], cc._pjsonLoader);那么如何來生成這個(gè).pjson文件呢?下面是我用nodejs寫的一個(gè)腳本,可以讀取目錄下面所有的.plist文件,然后生成一個(gè).pjson文件:
//pjson.js var fs = require('fs'); var plist = require('plist'); var pjson = {};//var src = "res/*.plist"; //node pjson fs.readdir('./res', function(err, files) {if (err) {throw err;}for (var i = files.length - 1; i >= 0; i--) {var file = files[i],ext = file.split('.')[1];if(ext === 'plist'){pjson[file] = [];pjson[file][0] = {};var data = fs.readFileSync('./res/'+file, 'UTF-8');var frames = plist.parse(data.toString()).frames;var fileName = Object.keys(frames);for(var j=0; j< fileName.length; j++){var dat = pjson[file][0][fileName[j]] = [];var frame = frames[fileName[j]];dat[0] = frame.frame.replace(/{|}/g, '').split(',');dat[1] = frame.sourceSize.replace(/{|}/g, '').split(',');dat[2] = frame.offset.replace(/{|}/g, '').split(',');if(frame.rotated) dat[3] = 1;}}};fs.writeFile('./res/plists.pjson', JSON.stringify(pjson), function (err) {if (err) throw err;console.log('done!');}); });所以你需要在nodejs命令行里面運(yùn)行:
//第一次運(yùn)行請(qǐng)先安裝依賴包 npm install plist//生成pjson文件 node pjson.js那么如何使用這個(gè)文件呢?很簡單,你只需要在resource.js的g_resources數(shù)組里面刪除plist相關(guān)的,然后添加這個(gè)plists.pjson的路徑就可以了,其它不用作任何改動(dòng)。
?
圖片資源壓縮
關(guān)于圖片和其他靜態(tài)資源,我用了一個(gè)前端自動(dòng)化任務(wù)工具gulp,不懂的可以看我上篇博文:Gulp上手,下面是我針對(duì)項(xiàng)目配置的gulp任務(wù)gulpfile.js:
var gulp = require('gulp'),imagemin = require('gulp-imagemin'),pngquant = require('imagemin-pngquant'),cache = require('gulp-cache'),autoprefixer = require('gulp-autoprefixer'),minifycss = require('gulp-minify-css'),rev = require('gulp-rev'),revReplace = require('gulp-rev-replace'),useref = require('gulp-useref');var basePath = 'publish/html5/';gulp.task('image', function () {return gulp.src(basePath+'res/**/*.png').pipe(cache(imagemin({optimizationLevel: 7,use: [pngquant({ quality: '60-80', speed: 1 })]}))).pipe(gulp.dest(basePath+'res')); });gulp.task('style', function () {return gulp.src('css/**/*.css').pipe(autoprefixer('Android', 'BlackBerry', 'iOS', 'OperaMobile', 'ChromeAndroid', 'FirefoxAndroid', 'ExplorerMobile')).pipe(minifycss()).pipe(gulp.dest(basePath+'css')); });gulp.task('static', function () {var userefAssets = useref.assets();return gulp.src(basePath+'index.html').pipe(userefAssets).pipe(rev()) .pipe(userefAssets.restore()).pipe(useref()).pipe(revReplace()).pipe(gulp.dest(basePath)); });gulp.task('default', ['image', 'style', 'static']);因?yàn)槠渲杏玫搅藢?duì)每次生成的js、css文件進(jìn)行md5命名和合并操作,所以你需要在你的html文件里面作如下配置:
<!-- build:css css/main.css --> <link rel="stylesheet" href="css/a.css"> <link rel="stylesheet" href="css/b.css"><!-- endbuild --><!-- build:js game.js --> <script src="frameworks/cocos2d-html5/CCBoot.js"></script> <script src="main.js"></script> <!-- endbuild -->整個(gè)項(xiàng)目發(fā)布
接著我寫了一個(gè)整個(gè)項(xiàng)目的發(fā)布腳本build.js:
var exec = require('child_process').exec;var buildProcess = exec('cocos compile -p web -m release --advanced', {}); buildProcess.on('close', function () {console.log('start gulp task');var nextProcess = exec('gulp default', {});nextProcess.on('close', function () {console.log('gulp task end');});nextProcess.stdout.setEncoding('utf-8');nextProcess.stdout.on('data', function (data) {console.log(data);});nextProcess.stderr.setEncoding('utf-8');nextProcess.stderr.on('data', function (data) {throw new Error(data);}); }); buildProcess.stdout.setEncoding('utf-8'); buildProcess.stdout.on('data', function (data) {console.log(data); }); buildProcess.stderr.setEncoding('utf-8'); buildProcess.stderr.on('data', function (data) {throw new Error(data); });所以每次項(xiàng)目發(fā)布的時(shí)候,你只需要打開nodejs命令行,然后執(zhí)行一下一個(gè)命令就完事:
node build.js一些可能對(duì)你有用的代碼
ajax簡單封裝
Utils.ArrayProto = Array.prototype; Utils.slice = Utils.ArrayProto.slice;Utils.decode = decodeURIComponent; Utils.encode = encodeURIComponent;Utils.defaults = function(obj){cc.each(Utils.slice.call(arguments, 1), function(o){for(var k in o){if (obj[k] == null) obj[k] = o[k];} });return obj; };Utils.formData = function(o) {var kvps = [], regEx = /%20/g;for (var k in o) kvps.push(Utils.encode(k).replace(regEx, "+") + "=" + Utils.encode(o[k].toString()).replace(regEx, "+"));return kvps.join('&'); };Utils.ajax = function(o){var xhr = cc.loader.getXMLHttpRequest();o = Utils.defaults(o, {type: "GET", data: null, dataType: 'json', progress: null, contentType: "application/x-www-form-urlencoded"});//ajax進(jìn)度的//if(o.progress) Utils.Progress.start(o.progress);xhr.onreadystatechange = function() {if (xhr.readyState == 4){if (xhr.status < 300){var res;if(o.dataType == 'json'){res = window.JSON ? window.JSON.parse(xhr.responseText): eval(xhr.responseText);}else{res = xhr.responseText;}if(!!res) o.success(res);////ajax進(jìn)度的//if(o.progress) Utils.Progress.done();}else{if(o.error) o.error(xhr, xhr.status, xhr.statusText); }}};//是否需要帶cookie的跨域//if("withCredentials" in xhr) xhr.withCredentials = true;var url = o.url, data = null;var isPost = o.type == "POST" || o.type == "PUT";if( o.data && typeof o.data == 'object' ){data = Utils.formData(o.data);}if (!isPost && data) {url += "?" + data;data = null;}xhr.open(o.type, url, true);if (isPost) {xhr.setRequestHeader("Content-Type", o.contentType);}xhr.send(data);return xhr; };Utils.get = function(url, data, success){if(cc.isFunction(data)){success = data;data = null;}Utils.ajax({url: url, type: "GET", data: data, success: success}); };Utils.post = function(url, data, success){if(cc.isFunction(data)){success = data;data = null;}Utils.ajax({url: url, type: "POST", data: data, success: success}); };用法和jquery的ajax用法類似
LoaderScene重定義
下面是我的loaderScene的一部分代碼:
var LoaderScene = cc.Scene.extend({_interval : null,_label : null,_className:"LoaderScene",numberSprites: [],init : function(){var self = this;// bgvar bgLayer = self._bgLayer = new cc.LayerColor(cc.color(216, 216, 216));bgLayer.setPosition(cc.visibleRect.bottomLeft);self.addChild(bgLayer, 0);//you codesreturn true;},onEnter: function () {cc.Node.prototype.onEnter.call(this);var loader = (this.loadType == 'resource') ? this._startLoading : this._startAjax;this.schedule(loader, 0.3);},onExit: function () {cc.Node.prototype.onExit.call(this);//you codes },initWithResources: function (resources, cb) {if(cc.isString(resources))resources = [resources];this.resources = resources || [];this.cb = cb;this.loadType = 'resource';},_startLoading: function () {var self = this;self.unschedule(self._startLoading);var res = self.resources;cc.loader.load(res, self._loadProgress.bind(self), function () {if (self.cb) self.cb();});},initAjax: function(ajaxSetting){this.ajaxSetting = ajaxSetting;this.loadType = 'ajax';},_startAjax: function(){var self = this,preNum = 0;self.unschedule(self._startAjax);if(!this.ajaxSetting.progress){this.ajaxSetting.progress = function(n){n = n.toFixed(2);if(preNum === n) return;preNum = n;self._loadProgress(null, 1, n);};}Utils.ajax(this.ajaxSetting);},_loadProgress: function(result, count, loadedCount){var percent = (loadedCount / count * 100) | 0;percent = Math.min(percent, 100);console.log(percent);} });LoaderScene.preload = function(resources, cb){var _cc = cc;if(!_cc.loaderScene) {_cc.loaderScene = new LoaderScene();_cc.loaderScene.init();}_cc.loaderScene.initWithResources(resources, cb);cc.director.runScene(_cc.loaderScene);return _cc.loaderScene; };LoaderScene.ajaxLoad = function(ajaxSetting){var _cc = cc;if(!_cc.loaderScene) {_cc.loaderScene = new LoaderScene();_cc.loaderScene.init();}_cc.loaderScene.initAjax(ajaxSetting);cc.director.runScene(_cc.loaderScene);return _cc.loaderScene; };如果是普通的資源加載調(diào)用LoaderScene.preload,如果是ajax加載定調(diào)用LoaderScene.ajaxLoad,配合上面的ajax封裝來用:
LoaderScene.preload(g_resources, function () {console.log('loaded!!!'); });LoaderScene.ajaxLoad({url: 'test.json',data: {'name': 'ddd'}success: function(data){console.log(data);},error: function(xhr, status, msg){} });其中有個(gè)顯示ajax加載百分比的方法,需要用到一個(gè)生成加載百分比的方法,同時(shí)要把a(bǔ)jax封裝里面的if(o.progress)的注釋打開:
Utils.noop = function(){};Utils.clamp = function(n, min, max) {if (n < min) return min;if (n > max) return max;return n; };Utils.Progress = {}; //設(shè)置最小值、更新頻率和速度 Utils.Progress.settings = {minimum: 0.1,trickle: true,trickleRate: 0.3,trickleSpeed: 100 };Utils.Progress.status = null;Utils.Progress.set = function(n) {var progress = Utils.Progress;n = Utils.clamp (n, progress.settings.minimum, 1);progress.status = n;progress.cb(progress.status);return this; };Utils.Progress.inc = function(amount){var progress = Utils.Progress,n = progress.status;if (!n) {return progress.start();}else{amount = (1 - n) * Utils.clamp(Math.random() * n, 0.1, 0.95);n = Utils.clamp(n + amount, 0, 0.994);return progress.set(n);} };Utils.Progress.trickle = function() {var progress = Utils.Progress;return progress.inc(Math.random() * progress.settings.trickleRate); };Utils.Progress.start = function(cb) {var progress = Utils.Progress;progress.cb = cb || Utils.noop;if (!progress.status) progress.set(0);var timer = function(){if (progress.status === 1) {clearTimeout(timer);timer = null;return;}progress.trickle();work();};var work = function() {setTimeout(timer, progress.settings.trickleSpeed);};if (progress.settings.trickle) work();return this; };Utils.Progress.done = function() {var progress = Utils.Progress;return progress.inc(0.3 + 0.5 * Math.random()).set(1); };LoaderLayer的定義
LoaderLayer是在加載的時(shí)候在當(dāng)前場景上面添加一個(gè)遮罩層,這里主要是ajax加載的,代碼如下:
Config.winSize = cc.size(720, 1134); Config.w = Config.winSize.width; Config.h = Config.winSize.height; Config.w_2 = Config.w / 2; Config.h_2 = Config.h / 2;var LoaderLayer = cc.LayerColor.extend({count: 0,ctor:function () {this._super(cc.color(0, 0, 0, 160));var draw = new cc.DrawNode();draw.x = Config.w_2 - 50;draw.y = 260;for(var i=0; i<3; i++){draw.drawRect(cc.p(40*i, 0), cc.p(40*i+20, 20), cc.color(181, 181, 181), 1, cc.color(181, 181, 181));}var draw2 = this.draw = new cc.DrawNode();draw2.x = Config.w_2 - 50;draw2.y = 260;draw2.drawRect(cc.p(0, 0), cc.p(20, 20), cc.color(239, 178, 82), 1, cc.color(239, 178, 82));this.addChild(draw);this.addChild(draw2);this.schedule(this.updateLoad, 0.2);return true;},updateLoad: function(){var draw = this.draw;draw.clear();if(this.count >3){this.count = 0;}for(var i=0; i< this.count; i++){draw.drawRect(cc.p(40*i, 0), cc.p(40*i+20, 20), cc.color(239, 178, 82), 1, cc.color(239, 178, 82));}this.count++;},onRemove: function(){var parent = this.parent;cc.eventManager.resumeTarget(parent,true);parent.resume();parent.removeChild(this, true);} });LoaderLayer.preload = function(url, data, cb, parent){var loader = cc.LoaderLayer;if(!loader) {loader = new LoaderLayer();}//parent.pause();cc.eventManager.pauseTarget(parent,true);parent.addChild(loader, 99);Utils.ajax({url: url,type: "POST",data: data,success: function(data){loader.onRemove();cb(data);},error: function(xhr, status, msg){loader.onRemove();alert(msg);}}); };使用也很簡單:
//這里默認(rèn)使用了ajax的post方法,parent一般都是this。 LoaderLayer.preload(url, data, cb, parent);?
H5離線緩存
HTML5離線存儲(chǔ)Application Cache可以讓用戶在離線狀態(tài)下瀏覽網(wǎng)站內(nèi)容,緩存之后的內(nèi)容不會(huì)再次從服務(wù)器獲取,除非緩存文件改變了。如何使用呢?這需要打開你的html文件在里面:
<!DOCTYPE html> <html lang="en" manifest="manifest.appcache"> <head>...?
接著在html文件的同級(jí)目錄下面新建manifest.appcache,并加入如下內(nèi)容:
//manifest.appcache CACHE MANIFEST# version 1.0 CACHE:css/main.cssimg/test.png NETWORK: *關(guān)于manifest.appcache文件,基本格式為三段: CACHE, NETWORK,與 FALLBACK,其中NETWORK和FALLBACK為可選項(xiàng),而第一行CACHE MANIFEST為固定格式,必須寫在前面。
CACHE是必須參數(shù),標(biāo)識(shí)出哪些文件需要緩存,可以是相對(duì)路徑也可以是絕對(duì)路徑
NETWORK是可選參數(shù),這一部分是要繞過緩存直接讀取的文件,可以使用通配符*,也就是說除了上面的cache文件,剩下的文件每次都要重新拉取。
FALLBACK也是可選參數(shù),指定了一個(gè)后備頁面,當(dāng)資源無法訪問時(shí),瀏覽器會(huì)使用該頁面。該段落的每條記錄都列出兩個(gè) URI—第一個(gè)表示資源,第二個(gè)表示后備頁面。兩個(gè) URI 都必須使用相對(duì)路徑并且與清單文件同源。可以使用通配符。
有了上面兩個(gè)文件之后還要配置服務(wù)器的mime.types類型,找大盤apache的mime.types文件,添加
text/cache-manifest .appcache上面文件配置完成之后,application cache就可以運(yùn)行了。
更新緩存的方式有三種:
可以修改一下manifest文件,把version改為1.1,然后刷新頁面。
js添加一個(gè)監(jiān)聽事件:
window.applicationCache.addEventListener('updateready', function() { console.log('updateready!'); window.applicationCache.swapCache(); });站點(diǎn)離線存儲(chǔ)的容量限制是5M;如果manifest文件,或者內(nèi)部列舉的某一個(gè)文件不能正常下載,整個(gè)更新過程將視為失敗,瀏覽器繼續(xù)全部使用老的緩存。
?
轉(zhuǎn)載于:https://www.cnblogs.com/guangyun/p/8421267.html
總結(jié)
以上是生活随笔為你收集整理的cocos2dx-js 开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: K_A12_022 基于STM32等单片
- 下一篇: java g1 配置_项目G1 jvm