The content of this article is about how to use native JavaScript to implement a simple puzzle game. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you. .
1. Basic logic of the game
If you want to use a language to develop games, you must first understand how to use this language to implement some basic logic, such as images. Drawing, interactive processing, timers, etc.
Graphic drawing is the basis of everything. Here we use JavaScript
to draw on canvas
. That is, first create the canvas
element in html
, and then in JavaScript
, get this element through the id, and get it through canvas
The corresponding context environment context
is prepared for subsequent drawing.
<canvas id="background" width="450px" height="450px"></canvas>
var background = document.getElementById("background"); var context = background.getContext('2d');
Pictures can be drawn through the drawImage
method of context
. The corresponding encapsulation is carried out here:
Note: here To wait for the image to be loaded before drawing, that is, call the drawImage
method in onload
, otherwise the drawing will fail.
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]); } }
After drawing the picture, we still need to dynamically refresh the view, otherwise canvas
is just a static picture. If it is a simple graphics refresh, just redraw it at the original position and overwrite it. But sometimes we just need to clear the existing graphics without drawing new ones. For example, in a jigsaw puzzle, after moving a block to another position, the original position needs to be cleared.
The purpose of clearing can be achieved through the clearRect
method of context
. The following is the code to clear a certain area of canvas
:
var originRect = rectForPosition(origin); context.clearRect(originRect[0], originRect[1], originRect[2], originRect[3]);
After drawing the graphics, we also need to process the player's input event. Then decide when to refresh the view based on the input event. Input events can be divided into three types: touch screen events on mobile phones; mouse and keyboard events on PCs. The monitoring of touch screen and mouse clicks in
JavaScript
is the same, both are called back through the onclick
event of canvas
, as follows :
// 屏幕点击 background.onclick = function(e) { };
We can get the position of the touch point in canvas
through e.offsetX
and e.offsetY
.
Note: The coordinate origin of canvas
is in the upper left corner, that is, the coordinate of the upper left corner is (0, 0)
.
Keyboard key clicks are called back through events such as onkeyup
and onkeydown
of document
. onkeyup
refers to the key lift event, onkeydown
refers to the key press event. We can know which key is currently pressed through keyCode
, and then process different logic according to different keys, as follows:
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 }
Sometimes , in addition to the need to refresh the view when the player inputs, the view also needs to be refreshed regularly at regular intervals. For example, in a snake game, the snake's position needs to be refreshed every once in a while.
At this time we need a timer to execute a piece of code that refreshes the view every once in a while. We implement the timer function through the setInterval
method:
setInterval("run()", 100);
The above code means that the run
method is executed every 100 milliseconds.
With the basic logic of the game, let’s take a look at how to implement the logic of the puzzle.
Because not any sequence can be restored by translation, we cannot simply generate a random sequence. For example, the sequence 1, 0, 2, 3, 4, 5, 6, 7, 8
cannot be restored no matter how you translate it.
The method adopted here is: 4 reducible sequences are preset, one is randomly selected from these 4 sequences, and then the sequence is simulated and translated for several steps. This is done to ensure the diversity of the initial sequence as much as possible and the reducibility of the sequence. The specific code is as follows:
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; } } }
When saving the order, 9 numbers from 0 to 8 are used to save it, and the blank square is the number 8 Location. So the only condition to judge whether it can be moved is whether the value of the target position is 8. The code is as follows:
var isPositionEmpty = function(position) { if (position < 0 || position > lastIndex()) { return false; } if (imageIndexForPosition[position] == lastIndex()) { return true; } else { return false; } }
The value of lastIndex()
above is 8.
The implementation of block movement is very simple. First clear the graphics at the old position, and then draw at the new position.
var refreshImagePositions = function(origin, target) { var originRect = rectForPosition(origin); context.clearRect(originRect[0], originRect[1], originRect[2], originRect[3]); drawImageItem(imageIndexForPosition[target], target); }
To check whether the pattern has been restored, you only need to traverse the array once to see if it is in order.
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 ,然后在屏幕点击和键盘按钮响应事件的开始处添加判断,如果已经结束,则不继续走方块移动的逻辑。
The above is the detailed content of How to use native JavaScript to implement a simple puzzle game. For more information, please follow other related articles on the PHP Chinese website!