Sign in to follow this  

basic collision detection

This topic is 3456 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am making a tetris game. I am using a 2d int array to store the shapes, a different number represents a different piece. I have functions that create each shape and erase each shape. Now i want to work on moving the shapes and collision detection. All open spaces on the board are marked by 0 so if a space is marked 0 then it is available to be moved to. So the square shape looks like this: 22 22 Lets say i try to move that down 1 so to do that i have to check if the one below it is a 0 but it doesn't check 1 below the whole shape it just checks 1 below the first row and find a 2 and says there is a collision. How would i get it to check below the whole shape. I thought about passing into the function something that says ignore this so it would ignore the 2 but then if your placing a square on top of another square it wont work, it has to detect the end of that piece only. Is the only way to do this to have a different collision detection function for each piece since there is not a constant beginning and ending spot for the pieces?

Share this post


Link to post
Share on other sites
o, thats a good idea. So then when there is a collision moving a piece down the array then i would update the array that has all the pieces that are settled down. So then to check for collision right i would have a function like this:

// return 1 if you can move right 0 otherwise
int canMoveRight(int xPos, int yPos)
{
if (gameBoardSet[yPos][xPos+1] == 0)
{
return TRUE;
} // end if
else
return FALSE;
} // end canMoveRight

this returns true if you can move right false otherwise, you pass it the current x and y positions and then it checks 1 over i also need to add to that to check the bounds to make sure that it is not going off the right side of the playing field. Then to update the version of the gameBoard that has the settled pieces would i need another function for each piece that takes the final x position and y position of the piece and draws it on there? Also, i am going to have the same problem with the bounds detection. I think it has something to do with checking the first x and y position on the piece and not the 2nd. Like on the square that is this:
22
22
it checks the position of the 2 where the piece starts to move it right not where it ends. So i would need to check where it ends but since each tetris piece is different then i think i need to have a function for each shape right? Unless i made the game board have 1 more row and column and just made them all 1's or something and never made it be displayed so then running into the last row and last column would be the same logic as any other collision but you would not see them so its like the end of the playing field.

[Edited by - cwl157 on June 21, 2008 11:20:38 AM]

Share this post


Link to post
Share on other sites
And would i need a separate function for each piece to update this or could i just copy the gameboard array into it to update it? I am playing around with it though and i still have some trouble with the square being 2 columns long and it looking at the first column where it starts and not the 2nd column. Then with the bounds if i add an extra column to the left and right ends and 1 at the bottom that is all 1's or something this logic could be the same. And i think part of my problem is now the gameBoard does not go all the way. It doesn't go from 0 to 17 it goes from 1-16 left to right and from 0 - 16 down because of the ends.

Share this post


Link to post
Share on other sites
You don't have to have a separate function for each piece. When I made Tetris, I did the collision detection a bit differently. I checked for collision after the piece has moved but before the array was drawn onto the screen. If the piece overlapped with the settled board array, I moved the piece back. That way, I would need only one function to do right, left, and bottom collisions.

Share this post


Link to post
Share on other sites
i dont know how that method would work with mine because i have a separate draw and erase function for each piece. So i was just going to check if the piece could be moved there and then move it there. The collision detection works for one piece now it will take it to the bottom and set it but i am having problems updated the array with the set piece. It's basically just setting the 2 arrays equal and i made a function that does that but it does not work right i don't think i can do it the way i think i can. How do i edit this function to set the gameBoardSet array equal to the gameBoard array.

// this sets the gameBoard = to the gameBoardSet
void setBoards()
{
for (int row = 0; row < 17; row++)
{
for (int col = 0; col < 17; col++)
{
gameBoardSet[row][col] = gameBoard[row][col];
} // end for
} // end for
} // end setBoards

if i run this function after placing a piece on the board all i get are 0's like nothing was set i dont know whats wrong

Share this post


Link to post
Share on other sites
ok i see what my error is. Its not how i set the boards equal but how i create the pieces. To create the piece i check for a collision if there is no collision i erase the piece that was there and re-draw it one line down. However, the erase comes after the draw so it completely erases the piece from the game board.

This is the code that sends the piece from top to bottom. It works but it does not keep the old piece there.

while (canMoveDown(xPos, yPos))
{
createSquare(xPos, yPos);
displayGameBoard();
setBoards();
cout << endl << endl;
eraseSquare(xPos, yPos);
yPos++;
} // end while

xPos = MIDDLE_X;
yPos = 0;
while (canMoveDown(xPos, yPos))
{
createLongShankVert(xPos, yPos);
displayGameBoard();
cout << endl << endl;
eraseLongShankVert(xPos, yPos);
yPos++;
} // end while

Share this post


Link to post
Share on other sites
forget all this stuff i just posted. A generic move down, move left, move right function can not work because to detect a collision moving down you have to use the bottom most block of the tetris piece to check and that varies by piece. To go right you have to use the right most block of that piece and that varies by piece. To move left you have to use the left move block of that piece and that varies by piece. So because of that i don't see how you can use the same block position on all of them to detect if its a collision because it all varies.

