I am trying to set up the collision detection on a basic 2d game, player clicks a button sprite moves one step int he corresponding direction.
Currently all my sprites have the collision rectange member:
public Rectangle collisionRect
{
get
{
return new Rectangle(
(int)position.X + collisionOffset,
(int)position.Y + collisionOffset,
frameSize.X - (collisionOffset * 2),
frameSize.Y - (collisionOffset * 2));
}//end get
}//end collisionRect get
this works quite well when I try to check to see if the rectangles for 2 sprites overlap
public Vector2 CheckCollision()
{
for (int i = 0; i < levelWalls.Count; ++i)
{
Sprite wall = levelWalls[i];
//check for collisions
if (wall.collisionRect.Intersects(player.collisionRect))
{
//remove collided sprite
levelWalls.RemoveAt(i);
--i;
}
}
}
however I am running into trouble in the part where I check to see if the player's sprite will run into a wall and stopping it. I know I should be doing something like calculating the players next position and seeing if that position collides with any walls and if it does setting it back to an old position, that seems to be a theory that works in my head, however I am having trouble keeping track of Old Position, Current Position and New Position.
Currently I have my player position updating in it's Update() method:
position += direction;
I then am trying to keep track of old, current and new positions in direction:
public override Vector2 direction
{
get
{
Vector2 inputDirection = Vector2.Zero;
keyboardState = Keyboard.GetState();
if (keyboardState.IsKeyDown(Keys.Left) && prevKeyboardState.IsKeyUp(Keys.Left))
inputDirection.X -= frameSize.X;
if (keyboardState.IsKeyDown(Keys.Right) && prevKeyboardState.IsKeyUp(Keys.Right))
inputDirection.X += frameSize.X;
if (keyboardState.IsKeyDown(Keys.Up) && prevKeyboardState.IsKeyUp(Keys.Up))
inputDirection.Y -= frameSize.Y;
if (keyboardState.IsKeyDown(Keys.Down) && prevKeyboardState.IsKeyUp(Keys.Down))
inputDirection.Y += frameSize.Y;
prevKeyboardState = keyboardState;
oldPOS = position;
newPOS = position + inputDirection;
return inputDirection;
}//end get
} //end Direction
My problem is all three: position, OldPOS and NewPOS are always exactly the same. How can I do this better?
EDIT: with some help I have worked it down to an issue now with my "collision detection" function
public Vector2 CheckCollision(Vector2 oldPOS, Vector2 newPOS)
{
bool collided = false;
for (int i = 0; i < levelWalls.Count; ++i)
{
Sprite wall = levelWalls[i];
//check for collisions
if (wall.collisionRect.Intersects(player.collisionRect))
{
//remove collided sprite
levelWalls.RemoveAt(i);
--i;
collided = true;
playerPOS = oldPOS;
break;
}
}
if (!collided)
playerPOS = newPOS;
return playerPOS;
}
it always execute the if(!collided) to set the position to the new position, even if i do collide and it removes a wall it never sets my position to the old position.
If I however make (!collided) return the old position I can tell my theory works as my sprite will not move at all.. . .
EDIT: AND SOLVED! I needed to create a new colision rectangle for the spot where the sprite will move to, I was using the collision rectangle for where the sprite is! here are the changes:
public Vector2 CheckCollision(Vector2 oldPOS, Vector2 newPOS)
{
Rectangle playerCollisionRect = new Rectangle((int)newPOS.X, (int)newPOS.Y, spriteSize.X, spriteSize.Y);
bool collided = false;
for (int i = 0; i < levelWalls.Count; ++i)
{
Sprite wall = levelWalls[i];
//check for collisions
if (wall.collisionRect.Intersects(playerCollisionRect))
{
collided = true;
playerPOS = oldPOS;
break;
}
}
if (!collided)
playerPOS = newPOS;
return playerPOS;
}