(最近設計模式看的有點頭大,一直面對純js實在是有些枯燥-_-。所以寫一點有趣的東西調劑一下)
現在canvas已經不算新鮮了,但由於日常業務中並不常用,所以實踐並不多,今天分享一下,如何實現簡單canvas迷宮。這個範例來自《html5秘籍》第二版,程式碼有稍微做了點調整。
由於中間有一步使用canvas取得圖片資訊的時候,必須使用伺服器環境。所以我先寫了一個範例丟在伺服器上,大家可以先體驗一下效果(用成就感當驅動力哈哈哈)
點我體驗
git位址
正文要實現這個小遊戲也不難,讓我們想想,一個迷宮遊戲有哪些基本要素。
首先當然得有個地圖,然後得有個移動的小人,這兩個我們利用cavans來繪製;
接下來是物體移動的程序,這個程序主要包括2個面向:
1.讓物體跟著我們指定的指令來移動;
2.偵測物體是否碰到牆體或出口。
繪製迷宮的地圖和移動的小人
繪製地圖的主要步驟是:
迷宮地圖的生成,可以藉助谷歌的迷宮線上生成器來獲得。
畫小人也是一樣直接找一個小人的圖片即可,不過這裡要注意的是,要找正方形的圖片,因為一會我們需要做移動的碰撞檢測,方形比較好判斷。
接下來就要寫繪製迷宮和小人的主要函數
function drawMaze(mazeFile, startingX, startingY) { var imgMaze = new Image() imgMaze.onload = function () { // 畫布大小調整canvas.width = imgMaze.width canvas.height = imgMaze.height // 繪製笑臉= document.getElementById(face) context.drawImage(imgMaze, 0, 0) x = startingX y = startingY context.drawImage(imgFace, x, y) context.stroke() } imgMaze.src = mazeFile}
mazeFile是迷宮的圖片位址,startingX和startingY,是起始點的座標。這裡圖片引入的方式用了2種,原因是小人的圖片我不常更換,就直接寫在頁面裡,迷宮的地圖打算做成可變的,所以在js裡引入,你想把圖片都直接用js引入也沒問題。其他部分比較簡單,不再贅述。
移動函數移動的主要原理是:
接受指定的使用者輸入(這裡是回應方向鍵),轉換成對應的移動指令。然後週期性的檢查移動指令,繪製對應的目標位置。舉個簡單的例子:
例如每按下一次方向鍵上,就記錄下應該往上移動,然後每隔100毫秒檢查當前的移動指令,繪製應該移動的目標地點,重複這個過程。程式碼也比較簡單:
// 移動函數function processKey(e) { dx = 0 dy = 0 // 上下左右方向鍵檢測if (e.keyCode === 38) { dy = -1 } if (e.keyCode === 40) { dy = 1 } if (e.keyCode === 37) { dx = -1 } if (e.keyCode === 39) { dx = 1 }}// 繪製幀function drawFrame() { if (dx != 0 || dy != 0) { // context.clearRect(x,y,canvas.width,canvas.height) // 繪製移動軌跡context. beginPath(); context.fillStyle = rgb(254,244,207) context.rect(x, y, 15, 15) context.fill() x += dx y += dy // 碰撞檢測if (checkForCollision()) { x -= dx y -= dy dx = 0 dy = 0 } //繪製小人應該移動的地點var imgFace = document.getElementById('face') context.drawImage(imgFace, x, y) if (canvas.height - y < 17) { // isFirst = false alert('恭喜你通關遊戲結束') return false } // 這裡如果重置的話變成非自動移動,也就是每按下一次方向鍵只前進一步,由於目前體驗不好所以先不做重設// dx = 0 // dy = 0 } setTimeout(drawFrame, 20)}
上述程式碼中,移動函數比較簡單,繪製幀的函數裡面比較重要的就是碰撞偵測函數,在下面詳細解釋。
碰撞偵測要偵測物體與牆體是否碰撞,通常情況是要先把地圖資訊儲存到記憶體裡,然後在移動物體時偵測是否與目前的某個牆體碰撞,但是由於我們的地圖背景是黑白迷宮,所以可以使用顏色來偵測碰撞。具體的做法是:
取得目前物體的座標位置,利用canvas偵測目前地圖上這個位置的顏色是否為黑色,如果是,說是牆體,不應該執行移動,以下就是程式碼:
function checkForCollision() { var imageData = context.getImageData(x - 1, y - 1, 15 + 2, 15 + 2) var pixels = imageData.data for (var i = 0, len = pixels.length; i < len ; i++) { var red = pixels[i], green = pixels[i + 1] blue = pixels[i + 2] alpha = pixels[i + 3] // 偵測是否碰到黑色的牆if (red === 0 && green === 0 && blue === 0) { return true } } return false}
在這裡,15是小人的寬度,我們偵測小人兩側各1px範圍(對應程式碼中的getImageData(x - 1, y - 1, 15 + 2, 15 + 2)可以稍微思考下這裡為什麼是+ 2),如果是黑色,表示偵測到碰撞。
其餘在程式碼裡,我加了一些其他的功能,像是提示答案等。至於更換地圖也比較簡單:把地圖對應的檔案位址,起點座標,答案圖片路徑等存在一個物件裡,然後設定一個地圖數組,點擊的時候切換地圖並重新渲染就可以了。還有一些值得優化的地方,例如:
有興趣的同學可以試著自己實現。
小結這個例子相對比較簡單,對js的要求不高,拿來玩一下還是挺不錯的。
然後依然是每次都一樣的結尾,如果內容有錯誤的地方歡迎指出;如果對你有幫助,歡迎點讚和收藏,轉載請徵得同意後著明出處,如果有問題也歡迎私信交流,主頁有郵筒地址~溜了
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。