Sunday, October 7, 2012

Implementing Tetris: Collision Detection

I’m sure it’s possible to create a Tetris game with a point-and-click gamedev tool, but I could never figure out how. Today, I’m more comfortable thinking at a higher level of abstraction, where the tetromino you see onscreen is only a representation of what’s going on in the underlying game. In this tutorial I’ll show you what I mean, by demonstrating how to handle collision detection in Tetris. Note: Although the code in this tutorial is written using AS3, you should be able to use the same techniques and concepts in almost any game development environment.

The Grid

A standard Tetris playing field has 16 rows and 10 columns. We can represent this in a multidimensional array, containing 16 sub-arrays of 10 elements:
Imagine the image on the left is a screenshot from the game – it’s how the game might look to the player, after a tetromino has landed but before another has been spawned. On the right is an array representation of the game’s current state. Let’s call it landed[], as it refers to all of the blocks that have landed. An element of 0 means that no block occupies that space; 1 means that a block has landed in that space. Now let’s spawn an O-tetromino in the centre at the top of the field:
tetromino.shape = [[1,1],
                   [1,1]];
tetromino.topLeft = {row: 0, col:4};
The shape property is another multidimensional array representation of the shape of this tetromino. topLeft gives the position of the top-left block of the tetromino: at the top row, and the fifth column in. We render everything. First, we draw the background – this is easy, it’s just a static grid image. Next, we draw every block from the landed[] array:
for (var row = 0; row < landed.length; row++) {
    for (var col = 0; col < landed[row].length; col++) {
        if (landed[row][col] != 0) {
            //draw block at position corresponding to row and col
            //remember, row gives y-position, col gives x-position
        }
     }
}
My block images are 20x20px, so to draw the blocks I could just insert a new block image at (col * 20, row * 20). The details don’t really matter. Next, we draw every block in the current tetromino:
for (var row = 0; row < tetromino.shape.length; row++) {
    for (var col = 0; col < tetromino.shape[row].length; col++) {
        if (tetromino.shape[row][col] != 0) {
            //draw block at position corresponding to
            //row + topLeft.row, and
            //col + topLeft.col
        }
     }
}
We can use the same drawing code here, but we need to offset the blocks by topLeft. Here’s the result:
Implementing Tetris: Collision Detection
Note that the new O-tetromino doesn’t appear in the landed[] array – that’s because, well, it hasn’t landed yet.

Falling

[...]

Read more: Implementing Tetris: Collision Detection

No comments:

Post a Comment