日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

成语json_cocos creator实战(2)成语小秀才ts版

發布時間:2025/4/5 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 成语json_cocos creator实战(2)成语小秀才ts版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 分析

公司要求做h5小游戲之前,想要做的一款類似成語小秀才的小游戲。學了一段時間ccc后回頭填坑,嘗試仿制一波,剛好發現論壇有套開源的ui素材。花了兩天做的demo。做完后發現最難的是生成隨機關卡,由于益智類小游戲動輒幾百上千關,編寫較高質量的關卡隨機算法還是很有難度的。

  • 玩法:每個成語最多空缺兩個位置,選擇對應的詞填入成語中,全對即可過關。
成語小秀才

界面分三部分,頂部關卡信息、成語區、選詞區。

  • 成語區實際上是9*9的布局,共81的格子,只顯示了有詞的格子,開啟調試模式可以顯示所有的格子。
  • 選詞區顯示成語中空缺的詞
調試模式

2 代碼結構

2.1 關卡數據結構

正式上線的話,需要開發服務端用于返回關卡數據和保存用戶信息。客戶端通過http請求獲取關卡數據,同時可以上傳分數等信息。demo中沒有用到服務端,直接本地掛載關卡數據,關卡數據保存在json文件中。

id????--->?成語id,對應成語庫中的成語
grids?--->?保存成語中四個字的位置
???????????id?--->?所處的格子位置
???????????space?--->?該字是否為空缺
{
????"id":?4959,
????"grids":?[
????????{
????????????"id":?18,
????????????"space":?false
????????},
????????{
????????????"id":?27,
????????????"space":?true
????????},
????????{
????????????"id":?36,
????????????"space":?false
????????},
????????{
????????????"id":?45,
????????????"space":?true
????????}
????]
}

2.2 詞條數據對象

用一個類來描述成語詞條的基本數據,它對應詞庫中的一條成語。

//?IdiomData.ts
export?class?IdiomData?{
????public?id:?number?=?0;??????????//?詞條id
????public?chars:?string?=?null;????//?完整成語,例如"一馬當先"
????public?pinyin:?string?=?null;???//?詞條拼音
????public?note:?string?=?null;?????//?詞條出處和釋義
}

2.3 詞條對象

用一個類來描述關卡中出現的每一條成語對象。

  • 記錄占用的格子
  • 保存詞條數據對象
//?Idiom.ts
export?class?Idiom?{
????public?grids?=?[];??????//?記錄占用的格子
????public?data?=?null;?????//?詞條數據
????public?constructor(grids,?idiomdataObj)?{
????????this.data?=?idiomdataObj;
????????for?(let?i?=?0;?i?????????????this.grids.push(grids[i]);
????????}
????}
}

2.4 格子對象

用一個類來描述每個格子的狀態和行為。

  • 記錄格子id
  • 該格子使用狀態
  • 保存完整的成語數據
  • 格子上需要填寫的字符
  • 保存被哪些詞條對象使用
  • 格子是否為空缺狀態
  • 格子填詞是否成功,用來判斷填詞是否成功
  • 當前格子上的詞id
//?Grid.ts
????public?gridId:?number?=?0;??????????????????//?格子id
????public?isUsed:?boolean?=?false;?????????????//?是否是被使用的格子
????public?data:?string?=?null;?????????????????//?完整的成語
????public?char:?string?=?"";???????????????????//?使用的成語字符,單個字
????public?idioms?=?[];?????????????????????????//?反向保存idiom引用????這個是用來保存這個格子被哪些詞條引用
????public?isSpaceGrid:?boolean?=?false;????????//?是否是?被?去字?狀態
????public?isSelectMode:?boolean?=?false;???????//?是否是?填字?模式
????public?isSuccess:?boolean?=?false;??????????//?標注該位置詞?是否正確
????public?currentId:?number?=?0;???????????????//?記錄當前格子上?選詞?的id,用來判斷回退
????
????//?重置?格子數據,關卡切換復用
????public?resetGrid()?{
????????……
????}
????//?格子注冊監聽事件
????public?addListener(fn:?Function,?target)?{
????????this.node.on(cc.Node.EventType.TOUCH_END,?fn,?target);
????}
????//?格子移除監聽事件
????public?removeListener(fn:?Function,?target)?{
????????this.node.off(cc.Node.EventType.TOUCH_END,?fn,?target);
????}

