0
\$\begingroup\$

I'm currently writing a game which is like Battle City game. But right now I'm facing a trouble involved to checking collision between two objects. This is the code that I wrote:

//-------------------------------------------------------------------------------------------
//  check collision between a tank and another object
//
bool GameController::checkTankMeetsObject(Tank tank, GameObject ob)
{
    int obX = ob.getCoord().getX();
    int obY = ob.getCoord().getY();

    // calculate area of obstacle: bottom left (X1, Y1), top right (X2, Y2)
    int obX1 = obX - SQUARESIZE / 2;
    int obX2 = obX + SQUARESIZE / 2;
    int obY1 = obY - SQUARESIZE / 2;
    int obY2 = obY + SQUARESIZE / 2;

    int tankX = tank.getCoord().getX();
    int tankY = tank.getCoord().getY();

    switch (tank.getDir())
    {
    case UP:
        if ((tankX < obX2 + SQUARESIZE / 2 && tankX > obX1 - SQUARESIZE / 2) &&
            (tankY + SQUARESIZE / 2 > obY1 && tankY + SQUARESIZE / 2 < obY2))
            return true;
        break;

    case DOWN:
        if ((tankX < obX2 + SQUARESIZE / 2 && tankX > obX1 - SQUARESIZE / 2) &&
            (tankY - SQUARESIZE / 2 > obY1 && tankY - SQUARESIZE / 2 < obY2))
            return true;
        break;

    case LEFT:
        if ((tankX - SQUARESIZE / 2 < obX2 && tankX - SQUARESIZE / 2 > obX1) &&
            (tankY > obY1 - SQUARESIZE / 2 && tankY < obY2 + SQUARESIZE / 2))
            return true;
        break;

    case RIGHT:
        if ((tankX + SQUARESIZE / 2 < obX2 && tankX + SQUARESIZE / 2 > obX1) &&
            (tankY > obY1 - SQUARESIZE / 2 && tankY < obY2 + SQUARESIZE / 2))
            return true;
        break;
    }

    return false;
}

This code does well with normal circumstance, but in special ones like which I describe below, it doesn't work.

enter image description here

The white squares are obstacles and the grey square is the tank. Current direction of the tank is RIGHT. In this situation, I can not move the tank RIGHT or LEFT, only direction I can go is DOWN. Is there any solution to optimize my code?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Give your tank a Property that Tracks where its Bounds are. Give all other objects a Bounds as well. Check against the two rectangles to see if they are binding.

Rectangle rect1 = new Rectangle(x,y,width,height);
Rectangle rect2 = new Rectangle(x,y,width,height);

x and y would be your sprites location in the world (Vector2.X and Vector2.Y) Width and Height would be the width and height of the sprites rectangle

//Trap movement before you allow them to bind

GameTime gameTime = this.GameTime;

//Set a velocity based on gametime passed
Vector2 velocity = (150,0);
Vector2 velocityup = (0,150);

//lets say rect1 is your tank
//lets also assume for now that we are moving up x=x y--
//rect1.x += (float)(gameTime.EllapsedGameTime.MilleSeconds * velocity);
rect1.y -= (float)(gameTime.EllapsedGameTime.MilleSeconds * velocityup);

//rect1 now is the position at which our tank would be in a non collision scenario
//so we will check to see if that position would indeed collide with something

if (rect1.Intersects(rect2){

    //we collide
    //dont allow the tank to move in this direction

}

I think the problem you are having is that your measurement of movement is not fine enough, and that you allow the movement first, and then check to prevent it, whereas in this manner you first check, then move.

By using Vector 2's and gametime, we know exactly where our object are, and can trap for the finest of movements. Let me know if you still have some issues here, I know this explanation wasn't the best, but I am new as well so apologies ahead of time man.

\$\endgroup\$
1
  • \$\begingroup\$ It seems very decent, I will try it right now. I will let you know if it works. \$\endgroup\$
    – Giang TT
    Commented Oct 2, 2014 at 8:23
0
\$\begingroup\$

Your answer to the collision problem is true/false. Instead you can differentiate between no collision, penetration of the object and touching the object. Then only disallow movement in the case of penetration, but allow touching.

I'd also suggest you move the collision code out of your tank and GameObject. Tanks and GameObjects both really just contain a collection of collision shapes. Your collision code doesn't care about anything but the shapes (perhaps also their old position, rotation, movement direction and speed).

You don't want to write new collision code every time you add a new kind of actor. This is basically composition versus inheritance at work.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .