Tetris in HTML5 for Noobs: Part 5 – User Interaction

So far, we’ve only been creating static images with our drawing commands. The next step is to make the images move. Games demand some level of interactivity, so we need to be able to respond to user input. In Tetris, the user is able to move the current tetrimino to the left or right, adjust its orientation, or drop it down onto the stack. We’ll use the four arrow keys as the controls for our game. You may remember that we added an onload attribute to the <body> tag to call a JavaScript function as soon as the page is loaded. There are actually many different events that we can define for each element in the HTML document, and the one that we are currently interested in is the onkeydown event. This is fired whenever a key is pressed on the keyboard. We’ll create a new function to handle the event. Add the following attribute to the <body> tag:

In the <script> section, we will define the following function:

This function will display a popup window with a key code whenever we press a button. If we load the page and press the arrow keys, we should find that the key codes for left, up, right, and down arrow are 37, 38, 39, and 40 respectively. Now that we know the code that each key maps to, we can create an if-else block to take the appropriate action, based on which key was pressed. For our first test, we’ll create a random tetrimino and allow the user to move it around as if they were playing the game. We’ll need to add four global variables to keep track of the current tetrimino’s type, position, and orientation.

Any time we add global variables, we should make sure they are initialized in the initialize function. Add the following lines to that function:

The left and right arrow keys should move the tetrimino one block left and right respectively. The up arrow key should change the orientation. For our game, the down key will eventually provide a hard drop, immediately placing the current tetrimino onto the stack, but for now, we’ll just move it down one block at a time. Change the function to look like this:

You can see that the first thing we do when a key is pressed is clear the canvas, giving us a clean slate to draw on. We then take the appropriate action, either updating the current coordinate or orientation, or creating a new tetrimino if a non-arrow key was pressed. The += and -= variable assignments increment or decrement the variable by the specified value. x += 1 is equivalent to x = x + 1 and y -= 1 is equivalent to y = y - 1. The % symbol used to change orientation is the modulus operator. This is essentially the remainder part of the result after division. In this case, the statement o = (o + 1) % 4 increments the o variable by 1, but resets it back to 0 if it gets up to 4. This keeps it in the valid range of 0 to 3.

When we create a new tetrimino, we use the built in JavaScript Math object to create a random number between 0 and 6 to represent the tetrimino type. The function Math.random() returns a uniformly sampled random number between 0 (inclusive) and 1 (exclusive), which we represent with the shorthand [0,1). By multiplying this value by 7 the output range becomes [0,7). To get an integer value, we use the Math.floor() function to trim off any fractional value and round down to the nearest whole number. This effectively gives us a random integer in the range 0 to 6 to represent the tetrimino type.

Lastly, we draw the current tetrimino to the canvas using the updated values. The complete code should now look like this:

If you run the code now and press a non-arrow key, you should see a random tetrimino appear at the top of the canvas. The arrow keys should allow you to move it left, right, and down, and pressing the up arrow key should change its orientation. You’ll notice that we haven’t implemented any boundary tests, so it’s easy to move the tetrimino all the way off the screen. We also have no good way of displaying more than one tetrimino at a time using this method, since we clear the entire canvas before redrawing the screen. The best way to fix this will be to implement a game state array that will maintain the current state of the game window. We can make changes to the array and then redraw its contents anytime a change occurs. Although this will incur some additional overhead for drawing single tetriminos, it will become very useful for implementing the game’s logic when many blocks are on the screen at once.

Updated: February 11, 2015 — 9:47 am

Leave a Reply

Your email address will not be published. Required fields are marked *

DrewBuck.com © 2015 Frontier Theme