2.5 關卡對象

用一個類來描述游戲關卡。關卡對象讀取關卡json文件,返回詞條對象數組。http請求獲取關卡數據可以放在這里。

//?Level.ts
????public?initLevelData()?{
????????let?idioms?=?this._levelData.json["idioms"];
????????let?idiomArr?=?[];
????????for?(let?i?=?0;?i?????????????let?_id?=?idioms[i].id
????????????let?idiomdataObj?=?new?IdiomData(this._jsonData.json[_id]);
????????????//?詞條對象?存詞條數據,占位
????????????let?idiomObj:?Idiom?=?new?Idiom(idioms[i].grids,?idiomdataObj);
????????????idiomArr.push(idiomObj);
????????}
????????return?idiomArr;
????}

3 界面設計

3.1 節點結構

節點結構

3.2 結算界面

展示詞條成語,提供下一關切換按鈕。

節點結構

3.3 詞條詳情界面

展示詞條拼音、釋義、出處。

詞條詳情

游戲邏輯

4.1 成語區

  • 制作一個格子的預制體,一次性創建81個格子對象。
格子預制體//?game.ts
????private?init()?{
????????//?9*9=81塊????rows?col
????????for?(let?index?=?0;?index?81;?index++)?{
????????????let?node?=?cc.instantiate(this.piece_prefab);
????????????node.parent?=?this.qipan;
????????????let?tile:?Grid?=?node.getComponent(Grid);
????????????tile.gridId?=?index;
????????????if?(!this.isDebug)?{
????????????????tile.hide();
????????????}
????????????this.tiles.push(tile);
????????}
????????……?……
????}
  • 遍歷成語對象后,給指定格子位置添加對應的成語字符并綁定數據。從成語對象中拿到成語,將每個成語都分割成單獨的字符存入數組中,將字符循環插入到格子中,如果該位置的格子為去字狀態,就把該位置的字符隱藏,并記錄空缺字符的id和字符用于初始化選詞區。
????????//?遍歷成語對象?
????????for?(let?i?=?0;?i?????????????let?chars?=?idiomArr[i].data.chars;
????????????let?grids?=?idiomArr[i].grids;
????????????//?分割拿到單獨的字符
????????????let?arr?=?chars.split("");
????????????for?(let?j?=?0;?j?????????????????let?gid?=?grids[j].id;
????????????????let?space?=?grids[j].space;
????????????????this.tiles[gid].bg.node.active?=?true;
????????????????this.tiles[gid].word.node.active?=?true;
????????????????//?設置?格子信息
????????????????this.tiles[gid].gridId?=?gid;
????????????????this.tiles[gid].char?=?arr[j];
????????????????this.tiles[gid].data?=?chars;
????????????????this.tiles[gid].idioms.push(idiomArr[i]);
????????????????//?判斷是否為?去字?狀態,如果是去字,那么就隱藏上面的word
????????????????if?(space)?{
????????????????????this.tiles[gid].isSpaceGrid?=?true;?????//?空格子
????????????????????if?(!this.tiles[gid].isSelectMode)?{????//?判斷?該空是否為選詞
????????????????????????this.tiles[gid].isSelectMode?=?true;
????????????????????????this.tiles[gid].bg.spriteFrame?=?this.word_tile;
????????????????????????//?添加點擊事件
????????????????????????this.tiles[gid].addListener(this.onSpaceGridClick,?this);
????????????????????????this.selectWords.push({"id":?gid,?"char":?arr[j]});
????????????????????}
????????????????}?else?{
????????????????????this.tiles[gid].word.string?=?arr[j];
????????????????????this.tiles[gid].bg.spriteFrame?=?this.word_normal;
????????????????}
????????????}
????????}
  • 空位置觸摸事件。空位置需要實現兩個功能:顯示字符和回退選詞區。
