來來來,一文讓你讀懂Cocos Creator如何讀寫JSON文件
前言
在游戲開發(fā)過程中,讀取配置文件是必不可少的,而使用JSON做配置文件又比較常見,本文重點(diǎn)給大家講述如何在Cocos Creator開發(fā)中讀取和解析JSON數(shù)據(jù)文件以及如何寫JSON文件。
一、JSON簡(jiǎn)介
1. 什么是JSON
JSON的英文全稱是JavaScript Object Notation,即JavaScript對(duì)象表示法。
2. JSON的特點(diǎn)
是一種輕量級(jí)的文本數(shù)據(jù)交換格式,類似XML,但是比XML更小、更快、更易解析。使用JavaScript語法來描述數(shù)據(jù)對(duì)象,JS程序無需解析器即可生成原生的JavaScript對(duì)象。獨(dú)立于語言和平臺(tái),目前大多數(shù)的編程語言都支持JSON。
3. JSON的語法
JSON語法是JavaScript語法的子集,具有以下規(guī)則:
數(shù)據(jù)在名稱/值對(duì)中
數(shù)據(jù)由逗號(hào)分隔
大括號(hào)保存對(duì)象
中括號(hào)保存數(shù)組
二、如何解析JSON文件
1. 關(guān)鍵原則
大括號(hào)代表對(duì)象,中括號(hào)代表數(shù)組;
2. 用什么方法讀?。?/h1>
Cocos Creator提供了cc.load.loadRes來專門加載位于 resources 目錄下的文件,所以提前把JSON文件放到 asserts/resources 目錄下即可。先來一個(gè)簡(jiǎn)單的JSON文件,如下:
1. ?`// box2dDemo.json`2. ?`{`3. ?`"engine": "Box2D",`4. ?`"version": "2.3.1"`5. ?`}`
讀取/解析代碼如下:
1. ?`cc.loader.loadRes('box2dDemo.json', function(err, object) {`2. ?`if(err) {`3. ?`console.log(err);`4. ?`return;`5. ?`}`6. ?`// 讀取的數(shù)據(jù)返回在object中,這是一個(gè)擁有2個(gè)元素的對(duì)象`7. ?`let engine = object.engine; // engine = box2D`8. ?`let ver = object.version; // ver = 2.3.1`9. ?`});`
是不是很簡(jiǎn)單?實(shí)際使用的JSON配置常常比這復(fù)雜一些,所以我們現(xiàn)在再給JSON文件增加一些元素,如下:
1. ?`// box2dDemo.json`2. ?`{`3. ?`"engine": "Box2D",`4. ?`"version": "2.3.1",`5. ?`"bodies":`6. ?`[`7. ?`{`8. ?`"name": "root",`9. ?`"body":`10. ?`{`11. ?`"type": "static",`12. ?`"gravityScale": 0.2`13. ?`}`14. ?`},`15. ?`{`16. ?`"name": "aa1",`17. ?`"body":`18. ?`{`19. ?`"type": "static",`20. ?`"gravityScale": 0.2`21. ?`}`22. ?`}`23. ?`],`24. ?`"joints":`25. ?`[`26. ?`{`27. ?`"bodyA": "root",`28. ?`"bodyB": "aa1",`29. ?`"lowerAngle": 0.5,`30. ?`"enableLimit": true`31. ?`},`32. ?`{`33. ?`"bodyA": "aa1",`34. ?`"bodyB": "aa2",`35. ?`"lowerAngle": -0.5,`36. ?`"enableLimit": true`37. ?`}`38. ?`]`39. ?`}`
我們?cè)诖a中定義一個(gè)解析函數(shù)叫 readJson,并且把解析出來的JSON數(shù)據(jù)保存起來,實(shí)現(xiàn)代碼如下:
1. ?`readJson: function() {`2. ?`this.box2d = {}; // 存儲(chǔ)解析出來的JSON數(shù)據(jù)`3. ?`varself= this;`4. ?`cc.loader.loadRes('box2dDemo.json', function(err, object) {`5. ?`if(err) {`6. ?`console.log(err);`7. ?`return;`8. ?`}`9. ?`let engine = object.engine; // engine = box2D`10. ?`let ver = object.version; // ver = 2.3.1`11. ?`let bodies = object.bodies; // bodies是個(gè)數(shù)組`12. ?`let joints = object.joints; // joints是個(gè)數(shù)組`13. ?`// 需在回調(diào)外面提前用self代替this`14. ?`self.box2d = object; // box2d是整個(gè)對(duì)象`15. ?`// 將循環(huán)2次,因?yàn)閎odies是個(gè)擁有2個(gè)對(duì)象的數(shù)組`16. ?`for(let x=0; x < bodies.length; x++) {`17. ?`let root = bodies[x]; // root是個(gè)對(duì)象`18. ?`let root_name = root.name; // 第1次循環(huán)root_name = root`19. ?`let type = root.body.type; // type = static`20. ?`let gravity = root.body.gravityScale; // gravity = 0.2`21. ?`}`22. ?`});`23. ?`},`
3. Cocos Creator讀取JSON文件注意事項(xiàng)
creator讀取json文件的一個(gè)坑(對(duì)文本內(nèi)容進(jìn)行操作可能導(dǎo)致的錯(cuò)誤) 使用creator中的 cc.loader.loadRes( url, cc.RawAsset, ( err, res )=>{ } )讀取游戲文件后發(fā)現(xiàn)第二次進(jìn)入游戲出現(xiàn)了錯(cuò)誤。現(xiàn)對(duì)這個(gè)問題總結(jié)下:對(duì)于動(dòng)態(tài)加載資源,第二次讀取會(huì)直接從緩存中讀取,所以如果讀取的是一個(gè)文本數(shù)據(jù),對(duì)文本數(shù)據(jù)修改了,那么相應(yīng)的,在下一次讀取數(shù)據(jù)會(huì)讀取修改后的文本數(shù)據(jù)。比如文本數(shù)據(jù)就一個(gè)數(shù)組[1,2,3],第一次讀取之后刪除了最后一位數(shù)據(jù)變?yōu)闉閇1,2],那么下一次讀取將會(huì)是[1,2]。為了不出現(xiàn)這種情況,可以對(duì)數(shù)據(jù)進(jìn)行序列化與反序列化操作,將其深度拷貝后使用。
4. JSON讀取通用代碼示例
1. ?`cc.loader.load(cc.url.raw('resources/data.json'), function(err,res){`2. ?`if(err) {`3. ?`cc.log(err);`4. ?`}else{`5. ?`let list=res;`6. ?`cc.log("load:");`7. ?`cc.log("list:"+list.name);`8. ?`}`9. ?`});`10. ?`// louadRes()方法,默認(rèn)路徑就是resources`11. ?`cc.loader.loadRes('data', function(err,res){`12. ?`if(err) {`13. ?`cc.log(err);`14. ?`}else{`15. ?`let list=res;`16. ?`cc.log("loadRes:");`17. ?`cc.log("list:"+list.sex);`18. ?`}`19. ?`});`
注意:當(dāng)使用以上代碼還報(bào)文件不存在或Download text failed的錯(cuò),那就要檢查下資源管理器里是不是有兩個(gè)resources文件夾,其中一個(gè)是最近新建的,另一個(gè)可能是以前新建的但是被刪除過,但是刪除不徹底,因?yàn)閏ocos creator里面的資源都是有一個(gè)唯一標(biāo)識(shí)的uuid,所以,還必須找到E:\Projects\你的項(xiàng)目\library\uuid-to-mtime.json這個(gè)文件,在里面找到之前的resources文件uuid,先剪切放到文本文件,然后保存uuid-to-mtime.json,重啟軟件,看是否能進(jìn)去,不能的話再把剪切出來的uuid復(fù)制回去,再重啟就可以了。
三、Json文件的寫入
1. ?`// writeToFile()寫入數(shù)據(jù)到文件,存儲(chǔ)格式為xml,不是Json格式`2. ?`if(cc.sys.isNative) {`3. ?`cc.log("Path:"+jsb.fileUtils.getWritablePath()); ? ?cc.log( jsb.fileUtils.writeToFile({"new":"value"},jsb.fileUtils.getWritablePath()+'data.json'));`4. ?`cc.log("fullPathForFilename:"+jsb.fileUtils.fullPathForFilename("resources/data.json"));`5. ?`}`6. ?`// writeStringToFile()寫入數(shù)據(jù)到文件,存儲(chǔ)格式為json,讀取數(shù)據(jù)用load()方法`7. ?`cc.log("writeStringToFile:"+jsb.fileUtils.writeStringToFile('{"a":"b","c":"d"}', jsb.fileUtils.getWritablePath()+'kk.json'));`8. ?`cc.log("getValueMapFromFile:"+JSON.stringify(jsb.fileUtils.getValueMapFromFile(jsb.fileUtils.getWritablePath()+"kk.json")));`
? ?`var`9. ?`arry=JSON.stringify(jsb.fileUtils.getStringFromFile(jsb.fileUtils.getWritablePath()+"kk.json"));`10. ?`cc.log("arry:"+arry);`11. ?`cc.loader.load(jsb.fileUtils.getWritablePath()+"kk.json", function(err,res){`12. ?`if(err) {`13. ?`cc.log(err);`14. ?`}else{`15. ?`let list=res;`16. ?`cc.log("list:"+list.a);`17. ?`}`18. ?`});`