這篇文章的內容是關於如何利用原生的 JavaScript來實現一個簡單的拼圖小遊戲,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。
一、遊戲的基礎邏輯
想用語言來開發遊戲,必須先了解如何使用這門語言來實現一些基礎邏輯,例如圖像的繪製、互動的處理、定時器等。
圖形繪製是一切的基礎,這裡使用 JavaScript
在 canvas
# 上繪製。也就是先在 html
中建立 canvas
元素,然後在 JavaScript
中,透過id 拿到這個元素,並且透過 canvas
# 拿到對應的情境環境 context
,為後續的繪圖做好準備。
<canvas id="background" width="450px" height="450px"></canvas>
var background = document.getElementById("background"); var context = background.getContext('2d');
透過 context
的 drawImage
方法可以繪製圖片,這裡進行了對應的封裝:
註:這裡要等圖片載入完畢後再繪製,也就是在 onload
中去呼叫 drawImage
方法,否則會繪製失敗。
var drawImageItem = function(index, position) { var img = new Image(); img.src = './image/dog_0' + String(index+1) + '.jpg'; img.onload = () => { var rect = rectForPosition(position); context.drawImage(img, rect[0], rect[1], rect[2], rect[3]); } }
在繪製圖片之後,我們還要去動態刷新視圖,否則 canvas
就只是一張靜態的圖片。如果是簡單的圖形刷新,只需在原來的位置重新繪製,進行覆蓋即可。但有時候我們只需要將原來已存在的圖形清除掉,而不需要繪製新圖案。例如在拼圖遊戲中,將一個方塊移到另一個位置後,就需要清空原來的位置。
透過 context
的 clearRect
方法可以達到清除的目的。以下是清除 canvas
的某個區域的程式碼:
var originRect = rectForPosition(origin); context.clearRect(originRect[0], originRect[1], originRect[2], originRect[3]);
有了圖形的繪製後,我們還需要處理玩家的輸入事件,然後根據輸入事件,來決定什麼時候要刷新視圖。輸入事件可分為 3 種:在手機上有觸控螢幕事件;在 PC 上,有滑鼠和鍵盤事件。
JavaScript
中對觸控螢幕和滑鼠點擊的監聽是一樣的,都是透過 canvas
的 onclick
事件進行回調,如下:
// 屏幕点击 background.onclick = function(e) { };
我們可以透過 e.offsetX
、 e.offsetY
來取得觸控點在 canvas
中的位置。
註: canvas
的座標原點在左上角,即左上角的座標是 (0, 0)
。
鍵盤的按鍵點選則是透過 document
的 onkeyup
、 onkeydown
等事件回呼。 onkeyup
是指按鍵的抬起事件, onkeydown
是指按鍵的按下事件。我們可以透過 keyCode
知道目前具體是哪一個按鍵,然後根據不同的按鍵去處理不同的邏輯,如下:
if (event.keyCode == '37') { // 左 // do something } else if (event.keyCode == '38') { // 上 // do something } else if (event.keyCode == '39') { // 右 // do something } else if (event.keyCode == '40') { // 下 // do something }
#有時候,除了在玩家輸入的時候需要去刷新視圖,還需要每隔一段時間定時去刷新視圖。例如在一個貪吃蛇遊戲中,就需要每隔一段時間就去刷新蛇的位置。
這個時候我們就需要一個計時器,讓它每隔一段時間去執行一段刷新視圖的程式碼。我們透過 setInterval
方法來實現計時器功能:
setInterval("run()", 100);
上面這段程式碼表示每隔 100 毫秒,去執行一次 run
方法。
有了遊戲的基礎邏輯,以下來看如何實現拼圖的邏輯。
因為不是任意序列都可以透過平移的方式來還原,所以我們不能簡單地產生一個隨機序列。例如 1、0、2、3、4、5、6、7、8
這個序列,無論怎麼平移,都不可能還原。
這裡採取的做法是:預先設定了 4 個可還原的序列,先從這 4 個序列中隨機選取一個,然後再對序列進行模擬平移若干步驟。以此來盡可能地確保初始序列的多樣性,也保證了序列的可還原性。具體代碼如下:
var setupRandomPosition = function() { var list1 = [4, 3, 2, 8, 0, 7, 5, 6, 1]; var list2 = [2, 0, 5, 6, 8, 7, 3, 1, 4]; var list3 = [3, 7, 2, 4, 1, 6, 8, 0, 5]; var list4 = [3, 2, 4, 1, 7, 6, 5, 0, 8]; var lists = [list1, list2, list3, list4]; imageIndexForPosition = lists[parseInt(Math.random() * 4)]; // 获取空位位置 var emptyPosition = 0; for (var i = imageIndexForPosition.length - 1; i >= 0; i--) { if (imageIndexForPosition[i] == lastIndex()) { emptyPosition = i; break; } } background.emptyPosition = emptyPosition; // 随机移动次数 var times = 10; while (times--) { // 获取随机数,决定空位哪个位置进行移动 var direction = parseInt(Math.random() * 4); var target = -1; if (direction == 0) { target = topOfPosition(emptyPosition); // 上 } else if (direction == 1) { target = leftOfPosition(emptyPosition); // 左 } else if (direction == 2) { target = rightOfPosition(emptyPosition); // 右 } else if (direction == 3) { target = bottomOfPosition(emptyPosition); // 下 } if (target < 0 || target > lastIndex()) { // 位置不合法,继续下一次循环 continue; } var result = moveImageIfCanAtPosition(target); if (result >= 0) { // 如果移动成功,更新空位的位置 emptyPosition = target; } } }
在保存順序的時候,是用0~8 這9 個數字來保存,而空白的方塊是數字8 的位置。所以判斷可以移動的唯一條件是,目標位置的值是否為 8。程式碼如下:
var isPositionEmpty = function(position) { if (position < 0 || position > lastIndex()) { return false; } if (imageIndexForPosition[position] == lastIndex()) { return true; } else { return false; } }
上面 lastIndex()
的值為 8。
方塊移動的實作很簡單,先將舊位置的圖形清除,然後在新的位置繪製。
var refreshImagePositions = function(origin, target) { var originRect = rectForPosition(origin); context.clearRect(originRect[0], originRect[1], originRect[2], originRect[3]); drawImageItem(imageIndexForPosition[target], target); }
檢查圖案是否已經還原,只需要對陣列進行一次遍歷,看是否有序即可。
var checkIfFinish = function() { for (var index = 0; index < imageIndexForPosition.length; index++) { if (index != imageIndexForPosition[index]) { return false; } } return true; }
当图案还原之后,我们不希望玩家还能通过键盘或鼠标来移动方块,这个时候就需要对交互事件进行屏蔽。
只需要一个标志位就可以达到这个目的:
// 屏幕点击 background.onclick = function(e) { if (isFinish) { return; } // do something }; // 键盘按钮事件 document.onkeyup = function(event) { if (isFinish) { return; } // do something }
当图案还原之后,标志位 isFinish 会被置为 true ,然后在屏幕点击和键盘按钮响应事件的开始处添加判断,如果已经结束,则不继续走方块移动的逻辑。
以上是如何利用原生的JavaScript來實作一個簡單的拼圖小遊戲的詳細內容。更多資訊請關注PHP中文網其他相關文章!