????????//?標注空位置上已經有詞??回退到選擇區
????????if?(grid.isUsed)?{
????????????let?char?=?grid.word.string;
????????????this.tiles[gridId].isUsed?=?false;
????????????this.tiles[gridId].word.string?=?"";
????????????this.tiles[gridId].isSuccess?=?false;
????????????this.tiles[gridId].bg.spriteFrame?=?this.word_selected;
????????????this.currentSelectGrid?=?gridId;
????????????let?currentid?=?grid.currentId;
????????????for?(let?i?=?0;?i?this.selectNode.length;?i++)?{
????????????????if?(this.selectNode[i].gridId?===?currentid)?{
????????????????????this.selectNode[i].node.getComponent(cc.Animation).play("show_word");
????????????????}
????????????}
????????}

4.2 選詞區

  • 復用格子預制體,遍歷記錄空缺字符的selectWordsArr數組里的數據。
選詞區????//?初始化選詞區
????private?initSelectGroup()?{
????????for?(let?s?=?0;?s?this.selectWords.length;?s++)?{
????????????let?gid?=?this.selectWords[s].id;
????????????let?char?=?this.selectWords[s].char;

????????????let?node?=?cc.instantiate(this.piece_prefab);
????????????node.parent?=?this.selectGroup;
????????????let?tile:?Grid?=?node.getComponent(Grid);
????????????tile.gridId?=?gid;
????????????tile.char?=?char;
????????????tile.word.string?=?char;
????????????tile.addListener(this.onSelectGridClick,?this);

????????????this.selectNode.push(tile);
????????}
????}
  • 為了可玩性,隨機打亂selectWordsArr里的數據,將選詞打亂。
????//?隨機打亂selectWords數組
????this.selectWords.sort(()?=>?{
????????return?Math.random()?>?0.5???-1?:?1;
????});
  • 選詞區觸摸回調,判斷選詞與空缺位置是否匹配,如果匹配將該格子的isSuccess設為true,表明該位置字符正確。這里判斷字符正確的依據不能通過比較id的方式,因為有可能選詞區出現若干個相同字符的格子,所以選擇任意一個都要能達到字符正確的效果。
????//?選詞?回調事件?--->?判斷與當前?選中位置?是否相符
????private?onSelectGridClick(e)?{
????????……?……
????????//?隱藏該選詞?
????????e.target.getComponent(cc.Animation).play("hide_word");
????????if?(this.tiles[this.currentSelectGrid].isUsed)?{
????????????let?char?=?this.tiles[this.currentSelectGrid].word.string;
????????????let?nowId?=?this.tiles[this.currentSelectGrid].currentId;
????????????this.selectNode[nowId].node.active?=?true;
????????????this.tiles[this.currentSelectGrid].word.string?=?grid.char;
????????}?else?{
????????????this.tiles[this.currentSelectGrid].word.string?=?grid.char;
????????????this.tiles[this.currentSelectGrid].isUsed?=?true;
????????????this.tiles[this.currentSelectGrid].bg.spriteFrame?=?this.word_finished;
????????????this.tiles[this.currentSelectGrid].currentId?=?gridId;
????????}
????????//?判斷是否填詞成功??通過比較字符的方式?gridId?===?this.currentSelectGrid
????????if?(char?===?this.tiles[this.currentSelectGrid].char)?{
????????????//?記錄該位置詞語正確
????????????this.tiles[this.currentSelectGrid].isSuccess?=?true;
????????}
????????this.judgeSuccess(this.currentSelectGrid);
????}

4.3 填詞邏輯

  • 每填一個詞都要判斷格子上綁定的成語是否填詞成功。找出空位置,然后判斷空位置上所有的isSuccess是否為true,滿足條件則播放填詞動畫,查找下一個空缺位置。