[Edited by - cwl157 on June 21, 2008 1:56:17 PM]

Share this post


Link to post
Share on other sites
i have been working on this since 8 am this morning and have not gotten any farther. Can someone please tell me how i would do collisions. I dont care how many functions i have to write or anything i just need it figured out its driving me crazy. I have a function that places the piece on the board and i have a function that erases the piece from the board. To move a piece from the top to the bottom i create the piece then erase the piece then create the piece 1 down and then erase that piece and create it again 1 more down, i need to do this until it reaches the bottom. It detects the piece from the top and stops all of them when they get to a row above the bottom row. So the square is the only one that works because it is shaped like this:
22
22

The long piece vertically is this at the beginning:
1
1
1
1
and the bottom is not detected until it gets here at the end
1
1
again it stops it one row up from the bottom row.

the horizontal long piece looks like this to start:
1111
and ends like this:
1111
00000000

again one row above the bottom. How can i draw and erase shapes until it reaches a collision whether it be at the bottom or if there are already pieces down it would be above that and then i need it for the right and left as well.

Thank you

Share this post


Link to post
Share on other sites
well erase shapes to move them down. All my pieces are 2d int arrays so like a long line would look like:

vertical: Horizontal
1000 1111
1000 0000
1000 0000
1000 0000

the square is:
2200
2200
0000
0000

To move a shape i have a create function for each shape so to create the square i have a createSquare function that takes the x and y position of where the square will go it looks like this:

// create the square
void createSquare(int xPos, int yPos)
{
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
if (square[row][col] == 2)
gameBoard[row+yPos][col+xPos] = 2;
else
continue;
} // end for
} // end for
} // end createSquare

Now to move the square down the game board i create the shape at the top then erase that shape and create it again after incrementing the y position so its one down from where it used to be. To move the shape right i erase the shape increment the x position 1 and recreate the shape with the new x position so its 1 to the right. To erase i just have an eraseSquare function that is the same as createSquare but instead of changing from 0 to 2 it changes from 2 to 0.

So basically i have 2 problems. Like the long line vertical for example, i start detecting from the 1st 1 not the last so the collision isnt detected until it gets to 1 from the top because thats the y position its using to compare, i need to use the bottom most 1. I need to figure that problem out and with setting the other board after that is detected because it goes create, erase, increment create erase increment so the last thing is erasing and then i try and set the game board array equal to the array that holds set pieces and it does not work right because the board ends with the piece erased.

Share this post


Link to post
Share on other sites
First, the shape movement can be much simpler. Suppose that you have a variable posY that tracks the shape's vertical position. Instead of constantly copying the shape to the board and erasing it, just check to see if the shape collides with the board. If it does, copy the shape to the board at position posY - 1. Otherwise, increment posY by 1.

In other words, moving the shape simply means updating a couple of variables that hold the shape's current position. Only after you've detected that the shape collides with the board, you copy it to the board.

Second, I don't understand why the collision detection doesn't work if you start testing the shape's individual squares from the top. Why does it matter if you start testing from the top or the bottom?

Share this post


Link to post
Share on other sites
i start at the top and create and erase them all the way down to the bottom then when i get to the bottom it does not detect that its at the bottom until the first block gets there because thats the one that i pass to the collision test function. Also what do you mean collides with the board? Like the int at that position on the board is 0 and then draw just that 1 block and not the whole piece? Also how would i draw the whole shape using this method i would be jumping all over the x and y position as it moves down and then if the whole shape has to move left or right... i don't get how that works. But if i had collision detection functions for each shape then when that shape is the one being moved i could just call those collision detection functions until a down collision is detected then x and y are reset and the next shape is drawn at the top. I think i would still have a problem with the create and erase thing though.

Share this post


Link to post
Share on other sites
There is no need to have a separate collision detection function for each shape.

If I understand you correctly, each shape is represented as a 4x4 array where 0 represents an empty space. Also, the board is represented as a large 2D array in a similar way.

Given these representations, a check for collision simply means testing if the shape, in it's current position, overlaps with the board.

The code should look something like this:


bool checkCollision(int posX, int posY)
{
for (int r = 0; r < 4; ++r)
for (int c = 0; c < 4; ++c)
{
if ( (board[r+posY][c+posX] != 0) && (shape[r][c] != 0) )
// There's overlap
return true;
}

return false;
}




Here's how moving the shape down might be handled:


int posX = 0, posY = 0; // Holds the shape's position
if (down key pressed)
if (checkCollision(posX, posY))
copyShapeToBoard(posX, posY-1);
else
++posY;


Of course, both code samples are meant to be illustrative and probably don't take some things into consideration.

EDIT: Actually the second code snippet is wrong because the shape should move down even if no key is pressed. Pressing the down key should only make it move faster, but that is not important to what I was trying to illustrate.

