Collisions are very common situations and appear everywhere in the video game world. In the Mario Bros. game series, Mario heads his head in the tile box to break that box or gets a reward item. Or in the homegrown Flappy Bird game, when the bird hits the sewer, the game will end.
In order for such events to occur, game makers need to develop mechanisms to detect collisions between objects in the game, from the characters, to the flight path of bullets, terrain, …
It sounds simple, but this is a problem in game design, especially in complex 3D games with many objects. Perhaps when playing games, you sometimes encounter errors such as being stuck to the wall, going through the wall, getting stuck in the corner and falling out of the world, … the high probability of the responsibility belongs to the detection mechanism. The game’s collision did not work correctly
In this article, I would like to share with you to learn and develop the collision detection feature for the simple 2D game Tetris which is still in progress in the previous article, and thereby have an overview of the playback mechanism. show video collisions in general.
Idea
In Tetris game, the cubes (Tetromino) will be changed position after each game tick or when the player presses the scroll key or rotate the block. Thus, we simply need to check that, with each Tetromino block being relocated, it is overwritten on any other element . Specifically, we must perform each check step between Tetromino blocks and the elements:
- Bottom line,
- The left border,
- Right border,
- And with the Tetromino blocks have “landed”.
And luckily, in the Tetris game, the currently falling Tetromino block is the only thing that moves . If it is another game with many moving elements in the game (players, enemies, NPCs, bullets, etc.), you will have to check the collision between all of them and against the standing object. Other yen. Imagine a complex game with an extremely wide environment and thousands of different elements. Not to mention, the game has to render continuously with a frame number of 60FPS (different from Tetris which is nearly 1 second to pass 1 tick). Obviously this is not a simple thing.
With this problem, there are many different methods to optimize performance, but it is outside the framework of this article, and making games is not my specialty (the life has rushed into making the Web. ). If you are passionate about writing games, do not be shy to pursue and learn more
Proceed
There are a total of 4 actions that we need to check for collisions: blocks move down, blocks move left / right and blocks rotate.
Catch key press events
First of all, I will add a function that listens for key-press events, helping users control the game:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | window <span class="token punctuation">.</span> <span class="token function">addEventListener</span> <span class="token punctuation">(</span> <span class="token string">'keydown'</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> event <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span> event <span class="token punctuation">.</span> keyCode <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token number">37</span> <span class="token punctuation">:</span> <span class="token comment">// Left</span> game <span class="token punctuation">.</span> <span class="token function">tryMoveLeft</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">break</span> <span class="token keyword">case</span> <span class="token number">38</span> <span class="token punctuation">:</span> <span class="token comment">// Up</span> game <span class="token punctuation">.</span> <span class="token function">tryRotating</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">break</span> <span class="token keyword">case</span> <span class="token number">39</span> <span class="token punctuation">:</span> <span class="token comment">// Right</span> game <span class="token punctuation">.</span> <span class="token function">tryMoveRight</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">break</span> <span class="token keyword">case</span> <span class="token number">40</span> <span class="token punctuation">:</span> <span class="token comment">// Down</span> game <span class="token punctuation">.</span> <span class="token function">tryMoveDown</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">break</span> <span class="token punctuation">}</span> |
The functions tryMoveLeft()
, tryRotating()
, tryMoveRight()
, tryMoveDown()
will be implemented later in this article.
Move down
Tetromino blocks move down after each game tick (0.8 seconds), or when users accelerate the game by pressing the down arrow button. In this action, we need to check the collision between Tetromino block and 2 elements: lower boundary and landed blocks . To do this, I choose the following way:
- Every 0.8 seconds or when the user presses arrow down, executes the
progress()
function. - In
progress()
, I proceed to do the following:- Instead of updating the
currentTetromino
immediately, I create a temporary Tetromino object, callednextTetromino
exactly the same as the current Tetromino block, except that the row is lower than 1 cell. - Check to see
nextTetromino
this temporarynextTetromino
block has been crossed from the lower boundary or overlap (that is, the overlap) with the landed blocks:- If not, continue lowering the currentTetromino block by calling
currentTetromino.fall()
. - If you already have discovered duplicate overrides, attach this block to the array blocks landed
landedBoard
and get a new random Tetromino other blocks.
- If not, continue lowering the currentTetromino block by calling
- Instead of updating the
- Conducting updates, drawing changes on the player interface via canvas.
Update the progress()
function
The progress()
function from my previous post needs to be updated as follows:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">let</span> nextTetromino <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">this <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> constructor</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> row <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> col <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> angle <span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">bottomOverlapped</span> <span class="token punctuation">(</span> nextTetromino <span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">landedOverlapped</span> <span class="token punctuation">(</span> nextTetromino <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> <span class="token function">fall</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">mergeCurrentTetromino</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token operator">=</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">randomTetromino</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// TODO</span> <span class="token punctuation">}</span> |
Note: the constructor()
helps me call the correct method of class constructor directly creating currentTetromino
. So whether currentTetromino
is LShape or ZShape or anything, I will create another Tetromino similar with the least verbose code. .
Now we need to start writing the methods used in progress()
.
Check the bottom border crossing with bottomOverlapped()
bottomOverlapped()
accepts a Tetromino-class object and returns a boolean, indicating whether the Tetromino has passed the lower boundary of the game. Needless to say, this function is as simple as this:
1 2 3 4 5 6 7 8 | <span class="token function">bottomOverlapped</span> <span class="token punctuation">(</span> tetromino <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> tetromino <span class="token punctuation">.</span> row <span class="token operator">+</span> tetromino <span class="token punctuation">.</span> height <span class="token operator">></span> <span class="token keyword">this</span> <span class="token punctuation">.</span> boardHeight <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Check overlap with landed cells with landedOverlapped()
landedOverlapped()
also takes a Tetromino object and returns a boolean result. A true value means that there is a overlap between landedArray and Tetromino blocks.
To detect the overlap, here I choose to check every block of Tetromino to see if it overlaps with the landedBoard
. Despite being 2 for loops, Tetromino blocks are always only a collection of 4 blocks, so performance is not a problem here. For more complex games, you need to consider choosing other techniques (such as hitbox), instead of checking every unit area (or volume) of an object like this: v.
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token function">landedOverlapped</span> <span class="token punctuation">(</span> tetromino <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator"><</span> tetromino <span class="token punctuation">.</span> height <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">let</span> j <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> j <span class="token operator"><</span> tetromino <span class="token punctuation">.</span> width <span class="token punctuation">;</span> j <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> tetromino <span class="token punctuation">.</span> shape <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">[</span> j <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&&</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> landedBoard <span class="token punctuation">[</span> tetromino <span class="token punctuation">.</span> row <span class="token operator">+</span> i <span class="token punctuation">]</span> <span class="token punctuation">[</span> tetromino <span class="token punctuation">.</span> col <span class="token operator">+</span> j <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> |
Re-attach the Tetromino block to the landed blocks with mergeCurrentTetromino()
Once we know that the current Tetromino block has collided and can’t go any further, we need to get it stuck on the landedBoard
array. Each type of Tetromino has its own color, so although it has become “a big block” with other Tetromino, I want the color of the falling block to remain in the landedBoard
array.
We also just need to iterate through the currentTetromino
, and update the value of each small cell to its corresponding position at landedBoard
.
1 2 3 4 5 6 7 8 9 10 | <span class="token function">mergeCurrentTetromino</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> height <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">let</span> j <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> j <span class="token operator"><</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> width <span class="token punctuation">;</span> j <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> shape <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">[</span> j <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> landedBoard <span class="token punctuation">[</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> row <span class="token operator">+</span> i <span class="token punctuation">]</span> <span class="token punctuation">[</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> col <span class="token operator">+</span> j <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> shape <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">[</span> j <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Speed things up with tryMoveDown()
This function will run when the user presses the arrow down. Here I simply run the progress()
function then proceed to draw changes to the canvas and it is done.
1 2 3 4 5 6 | <span class="token function">tryMoveDown</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">progress</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">updateCurrentBoard</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">draw</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Result
See JSFiddle after the last section here: https://jsfiddle.net/tranxuanthang/3c1fj8os/6/
Move left / right
Check Tetromino block beyond left / right margin
Similar to landedOverlapped()
, checking whether Tetromino blocks are beyond the left / right boundary is very simple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token function">leftOverlapped</span> <span class="token punctuation">(</span> tetromino <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> tetromino <span class="token punctuation">.</span> col <span class="token operator"><</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token function">rightOverlapped</span> <span class="token punctuation">(</span> tetromino <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> tetromino <span class="token punctuation">.</span> col <span class="token operator">+</span> tetromino <span class="token punctuation">.</span> width <span class="token operator">></span> <span class="token keyword">this</span> <span class="token punctuation">.</span> boardWidth <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Proceed to move the block
Now we create the tryMoveLeft()
and tryMoveRight()
to proceed to move the Tetromino block to the left / right when the user presses the corresponding arrow key.
We must continue to create a temporary Tetromino block to simulate the next state of the Tetromino block. Whether moving left or right, you need to check for overlap with landedBoard
(reuse landedOverlapped()
we wrote in the previous section) and also check for overlap on left / right sides respectively. No need to check overlap with the opposite side or bottom border.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token function">tryMoveLeft</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> tempTetromino <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">this <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> constructor</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> row <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> col <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> angle <span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">leftOverlapped</span> <span class="token punctuation">(</span> tempTetromino <span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">landedOverlapped</span> <span class="token punctuation">(</span> tempTetromino <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> col <span class="token operator">-=</span> <span class="token number">1</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">updateCurrentBoard</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">draw</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token function">tryMoveRight</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> tempTetromino <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">this <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> constructor</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> row <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> col <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> angle <span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">rightOverlapped</span> <span class="token punctuation">(</span> tempTetromino <span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">landedOverlapped</span> <span class="token punctuation">(</span> tempTetromino <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> col <span class="token operator">+=</span> <span class="token number">1</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">updateCurrentBoard</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">draw</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Result
It is much better. See JSFiddle to this step here: https://jsfiddle.net/tranxuanthang/4uLw7hn6/4/
Rotate the Tetromino block
It’s the same as when we proceed to write functions that bring Tetromino blocks down or to the left / right. However, rotating Tetromino blocks is quite complicated and unexpected because it changes both the width and height of Tetromino blocks when they are in the table. In order for the rotation to work 100% correctly, you must fully check the collision / coincide with all other elements (except the left edge, due to the way I choose to place the Tetromino block position as the upper left corner).
Fortunately, the test functions we all do above, just reuse / recall:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token function">tryRotating</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> tempTetromino <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">this <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> constructor</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> row <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> col <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> angle <span class="token punctuation">)</span> tempTetromino <span class="token punctuation">.</span> <span class="token function">rotate</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">rightOverlapped</span> <span class="token punctuation">(</span> tempTetromino <span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">bottomOverlapped</span> <span class="token punctuation">(</span> tempTetromino <span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token operator">!</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">landedOverlapped</span> <span class="token punctuation">(</span> tempTetromino <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> currentTetromino <span class="token punctuation">.</span> <span class="token function">rotate</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">updateCurrentBoard</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">draw</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Finally, we have perfected the player’s movement and control features for the game:
The result here, you can click on the Result tab, click on the canvas frame once and try to control with 4 up / down / left / right arrow keys:
Conclusion
Today we have learned and done quite a bit, and the game is starting to take shape. However, the game is still far from perfect, and there are still many features we have to develop such as:
- How to clear rows and earn points? How to calculate the point?
- How to improve RNG algorithm into random in 7-bag style?
- How to give users a hint about the next block to help players outline the strategy?
- Pause & resume, sound effects and background music, …
I would like to save these shortcomings for the later part of the lesson. Thank you all for reading.