????//?判斷詞條成功
????private?judgeSuccess(gridId:?number)?{
????????……?……
????????if?(this.tiles[gridId].idioms.length?>?0)?{
????????????for?(let?i?=?0;?i?this.tiles[gridId].idioms.length;?i++)?{
????????????????let?idiom?=?this.tiles[gridId].idioms[i];
????????????????let?flag?=?true;
????????????????spaceArr?=?[];
????????????????//?遍歷去字?位置
????????????????for?(let?j?in?idiom.grids)?{
????????????????????let?id?=?idiom.grids[j].id;
????????????????????if?(idiom.grids[j].space?===?true)?{
????????????????????????spaceArr.push(id);
????????????????????}
????????????????}
????????????????//?判斷成功
????????????????for?(let?s?=?0;?s?????????????????????if?(this.tiles[spaceArr[s]].isSuccess?!==?true)?{
????????????????????????flag?=?false;
????????????????????}
????????????????}
????????????//?填詞動畫后,找下一個?空位置
????????????this.findNextSpaceGrid();
????????????……?……
????}

4.4 過關邏輯

  • 尋找下一個空位置。遍歷格子對象,篩選isSelectMode為true同時isUsed為false,也就是未被占用的格子。滿足條件的格子設置當前選中狀態即可。
尋找空位置????????for?(let?i?=?0;?i?this.tiles.length;?i++)?{
????????????if?(this.tiles[i].isSelectMode?&&?this.tiles[i].isUsed?===?false)?{
????????????????//?記錄選中的格子位置
????????????????this.currentSelectGrid?=?i;
????????????????this.tiles[i].bg.spriteFrame?=?this.word_selected;
????????????????return;
????????????}
????????}
  • 如果尋找下一個空位置失敗,那么說明不存在下一個空格子,就要判斷過關。
????????//?如果沒有下一個格子?就判斷是否過關
????????let?flag?=?true;
????????for?(let?sw?=?0;?sw?this.selectWords.length;?sw++)?{
????????????let?id?=?this.selectWords[sw].id;
????????????if?(this.tiles[id].isSuccess?!==?true)?{
????????????????flag?=?false;
????????????}
????????}
????????if?(flag)?{
????????????//?執行過關函數
????????????cc.log("過關");
????????????this.gameSuccess();
????????}

4.5 動畫效果

  • 選詞觸摸動畫,對照小秀才發現當選詞點擊時只需要把scale執行從1到0的動畫就可以達到同樣的效果。如果直接將active置false,layout的格子布局就會自動調整可見選詞區的位置,導致每個選詞的位置出現變化。
選詞觸摸動畫
  • 填詞動畫。對比發現,填詞正確動畫拆分看,每個位置的動畫都是一樣的,將格子進行快速縮放并設置不同的延遲,看上去有跳動的效果。
填詞動畫????//?填詞成功動畫
????private?fillGrid(grids,?arr)?{
????????for?(let?i?=?0;?i?????????????let?id?=?grids[i].id;
????????????this.tiles[id].isSelectMode?=?false;
????????????//?每個字延遲動畫
????????????setTimeout(()?=>?{
????????????????this.tiles[id].getComponent(cc.Animation).play("word_success");
????????????},?100?*?i);
????????}
????????for?(let?j?=?0;?j?????????????this.tiles[arr[j]].removeListener(null,?this);
????????}
????}

4.6 詞條成功邏輯

  • 判斷詞條中空位置格子是否都正確,如果正確就執行填詞動畫,查找下一個空位。如果沒有空位置且填詞全都正確,則說明過關,展示結算界面。
結算界面
  • 詞條詳情界面,顯示拼音、釋義、出處。
詞條詳情

5 演示

demo完整演示

6 總結

  • 項目開始前把結構劃分清除,每個模塊之間的聯系都確定好,可以提高開發效率。
  • 第一次仿制游戲,得益于有完整的ui素材,論壇也有類似的帖子介紹。拿這類的小游戲練手對提高學習信心很有幫助。
  • 關于隨機關卡,跟壇友交流過,隨機生成的成語質量無法保證,也就是有可能生僻詞混搭,能實現但體驗會變差。還有另一種手動標注成語,人工干預的方式去生成關卡。隨機關卡思路是有了,但是具體沒實現,暫時用不上。什么時候有心情做了再發出來。
  • 使用cocos creator2.3.2版本,typescript語言

總結

以上是生活随笔為你收集整理的成语json_cocos creator实战(2)成语小秀才ts版的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。