I have to go now but if you have any more questions, I'll try to reply tomorrow.

[Edited by - Gage64 on June 21, 2008 11:08:04 PM]

Share this post


Link to post
Share on other sites
The function Gage64 posted should work with every shape. If the shape overlaps with the board, then there is a collision, if it doesn't overlap, then there is no collision. It doesn't matter what the shape looks like.

Share this post


Link to post
Share on other sites
Quote:
Original post by cwl157
ok, the collision function you posted worked but each shape array is different therefore, wouldn't i need a collision detection function for each shape?


No. Notice that a shape is just an array where some entries are 0 and some are not. The values of the other entries do not matter. All that matters is that they are not 0.

What makes two shapes different is the location of the non-zero entries, but the collision detection function doesn't care where those entries are - it goes over all entries in the shape. Therefore, it will work with every type of shape.

Share this post


Link to post
Share on other sites
what gets me is in his function he compares an array called shape to check if its equal to zero. I have a different 2d int array for each shape so then does it not matter which shape array i use to compare? I think since i have a different 2d int array for each shape dont i have to have a different collision function for each shape that uses the shape's 2d int array?

Share this post


Link to post
Share on other sites
thats the thing i dont have a generic shape array. I have a different array for each shape then to draw the shape on the board i have a different create shape function that goes through the array for that particular shape and draws it on the game board. I'm sure your function would work if you had a generic shape array i have many shape arrays each containing the layout of one particular shape, probably not the best way to do it but it works. Like for example for the one where all 4 blocks are in a row it can either looks like this:
1111
or like this:
1
1
1
1

I have a different array for each of those shapes so to detect a collision on that shape i would have to comapare that particular shape's array. Unless to cut down on the functions i had another array called shape and then whichever shape is randomly selected to be put down on the board i would copy that array into the shape array and then i could use the one collision detection function but then i would still need different functions that copy each shape into the shape array since they are all different.

Share this post


Link to post
Share on other sites
sure i was actually just making the collision for them so all the functions and arrays for a shape are in the same code block so ill post the code block for 1 tetris piece. it has the arrays defined, create and erase functions for that piece and the collision functions for that piece. This is for the piece i call the long shank its the one that just has 4 blocks in a row either vertically or horizontally.

/************************************************
* the Long Shank
*
* 1111 1000
* 0000 1000
* 0000 1000
* 0000 1000
************************************************/

// the long shank horizontally
int longShankHorz[4][4] = {{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
};

// the long shank vertically
int longShankVert[4][4] = {{1, 0, 0, 0},
{1, 0, 0, 0},
{1, 0, 0, 0},
{1, 0, 0, 0},
};

// set the long shank horizontally
void createLongShankHorz(int xPos, int yPos)
{
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
if (longShankHorz[row][col] == 1)
gameBoard[row+yPos][col+xPos] = 1;
else
continue;
} // end for
} // end for
} // end createLongShankHorz

// erase the long shank horizontally
void eraseLongShankHorz(int xPos, int yPos)
{
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
if (longShankHorz[row][col] == 1)
gameBoard[row+yPos][col+xPos] = 0;
else
continue;
} // end for
} // end for
} // end eraseLongShankHorz

// check if there is a collision on the long shank horz
bool checkCollisionLongShankHorz(int posX, int posY)
{
for (int r = 0; r < 4; ++r)
for (int c = 0; c < 4; ++c)
{
if ( (gameBoard[r+posY][c+posX] != 0) && (longShankHorz[r][c] != 0) )
// There's overlap
return true;
} // end for

return false;
} // end checkCollisionLongShankHorz

// set the long shank vertically
void createLongShankVert(int xPos, int yPos)
{
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
if (longShankVert[row][col] == 1)
gameBoard[row+yPos][col+xPos] = 1;
else
continue;
} // end for
} // end for
} // end createLongShankVert

// erase the long shank vertically
void eraseLongShankVert(int xPos, int yPos)
{
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
if (longShankVert[row][col] == 1)
gameBoard[row+yPos][col+xPos] = 0;
else
continue;
} // end for
} // end for
} // end eraseLongShankVert

// check if there is a collision on the long shank vert
bool checkCollisionLongShankVert(int posX, int posY)
{
for (int r = 0; r < 4; ++r)
for (int c = 0; c < 4; ++c)
{
if ( (gameBoard[r+posY][c+posX] != 0) && (longShankVert[r][c] != 0) )
// There's overlap
return true;
} // end for

return false;
} // end checkCollisionLongShankVert

/************************************************
* end long shank
************************************************/

Share this post


Link to post
Share on other sites
since i have different ones for different things when thinking about the move functions all of them would have to be different as well. So maybe the best thing would be to have a shape array and then make a copy function for each shape that copies the shape into the shape array and then i could have 1 collision function and 1 move function and 1 erase function for all of them they would just use the shape array.

Share this post


Link to post
Share on other sites

This topic is 3456 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this