Skip to main content
GameDev.net gamedev.net
🔒 Locked

tetris collision detection

Started by copper103 Nov 26, 2009 at 1:31 PM 31 replies 13.3k views
Original Post
copper103
copper103
i basically have a working tetris program in C++ now with allegro, but the only problem is i dont really know how to check for collisions, i have tried a few things but they dont seem to work game board is a [21][21] array with all spaces set to 0, 1 for block currently moving, and 2 for a block that has settled the piece currently moving is a [5][5] array
DevFred
DevFred
21? 5? Why those weird dimensions?
furiousuk
furiousuk
To detect collisions the easiest way is to calculate where the block is moving to before actually moving it. So,

* Get the blocks new position (desired position)
* Check that the desired position is clear
* If it is then move the block
* Else, a collision has occured so stop moving the block and spawn a new one at the top.

Probably the simplest way of detecting if the falling block has collided with anything is to iterate through your 5x5 array and for each space in the array, check that the 5x5 array holds a block in that location and then check if the gameboard holds a block in the relevant position in the 21x21 array.

There are, of course, multiple ways to solve this problem. Without knowing your exact implementation I suspect this is the easiest way to solve your problem.
Eskapade
Eskapade
The falling piece has a current position (row, column) referring to the index in the game field. Let's say the origin is on the top left. It really doesn't matter which corner of the piece you take, though.

You create a new tile to drop and it's spawned/created at (row=20, column=5) for example. It is 5 fields wide, 5 fields tall. All possible collisions occur in
(20, 5), (20, 6), (20, 7), (20, 8), (20, 9),
(19, 5), (19, 6), (19, 7), (19, 8), (19, 9),
...
(16, 5), (16, 6), (16, 7), (16, 8), (16, 9).

You will have to check these fields whether they are set in the play field AND the currently falling piece.
For example:

