Home
2D Game Tutorials
Arcade Game   Tutorials
Miscellaneous   Tutorials
Code Dump
Forum
Links







Falling Blocks Part 5: Collision Detection

CheckEntityCollisions()

Detecting collisions between two squares in 2D is about as easy as it gets. All we have to do is compare the distance between two squares and see if it's equal to the distance between two touching squares. We know that the distance between the centers of two touching squares will always be SQUARE_MEDIAN*2. This is just the distance from one square's center to its side plus the distance between another square's center and its side.

Note that we can also use SQUARE_MEDIAN*2 as the distance a square will move.

To get the distance between two squares, we subtract the location of one square's center from the other's. We then take the absolute value of the number we get because the distance between two squares should never be negative. Note that we could easily get a negative number depending on the order of subtraction.

Our function takes a pointer to the square that is moving and its direction. We need to get the location of the square after it moves, which is accomplished using a simple switch statement. Add the following to "Main.cpp":

// Check collisions between a given square and the squares in g_OldSquares
bool CheckEntityCollisions(cSquare* square, Direction dir)
{
    // Width/height of a square. Also the distance
    // between two squares if they've collided.

    int distance = SQUARE_MEDIAN * 2;

    // Center of the given square
    int centerX = square->GetCenterX();
    int centerY = square->GetCenterY();

    // Determine the location of the square after moving
    switch (dir)
    {
        case DOWN:
        {
            centerY += distance;
        } break;

        case LEFT:
        {
            centerX -= distance;
        } break;

        case RIGHT:
        {
            centerX += distance;
        } break;
    }

    // Iterate through the old squares vector, checking for collisions
    for (int i=0; i<g_OldSquares.size(); i++)
    {
        if ( ( abs(centerX - g_OldSquares[i]->GetCenterX() ) < distance ) &&
            ( abs(centerY - g_OldSquares[i]->GetCenterY() ) < distance ) )
        {
            return true;
        }
    }

    return false;
}

Our other CheckEntityCollisions() function takes a pointer to a block. Because a block is made up of four squares, we can get an array of pointers to these squares and just call our previous function on them. Add the following to "Main.cpp":

// Check collisions between a given block and the squares in g_OldSquares
bool CheckEntityCollisions(cBlock* block, Direction dir)
{
    // Get an array of the squares that make up the given block
    cSquare** temp_array = block->GetSquares();

    // Now just call the other CheckEntityCollisions() on each square
    for (int i=0; i<4; i++)
    {
        if ( CheckEntityCollisions(temp_array[i], dir) )
            return true;
    }

    return false;
}

CheckWallCollisions()

To check to see if a square is going to collide with the walls of the game area, we get the location of the square after it moves and compare that with the dimensions of the game area. If the square is out of bounds, then we know that there's been a collision. Add the following to "Main.cpp":

// Check collisions between a given square and the sides of the game area
bool CheckWallCollisions(cSquare* square, Direction dir)
{
    // Get the center of the square
    int x = square->GetCenterX();
    int y = square->GetCenterY();

    // Get the location of the square after moving and see if its out of bounds
    switch (dir)
    {
        case DOWN:
        {
            if ( (y + (SQUARE_MEDIAN*2)) > GAME_AREA_BOTTOM )
            {
                return true;
            }
            else
            {
                return false;
            }
        } break;

        case LEFT:
        {
            if ( (x - (SQUARE_MEDIAN*2)) < GAME_AREA_LEFT )
            {
                return true;
            }
            else
            {
                return false;
            }
        } break;

        case RIGHT:
        {
            if ( (x + (SQUARE_MEDIAN*2)) > GAME_AREA_RIGHT )
            {
                return true;
            }
            else
            {
                return false;
            }
        } break;
    }

    return false;
}

For blocks, we do the exact same thing with CheckWallCollisions() as we did with CheckEntityCollisions(). Add the following to "Main.cpp":

// Check for collisions between a given block a the sides of the game area
bool CheckWallCollisions(cBlock* block, Direction dir)
{
    // Get an array of squares that make up the given block
    cSquare** temp_array = block->GetSquares();

    // Call other CheckWallCollisions() on each square
    for (int i=0; i<4; i++)
    {
        if ( CheckWallCollisions(temp_array[i], dir) )
        return true;
    }

    return false;
}

CheckRotationCollisions()

Thanks to cBlock's GetRotatedSquares() function, checking for rotation collisions is really simple. The same two events that can occur when we move a block can occur when we rotate it. It can either hit the walls of the game area or it can hit a square. The process is the exact same as it was for the last two collision detection functions. Note that we always delete the array before returning anything.

Add the following to "Main.cpp":

bool CheckRotationCollisions(cBlock* block)
{
    // Get an array of values for the locations of the rotated block's squares
    int* temp_array = block->GetRotatedSquares();

    // Distance between two touching squares
    int distance = SQUARE_MEDIAN * 2;

    for (int i=0; i<4; i++)
    {
        // Check to see if the block will go out of bounds
        if ( (temp_array[i*2] < GAME_AREA_LEFT) ||
             (temp_array[i*2] > GAME_AREA_RIGHT) )
        {
            delete temp_array;
            return true;
        }

        if ( temp_array[i*2+1] > GAME_AREA_BOTTOM )
        {
            delete temp_array;
            return true;
        }

        // Check to see if the block will collide with any squares
        for (int index=0; index<g_OldSquares.size(); index++)
        {
            if ( ( abs(temp_array[i*2] - g_OldSquares[index]->GetCenterX()) < distance ) &&
                ( abs(temp_array[i*2+1] - g_OldSquares[index]->GetCenterY()) < distance ) )
            {
                delete temp_array;
                return true;
            }
        }
    }

    delete temp_array;
    return false;
}

Falling Blocks Part 6: Changing The Focus Block

 

 

This site is © Copyright Aaron Cox 2004-2005, All Rights Reserved.
Website templates