寫一個狼吃羊的小遊戲

其實在2016年,我就準備寫這個小遊戲了。但是奈何當時沒文化😌,也還沒有轉行成前端。既沒有面向對象的思想,也不懂什麼尋徑算法,更不瞭解模塊化,只是掌握了canvas的基本知識。所以以當時的水平,就搞了一段時間後,把羊,狼,磚塊畫了出來,具體怎麼運動?搞不下去,就擱置下來了。時間飛逝,這個小遊戲就這麼靜靜地爛尾了兩年多,直到前幾天,在codepen上看到了一個尋徑的demo,才又重新撿起來。

現在再撿起來,感覺得心應手應手了許多,儘管中間也碰到了一些坑,但不至於無從下手。儘管還有許多可以改進的地方,代碼寫的也不怎麼規範,斷斷續續搞了一週多,好歹搞出來一個能用的版本。下面說說開發過程中遇到的一些問題,和學到的知識。

這裏是試玩地址:https://www.imgss.top/demo/wAs/
github: https://github.com/imgss/wAs

一 devicePixelRatio

在手機上打開這個小遊戲時,遊戲畫面會變得比較模糊,這是由於手機屏幕的css尺寸和真實的物理像素數量是不一樣的。這也是window.devicePixelRatio這個屬性存在的意義。同時canvas的css寬度和canvas本身的寬度也是這個區別。舉個例子:

一個手機的 devicePixelRatio 是3,canvas的css寬度是500px,要想使canvas繪製出的圖片不模糊,需要給canvas的寬度設置成多少?答案是500 * 3 = 1500。寫成代碼是:

    var ratio = window.devicePixelRatio;

    var oldWidth = canvas.width;
    var oldHeight = canvas.height;
    
    canvas.width = oldWidth * ratio; //根據radio設置新的width,解決圖片模糊問題
    canvas.height = oldHeight * ratio;
    canvas.style.width = oldWidth + "px";
    canvas.style.height = oldHeight + "px";//使canvas在屏幕上的顯示和之前保持一致

二 尋徑算法

這也是整個遊戲最難的地方,遊戲中羊是在不斷運動的,狼需要根據羊當前的位置計算出行動路徑。在實現中,我參考了codepen上的這個demo,具體的思路是,用一個二維數組來表示整張地圖,從目標節點(羊的位置)開始,向上下左右遍歷,如果碰到牆或者邊界就停止,並標記爲訪問過。再根據這些節點的兄弟節點進行遍歷,直到找到狼所在的位置,或者整個地圖全部搜索了一遍。

當在遍歷中找到狼的位置後,進行一次回溯,就拿到了狼的運動路徑。

整個算法在search.js中,是根據上面的那個demo修改的,實現了一個pathFinder類;

export default class Pathfinder{
  constructor(gridData, targetPosition, foundCallback) {
    this.gridData = gridData;
    this.targetPosition = targetPosition;

    this.foundCallback = foundCallback;
    this.width = this.gridData[0].length;
    this.height = this.gridData.length;
  }
  // 將二維地圖轉換成節點數據
  parseGridData() {
   ...
  }

瞭解更多的尋徑算法知識可以看這篇文章: https://www.redblobgames.com/pathfinding/a-star/introduction.html

三 一個有用的庫

在開發過程中發現手機端的操作不是很流暢,找到了一個叫nipplejs的虛擬搖桿的庫。使用方法也很簡單,虛擬搖桿可以是固定在屏幕的某個地方,也可以是顯示在屏幕的任何一個地方。但是在實際中使用發現,用搖桿操作,很容易導致羊多跑或者少跑一兩格,對於這個遊戲來說,不如箭頭控制精度好,最終還是放棄了。

遊戲裏還用到一個sweetalert庫,用來做彈出框的,沒有依賴,用起來很方便(其實是做不出酷炫的彈窗特效)。

後記

整個過程中,加深了自己對算法重要性的認識,雖然前端很少涉及高深的算法,但是多懂一點算法知識絕對大有裨益。小遊戲中還有許多值得優化的地方,也還有幾個bug,這些以後再慢慢優化吧。(完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章