Sign in to follow this  
Teehee

FIXED: Player collision with multiple objects

Recommended Posts

Teehee    105
I wanted to implement some simple collision detection with rectangles into my project to see if it can handle collision with multiple objects of a list, because I already had a problem with displaying multiple objects of the same type at a time (Though I was able to fix that one myself). Unfortunately the worst I could imagine happened (Besides it not working at all): The game only checks for one wall, and it seems like it just aborts the for loop after that.

Here's the code that checks for the collision, but only checks for the first wall object created:
[CODE]
public void UpdatePlayer(GameTime gameTime)
{
for (int i = WallList.Count - 1; i >= 0; i--)
{
// Disable moving through walls on the right.
Rectangle playerrect = new Rectangle((int)(player.Position.X + player.PlayerAnimations.FrameWidth / 2),
(int)(player.Position.Y - player.PlayerAnimations.FrameHeight / 2), 0, 16);
if (playerrect.Intersects(WallList[i].CollisionBox)) player.AllowRight = false;
else if (!player.AllowRight) player.AllowRight = true;
// Disable moving through walls on the left.
playerrect = new Rectangle((int)(player.Position.X - player.PlayerAnimations.FrameWidth / 2),
(int)(player.Position.Y - player.PlayerAnimations.FrameHeight / 2), 0, 16);
if (playerrect.Intersects(WallList[i].CollisionBox)) player.AllowLeft = false;
else if (!player.AllowLeft) player.AllowLeft = true;
// ^Up
playerrect = new Rectangle((int)(player.Position.X - player.PlayerAnimations.FrameWidth / 2),
(int)(player.Position.Y - 1 - player.PlayerAnimations.FrameHeight / 2), 16, 0);
if (playerrect.Intersects(WallList[i].CollisionBox)) player.AllowUp = false;
else if (!player.AllowUp) player.AllowUp = true;
// ^Down
playerrect = new Rectangle((int)(player.Position.X - player.PlayerAnimations.FrameWidth / 2),
(int)(player.Position.Y + player.PlayerAnimations.FrameHeight / 2), 16, 0);
if (playerrect.Intersects(WallList[i].CollisionBox)) player.AllowDown = false;
else if (!player.AllowDown) player.AllowDown = true;
}

player.Update(ref ProjList, fireball, Woosh, GraphicsDevice.Viewport, gameTime, prevKeyboardState,
curKeyboardState, prevGamePadState, curGamePadState);
}
[/CODE]

If I for example switch [i]for (int i = WallList.Count - 1; i >= 0; i--)[/i] with [i]for (int i = 0; i < WallList.Count; i++)[/i], it only checks for the last wall object created.

Even if I don't think that the problem could lie in the creation of the wall or the wall itself, here's the code used for both:
[spoiler][CODE]
/* The method used to add a rock to the game */
public void AddRock()
{
Rock rock = new Rock();
Animation RockAnim = new Animation();
rock.TexData = new Color[rockanim.Width * rockanim.Height];
rockanim.GetData(rock.TexData);
RockAnim.Initialize(rockanim, Vector2.Zero, 16, 16, 1, 1, 10, Color.White, 1f, true);
int i = (int)(random.NextDouble() * 10);
for (; i > 4; i = (int)(random.NextDouble() * 10)) ;
Vector2 RockPos = new Vector2((float)random.NextDouble() * (-graphics.GraphicsDevice.Viewport.Width / 2),
(float)random.NextDouble() * (-graphics.GraphicsDevice.Viewport.Height / 2));
Rectangle RockRect = new Rectangle((int)(RockPos.X - RockAnim.FrameWidth / 2),
(int)(RockPos.Y - RockAnim.FrameHeight / 2), 16, 16);
rock.Initialize(RockPos, RockRect, RockAnim, i);
WallList.Add(rock);
}
[/CODE]

[CODE]
/* The Rock class */
class Rock
{
public Vector2 Position;
public Animation RockAnimations;
public Color[] TexData;
Rectangle FrameBox;
public Rectangle CollisionBox
{
get { return FrameBox; }
}
public bool Active;
public void Initialize(Vector2 pos, Rectangle rockrect, Animation anim, int variety)
{
Position = pos;
RockAnimations = anim;
FrameBox = rockrect;
RockAnimations.FrameVariety = variety;
RockAnimations.SetPosition(Position);
Active = true;
}
public void Update(GameTime gameTime)
{
RockAnimations.Update(gameTime);
}
public void Draw(SpriteBatch spriteBatch)
{
RockAnimations.Draw(spriteBatch, 0f);
}
}
[/CODE]
[/spoiler]

Please let me know if you find a solution for this, because I'm running out of ideas how to fix this one.

EDIT: Fixed the problem myself! Had to place [i]if (!player.AllowRight || !player.AllowLeft || !player.AllowUp || !player.AllowDown) break;[/i] at the end of the [i]for[/i] loop or else it would just overwrite the AllowX bools for every wall, resulting in making only the last wall that's being checked in the loop affect the players movement.

Share this post


Link to post
Share on other sites
FalconDragoon    485
One thing you might want to consider is using a local set of bools, updating those in the loop and assigning to your player item after the loop. Adding the IF to the top of the loop will prevent overwriting, however it will mean you can only collide with a singe iteration.
However, something like this:
[source lang="csharp"]bool allowUp = true, allowDown = true, allowLeft = true, allowRight = true;
for (int i = WallList.Count - 1; i >= 0; i--)
{
if(!allowUp && !allowDown && !allowLeft && !allowRight) break;
// Disable moving through walls on the right.
Rectangle playerrect = new Rectangle((int)(player.Position.X + player.PlayerAnimations.FrameWidth / 2),
(int)(player.Position.Y - player.PlayerAnimations.FrameHeight / 2), 0, 16);
if (playerrect.Intersects(WallList[i].CollisionBox)) allowRight = false;
else allowRight = allowRight && true;
// Disable moving through walls on the left.
playerrect = new Rectangle((int)(player.Position.X - player.PlayerAnimations.FrameWidth / 2),
(int)(player.Position.Y - player.PlayerAnimations.FrameHeight / 2), 0, 16);
if (playerrect.Intersects(WallList[i].CollisionBox)) allowLeft = false;
else allowLeft = allowLeft && true;
// ^Up
playerrect = new Rectangle((int)(player.Position.X - player.PlayerAnimations.FrameWidth / 2),
(int)(player.Position.Y - 1 - player.PlayerAnimations.FrameHeight / 2), 16, 0);
if (playerrect.Intersects(WallList[i].CollisionBox)) allowUp = false;
else allowUp = allowUp && true;
// ^Down
playerrect = new Rectangle((int)(player.Position.X - player.PlayerAnimations.FrameWidth / 2),
(int)(player.Position.Y + player.PlayerAnimations.FrameHeight / 2), 16, 0);
if (playerrect.Intersects(WallList[i].CollisionBox)) allowDown = false;
else allowDown = allowDown && true;
}
player.AllowUp = allowUp;
//etc...[/source]
Will allow you to check all the walls for collisions in all directions, while also breaking the loop when checking is no longer needed (the case where the player is blocked in all for directions)

Share this post


Link to post
Share on other sites

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