bool collides(piece, playField){if(piece[0][0] && playField[positionY][positionX])    return true; // yes, it collides// check other fields    return false;}


Same check for the second column in the first row (row #0, column #1) would be
if(piece[0][1] && playField[positionY+0][positionX+1])   return true;


Now, of course you can write every field like that, but doing this with a loop would be easier. So you calculate the indices in piece and playField by using two loops: one to increase the row, one to increase the column, both going from 0 to 5 (excluding 5, indices go from 0 to 4).

Hope that helps!
MorDuc
MorDuc
im working on a tetris game myself

have made the collisiondetection function

int tempX, tempY;		for(int i = 0; i < 4; i++){			tempX = (currentObject.x + currentObject.pBlock->block[rotate][0])+mx;			tempY = (currentObject.y + currentObject.pBlock->block[rotate][1])+my;			if(tempY >= 0)			{				if(tempX < 0 || tempX >= MAPWIDTH || map[tempX][tempY].filled == true)				{					collision = true;				}								if(tempY >= MAPHEIGHT || collision == true && my == 1 ) {					landed = true;					collision = true;				}				if(landed == true && currentObject.y < 0){}					// gamestate -> gameover			}				}		if(collision == false)		{			currentObject.x += mx;			currentObject.y += my;			pressTimer->reset();		}		if(landed == true)		{				for(int i = 0; i<4; i++){					tempX = (currentObject.x + currentObject.pBlock->block[rotate][0]);					tempY = (currentObject.y + currentObject.pBlock->block[rotate][1]);					map[tempX][tempY].color = currentObject.color;					map[tempX][tempY].filled = true;									moveTimer->reset();						}		}				collision = false;}
shultays
shultays
rather than creating a 5x5 array for each type of piece it would be better if you use something like


int blocknum;
int coors[blocknum][2];

where coors array contains the relative position of each block. for example

x
x
xx

is

blocknum = 4
coors[0] = {0,0}
coors[1] = {0,1}
coors[2] = {0,2}
coors[3] = {1,0}

and for testing

for(int i=0; i<blocknum; i++){  int x = coors[pixelnum][0] + positionx;  int y = coors[pixelnum][1] + positiony;  if(board[x][y] == 1){    //collision  }}
taytay
T Jackson
T Jackson
Yeah I wouldn't really call it collision detection. Perhaps collision prevention though. You need procedures that can determine which tiles areas have something there, and if they do then the player's request to move the piece is denied. If the player requests to rotate a piece then another procedure checks to see if it will fit in place without interfering with any of the other tiles before committing to the move.

Tetris is a dead simple video game to make and to play. Most first year computer science students possess the abilities to code a simple game of Tetris.

Trent Jackson

xfront
xfront
Quote:
Original post by copper103
game board is a [21][21]

the piece currently moving is a [5][5] array


It appears your not using array's [0];[0] coordinates. It's not very bad, but when I tried to make a tetris, I had some glitches on the sides of my play area. I rewrote code using [0]'s and it worked fine than. This is not a very huge issue if you recheck that your code never seeks for that array.

As for the collision, I checked if there were nothing under the block.

If you still have problems after all of the suggestions, try to count things from zero in arrays if you didn't.
I doubt that the problem is in your collision code, after trying to rewrite it few times.
Time is measured by stuff you do. Don't waste minutes on nothing, have more time.
agm_ultimatex
agm_ultimatex
I'm in the process of building a tetris clone myself using java. I dont have the actual pieces in yet, but Ive done some tests with dropping down single squares, canceling out a row, and blocks stopping on top of a square that's stopped or when it reaches the bottom.

I used a multi-dimensional array, and actually looped through it backwards. Found it easier that way to check if there's something above it and that, for instance in pseudo code:

If there something in the above square that's falling?
If there's something in this square that's not falling but alive?
Then set the above square to not falling
end
end
NordCoder
NordCoder
http://www.aaroncox.net/tutorials/arcade/FallingBlocks.html

This might be of some help. Look under Part 5.
szecs
szecs
Quote:
Original post by T Jackson
Yeah I wouldn't really call it collision detection. Perhaps collision prevention though. You need procedures that can determine which tiles areas have something there, and if they do then the player's request to move the piece is denied. If the player requests to rotate a piece then another procedure checks to see if it will fit in place without interfering with any of the other tiles before committing to the move.

Tetris is a dead simple video game to make and to play. Most first year computer science students possess the abilities to code a simple game of Tetris.

Trent Jackson
It's simple, but not dead simple.
I consider myself an experienced programmer (OK not programmer, but problem-solver)
I thought today at 3 PM, that I don't have the mood for doing anything, so I'll try coding tetris, and see how much time does it take. It's a newbie program after all.

I'm finished, but it's 19:45 PM now. (OK it took me half an hour the struggle with glut projection matrix setup with no success.)
And the rotation isn't perfect yet. (It's not the same can be seen in games).
T Jackson
T Jackson
Quote:
Original post by szecs
It's simple, but not dead simple.
I consider myself an experienced programmer (OK not programmer, but problem-solver)
I thought today at 3 PM, that I don't have the mood for doing anything, so I'll try coding tetris, and see how much time does it take. It's a newbie program after all.

I'm finished, but it's 19:45 PM now. (OK it took me half an hour the struggle with glut projection matrix setup with no success.)
And the rotation isn't perfect yet. (It's not the same can be seen in games).

You must be an incredibly fast programmer, either that or I must be a little slow.

I have produced a considerably "flash and contemporary" version of Tetris. A lot of animations and thought went into the game. I started with a raw engine (a very simple and traditional game of Tetris) -- then began to add in all sorts of frills like background animation, music and sound effects etc ...

A raw game engine for Tetris with no frills should require no more than about 20 Kb of text in an OPP language. Something fancy will require a lot more. I end up with about 150 Kb worth of source text written from scratch when I had finished. About a month's worth of work at a leisurely pace.

So I guess you're right. For some people it's a simple game, for others it can be made into a complex game. But for the majority of people on the Internet it is DEAD simple.

Trent Jackson
T Jackson
T Jackson
Last but not least ...

Computer programming IS problem solving.

A synonymous affair.
T Jackson
T Jackson
Before you can copy a game you need to become a master at playing it first.

It is a reverse engineering exercise. You need to take into account all aspects of the game and turn them into as many broken down pieces as possible.

So just first start off by playing someone else's game of Tetris until you get a big hard on, then flop it out and have a good wank.
T Jackson
T Jackson
Quote:
Original post by MorDuc
im working on a tetris game myself

have made the collisiondetection function

int tempX, tempY;		for(int i = 0; i < 4; i++){			tempX = (currentObject.x + currentObject.pBlock->block[rotate][0])+mx;			tempY = (currentObject.y + currentObject.pBlock->block[rotate][1])+my;			if(tempY >= 0)			{				if(tempX < 0 || tempX >= MAPWIDTH || map[tempX][tempY].filled == true)				{					collision = true;				}								if(tempY >= MAPHEIGHT || collision == true && my == 1 ) {					landed = true;					collision = true;				}				if(landed == true && currentObject.y < 0){}					// gamestate -> gameover			}				}		if(collision == false)		{			currentObject.x += mx;			currentObject.y += my;			pressTimer->reset();		}		if(landed == true)		{				for(int i = 0; i<4; i++){					tempX = (currentObject.x + currentObject.pBlock->block[rotate][0]);					tempY = (currentObject.y + currentObject.pBlock->block[rotate][1]);					map[tempX][tempY].color = currentObject.color;					map[tempX][tempY].filled = true;									moveTimer->reset();						}		}				collision = false;}


You are using an object orientated programming language. Why are you thinking procedural for?
T Jackson
T Jackson
Why not just create a class called blocks and a method to see if an instance of the class exists?

Your play field is say 20 x 20, which means that could end up with 400 instances of the block class if the whole screen is filled.

Collision prevention is straightforward. OOP makes this easy.

Does this instance exist?

We on the same wavelength?
beatdown_master
beatdown_master
I think it's interesting to note that you don't actually need animation in Tetris (other than moving and removing blocks). I also had some problems with allowing the use to move the block right before the block freezes in place. This allows for some "trick" placements.
T Jackson
T Jackson
The guy who wrote this thing: .net Tetris Game -- is an idiot.

It doesn't take full advantage of object orientated programming in .net

But the guy who composed the music is a genius.
T Jackson
T Jackson
Quote:
Original post by beatdown_master
I think it's interesting to note that you don't actually need animation in Tetris (other than moving and removing blocks). I also had some problems with allowing the use to move the block right before the block freezes in place. This allows for some "trick" placements.


If you don't animate and think outside the square then you end up adding to the 100 million+ collection of boring Tetris clones.

As for the "trick maneuvers" before the block freezes in place -- a small amount of time is called for before the piece locks in. Delay of 1 sec should suffice, and if the player uses the down key then this delay is overridden.

T Jackson
T Jackson
I'd say that idiot only won the coding contest due to originality.

I think it was his first .net project too.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.