# Collision Detection

• (2 Pages)
• 1
• 2

## 19 Replies - 3457 Views - Last Post: 02 May 2011 - 08:53 AM

Reputation: 142
• Posts: 664
• Joined: 16-January 10

# Collision Detection

Posted 01 April 2011 - 08:19 AM

I know this may seem like childs play to you guys but I've been having trouble with this for a few hours and I just give up. I have this level:

My player sprite needs to check for collisions with each Block and Wall tile (there is only one Block and several wall tiles in the above example), now I've only started to test on the Blocks so far and I can't figure out how to keep the player's position stable on all sides of the block. I will also need to use the exact same collision check for the Wall tiles. Here's what I have:

```public void CollisionDetection(KeyboardState keyboardState, GamePadState gamePadState)
{
Player p = gameLevel.LevelPlayer;

foreach (Block b in gameLevel.Blocks)
{

if (b.Bounds.Left > p.Bounds.Right || b.Bounds.Right < p.Bounds.Left
|| b.Bounds.Top > p.Bounds.Bottom || b.Bounds.Bottom < p.Bounds.Top)
{
p.Position = new Vector2(//Something);
}
}

/*
foreach (Wall w in gameLevel.Walls)
{

}
*/
}

```

What am I missing?

Is This A Good Question/Topic? 0

## Replies To: Collision Detection

### #2 bonyjoe

Reputation: 178
• Posts: 548
• Joined: 08-September 10

## Re: Collision Detection

Posted 01 April 2011 - 09:13 AM

If you know which direction he is going in then you know where he is hitting the block if he is intersecting

So you could check like so

```if(player.rect.intersects(wall.rect))
{
if(playerdirection == right)
player.rect.right = wall.rect.left; (or whatever calculations you would need to set your player position to mimic this)
if(playerdirection == etc)
player = etc;
}
```

If travelling diagonal say up/left your code would just execute both the up and the left checks one after the other.

This is basic and not the best way to do it, but it should be fine for what you require.

Reputation: 142
• Posts: 664
• Joined: 16-January 10

## Re: Collision Detection

Posted 01 April 2011 - 09:40 AM

bonyjoe, on 01 April 2011 - 09:13 AM, said:

If you know which direction he is going in then you know where he is hitting the block if he is intersecting

So you could check like so

```if(player.rect.intersects(wall.rect))
{
if(playerdirection == right)
player.rect.right = wall.rect.left; (or whatever calculations you would need to set your player position to mimic this)
if(playerdirection == etc)
player = etc;
}
```

If travelling diagonal say up/left your code would just execute both the up and the left checks one after the other.

This is basic and not the best way to do it, but it should be fine for what you require.

This works fine for what I have as long as I don't hold 2 diagonal keys together when colliding with the block/wall tile otherwise there will be some glitches. It's probably due to the limitation of the amount of player sprites I have since I don't have any diagonals.

### #4 Writers Block

Reputation: 6
• Posts: 19
• Joined: 13-March 11

## Re: Collision Detection

Posted 01 April 2011 - 01:38 PM

Consider setting your 'level' up as a grid with, say, '1' to represent a wall block and zero open space.

You can then check if he is trying to enter a specific tile.

Say screen width is 320, a tile is 16 and mouseX position is 272: 272/16 gives you his position for the grid.

Pretty sure I made a pacman game in blitz basic that used this method - long time ago though. It did work.

Reputation: 142
• Posts: 664
• Joined: 16-January 10

## Re: Collision Detection

Posted 01 April 2011 - 01:56 PM

Writers Block, on 01 April 2011 - 01:38 PM, said:

Consider setting your 'level' up as a grid with, say, '1' to represent a wall block and zero open space.

You can then check if he is trying to enter a specific tile.

Say screen width is 320, a tile is 16 and mouseX position is 272: 272/16 gives you his position for the grid.

Pretty sure I made a pacman game in blitz basic that used this method - long time ago though. It did work.

Unfortunately the Blocks and Wall tiles are actually layered on top of the existing tile map you suggested, and I can use that method for the Blocks and Walls with each other and the floor tiles of the map, but the Player sprite doesn't move along in tile map increments so it's not feasible.

### #6 bonyjoe

Reputation: 178
• Posts: 548
• Joined: 08-September 10

## Re: Collision Detection

Posted 02 April 2011 - 06:33 AM

What happens when you walk diagonally into a block?

You may be better off doing a collision check ahead of time, so check if the player will have collided after he has taken his step, if he will have set his position accordingly. Rather than what I assume you're doing now which is moving him then checking if he is collided and moving him back to not collided.

Reputation: 142
• Posts: 664
• Joined: 16-January 10

## Re: Collision Detection

Posted 02 April 2011 - 08:55 AM

Actually I am doing it Collision Detection then Movement but I'll just show you:

HandleInput() which is put in the Update by the Screenmanager for any screen
```/// <summary>
/// Lets the game respond to player input. Unlike the Update method,
/// this will only be called when the gameplay screen is active.
/// </summary>
public override void HandleInput(InputState input)
{
if (input == null)
throw new ArgumentNullException("input");

// Look up inputs for the active player profile.
int playerIndex = (int)ControllingPlayer.Value;

KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];

// The game pauses either if the user presses the pause button, or if
// they unplug the active gamepad. This requires us to keep track of
// whether a gamepad was ever plugged in, because we don't want to pause
// on PC if they are playing with a keyboard and have no gamepad at all!

{
}
else
{
CollisionDetection(input);

// Otherwise move the player position.
Vector2 movement = Vector2.Zero;

{
movement.Y--;
gameLevel.LevelPlayer.ChangeDirection(0);
}
{
movement.Y++;
gameLevel.LevelPlayer.ChangeDirection(1);
}
{
movement.X--;
gameLevel.LevelPlayer.ChangeDirection(2);
}
{
movement.X++;
gameLevel.LevelPlayer.ChangeDirection(3);
}

if (movement.Length() > 1)
movement.Normalize();

gameLevel.LevelPlayer.Position += movement * 3;
gameLevel.LevelPlayer.Bounds = new Rectangle((int)gameLevel.LevelPlayer.Position.X, (int)gameLevel.LevelPlayer.Position.Y,
gameLevel.LevelPlayer.Bounds.Width, gameLevel.LevelPlayer.Bounds.Height);
}
}

```

CollisionDetection() for Player
```public void CollisionDetection(InputState input)
{
Player p = gameLevel.LevelPlayer;

// Look up inputs for the active player profile.
int playerIndex = (int)ControllingPlayer.Value;

KeyboardState prevKeyboardState = input.LastKeyboardStates[playerIndex];
KeyboardState curKeyboardState = input.CurrentKeyboardStates[playerIndex];

foreach (Block b in gameLevel.Blocks)
{
if (p.Bounds.Intersects(b.Bounds))
{
if (p.Direction == 0)
p.Position = new Vector2(p.Position.X, b.Bounds.Bottom);
if (p.Direction == 1)
p.Position = new Vector2(p.Position.X, b.Bounds.Top - p.Bounds.Height);
if (p.Direction == 2)
p.Position = new Vector2(b.Bounds.Right, p.Position.Y);
if (p.Direction == 3)
p.Position = new Vector2(b.Bounds.Left - p.Bounds.Width, p.Position.Y);

if ((prevKeyboardState.IsKeyDown(Keys.Space) && curKeyboardState.IsKeyUp(Keys.Space)) ||
{
//MoveBlock(b, p.Direction);
}
}
}

```

Reputation: 142
• Posts: 664
• Joined: 16-January 10

## Re: Collision Detection

Posted 21 April 2011 - 04:31 AM

Hi, I've updated my game to include 8 directional movement for my Player, or at least I have 4 directional sprites (Up, Down, Left, Right) and it now works with the diagonals. I decided to do this in order to solve the problem I was having with multiple directions being used when intersecting the bounds of an object. Only problem is I haven't got it to fully work.

```foreach (Wall w in gameLevel.Walls)
{
if (p.Bounds.Intersects(w.Bounds))
{
switch (p.Direction)
{
case 0: // Up
p.Position = new Vector2(p.Position.X, w.Bounds.Bottom);
break;
case 1: // Up Left
if ((p.Bounds.Top < w.Bounds.Bottom) && (p.Bounds.Right > w.Bounds.Left))
p.Position = new Vector2(p.Position.X, w.Bounds.Bottom);
else if ((p.Bounds.Left < w.Bounds.Right) && (p.Bounds.Top < w.Bounds.Bottom))
p.Position = new Vector2(w.Bounds.Right, p.Position.Y);
else
p.Position = new Vector2(p.Position.X, w.Bounds.Bottom);
break;
case 2: // Up Right
if ((p.Bounds.Top < w.Bounds.Bottom) && (p.Bounds.Left < w.Bounds.Right))
p.Position = new Vector2(p.Position.X, w.Bounds.Bottom);
else if ((p.Bounds.Right > w.Bounds.Left) && (p.Bounds.Top > w.Bounds.Bottom))
p.Position = new Vector2(w.Bounds.Left - p.Bounds.Width, p.Position.Y);
else
p.Position = new Vector2(p.Position.X, w.Bounds.Bottom);
break;
case 3: // Down
p.Position = new Vector2(p.Position.X, w.Bounds.Top - p.Bounds.Height);
break;
case 4: // Down Left
if (p.Bounds.Bottom > w.Bounds.Top)
p.Position = new Vector2(p.Position.X, w.Bounds.Top - p.Bounds.Height);
break;
case 5: // Down Right
if (p.Bounds.Bottom > w.Bounds.Top)
p.Position = new Vector2(p.Position.X, w.Bounds.Top - p.Bounds.Height);
break;
case 6: // Left
p.Position = new Vector2(w.Bounds.Right, p.Position.Y);
break;
case 7: // Right
p.Position = new Vector2(w.Bounds.Left - p.Bounds.Width, p.Position.Y);
break;
}
}
}

```

Now I've just been working on getting the Up and Left, Up and Right cases (1 and 2) to work but with both cases there are at least 2 sides of the Wall object that could be affected at any given time. I can only get it to work one of the 2 possible scenarios.

Case 0: The Player is below the wall and touches the Bottom barrier while pressing Up

Case 1: A) The Player is below the wall and touches the Bottom barrier and decides to walk Left while still pressing Up.
Case 1: B ) The Player is moving Left into the Right-hand barrier of the wall and moves Up while still moving Left

Case 2: A) The Player is below the wall and touches the Bottom barrier and decides to walk Right while still pressing Up.
Case 2: B ) The Player is moving Right into the Left-hand barrier of the wall and moves Up while still moving Right

Case 3: The Player is above the wall and touches the Top barrier while pressing Down

Case 4: A) The Player is above the wall and touches the Top barrier and decides to walk Left while still pressing Down.
Case 4: B ) The Player is moving Left into the Right-hand barrier of the wall and moves Down while still moving Left

Case 5: A ) The Player is above the wall and touches the Top barrier and decides to walk Right while still pressing Down.
Case 5: B ) The Player is moving Right into the Left-hand barrier of the wall and moves Down while still moving Right

Case 6: The Player is moving Left into the Right-hand barrier of the wall.

Case 7: The Player is moving Right into the Left-hand barrier of the wall.

This post has been edited by ShadowsEdge19: 21 April 2011 - 04:32 AM

### #9 frostyraver

Reputation: 13
• Posts: 195
• Joined: 21-April 09

## Re: Collision Detection

Posted 22 April 2011 - 04:29 AM

What I'm currently doing is working with layered tile system.

9 = Top height
8
7
6
5 = Mid ground, walkable player tile
4
3
2
1
0 = Bottom ground

```mapData[x, y, LayerNumber]

```

Use that, create a few maps on top of each other.

Then for a player collision do something like

```// right
if (mapData[player.pos.x + 1, y, 5].collision != collision.solid)
player.pos.x += 10;

```

Layer 5 = the player one and that's all you would have to scan, or you could add in a loop for other layers like so:

```for (int t = 0; t < 10; t++)
{
// right
if (mapData[player.pos.x + 1, y, t].collision != collision.solid)
player.pos.x += 10;
}

```

Of coarse you would fill out left, right, and stuff too.

Do it as an ELSE IF statement so you don't get it tracking several coordinates at once, only what's first pressed!

Here's a screen shot of it in action. I have trees on layer 6 so my player goes UNDER, 10 layers is plenty but as long as I don't draw a graphic on them I won't get a performance loss, well much of one.

Also as you can see the tiles, break and detect the water 'splash' I have going, the water is the base of layer 4 those dirt tiles are layer 5, I just drew the player after the tile to bring it to front, then drew tiles 6 and up on top.

It's pretty neat.

This post has been edited by frostyraver: 22 April 2011 - 05:02 AM

Reputation: 142
• Posts: 664
• Joined: 16-January 10

## Re: Collision Detection

Posted 22 April 2011 - 07:11 AM

Okay I have the various Floor Tiles on Layer 1:

Layer 1: Floor Tiles:-
• Smooth (Icy) that is the default tile;
• Rough (looks like icy cobble stones) that stop the Blocks in their tracks when moving
• Directional Arrows, smooth tiles that redirect the Block in the direction that it is pointed in, so movement continues in different direction.
• Goal Tiles, smooth tiles that when a Block stops upon it they trigger an event, but only if a Block can stop on it as they will still act like smooth tiles the rest of the time.

Layer 2: Player
Layer 3: Wall Tiles
Layer 4: Block Tiles

Is that correct?

Could I see what your collision() method is doing in mapData? Is that an Object or just a List?

### #11 frostyraver

Reputation: 13
• Posts: 195
• Joined: 21-April 09

## Re: Collision Detection

Posted 22 April 2011 - 07:39 AM

ShadowsEdge19, on 22 April 2011 - 07:11 AM, said:

Okay I have the various Floor Tiles on Layer 1:

Layer 1: Floor Tiles:-
• Smooth (Icy) that is the default tile;
• Rough (looks like icy cobble stones) that stop the Blocks in their tracks when moving
• Directional Arrows, smooth tiles that redirect the Block in the direction that it is pointed in, so movement continues in different direction.
• Goal Tiles, smooth tiles that when a Block stops upon it they trigger an event, but only if a Block can stop on it as they will still act like smooth tiles the rest of the time.

Layer 2: Player
Layer 3: Wall Tiles
Layer 4: Block Tiles

Is that correct?

Could I see what your collision() method is doing in mapData? Is that an Object or just a List?

The way you build the floor is up to you, does the user dig into the ground? that's why I like to start middle, so if need be you can dig into the ground, the best thing with this method is you can set it to 10 layers and have it all non collision then use the layers you want.

My collision is much like the 2d platformer tutorial since I haven't manage to find a better way.

I'll walk you through what I refer to please KEEP IN MIND I use a tile sheet and a lot of my own data you should be able to get the idea from this:

Tile_Data.cs
```/// <summary>
/// Controls the collision detection and response behavior of a tile.
/// </summary>
enum TileCollision
{
// Passable
Passable = 0,

// Impassable tiles
Impassable = 1,
}

```

I don't need the platform because this is a top down game, and this seams to work awesomely

```    enum TileDestructable
{
// Passable
Destructible = 0,

// Impassable tiles
Indestructible = 1,
}

```

If we can destroy the tiles. Or not, so for an NPC I would set them to indestructible so my bombs can't blow them up.

```    struct Tile_Data
{
public TileCollision Collision;
public TileDestructable Destructible;
public string TileSheetName;
public int TileSheetIndex;
public string TileName;
public int TileHP;
public char TileChar;
public const int Width = 32;
public const int Height = 32;

public static Vector2 Size = new Vector2(Width, Height);

public Tile_Data(TileCollision collision, string tilesheetname, int tilesheetindex, string tilename, int tilehp, char tilechar, TileDestructable destructible)
{
Collision = collision;
TileSheetName = tilesheetname;
TileSheetIndex = tilesheetindex;
TileName = tilename;
TileHP = tilehp;
TileChar = tilechar;
Destructible = destructible;
}
}

```

Assign's a tile stats, HP of a tile so we can take a few hits to destroy it and what not.

Game_Level.cs

Lets say we wanted to load in a grass tile at 100, 100 on layer 5 because our player walks on this:
```mapdata[100, 100, 5] = LoadTownGroundTile('G', 100, 100, 1, 1);

A Grass Tile:
[code]
public Tile_Data LoadTownGroundTile(char tileType, int x, int y, int Length, int Height) // Length and Height will extend 1 over on the sprite sheet to do 4x4 tiles.
{
// DEBUGGAN
switch (tileType)
{
// Grass
case 'G':
return LoadDestroyableTerrains1x1(TileCollision.Passable, 1060, tileType, x, y, Length, Height, 10, "Grass Dirt", TileDestructable.Destructible);
}
}

```

Then it goes to here:

```        // Load Destroyable Terrains
private Tile_Data LoadDestroyableTerrains1x1(TileCollision tilecollision, int tileNumber, char tileType, int x, int y, int Length, int Height, int RNGMAX, string TileName, TileDestructable destructible)
{
// Randomly pick a tile for randomness
int rand = rng.Next(0, RNGMAX);
int tileSheetIndex = tileNumber + rand;
return new Tile_Data(tilecollision, "Tile_Main_Terrains_1x1", tileSheetIndex, TileName, 1, tileType, destructible);
}

```

It's a lot of code but it's SO flexible and works so easy it's pretty simple when you read it. There's a performance issue if you are trying to draw 10 layers of tile on screen at once, you could only draw the first tile down by REVERSING the layer for loop so it starts from layer 9 and goes down, because, unless it's transparent we want to only draw what we see, the data under those tiles will still have the properties (HP and what not) we just don't want to display to make less work on the game.

I'm no where near an expert, I myself are learning as I go, if someone figures out a better way to do some things let me know please. It's always good to discuss efficiency.

### #12 frostyraver

Reputation: 13
• Posts: 195
• Joined: 21-April 09

## Re: Collision Detection

Posted 22 April 2011 - 07:50 AM

Sorry I got off topic, Here's another reply with my collision Data

Player_Main

```// Checks the collisions
private void HandleCollisions(GameTime gameTime)
{
// Get the player1's bounding rectangle and find neighboring tiles.
Rectangle bounds = BoundingRectangle;
int leftTile = (int)Math.Floor((float)bounds.Left / Tile_Data.Width);
int rightTile = (int)Math.Ceiling(((float)bounds.Right / Tile_Data.Width));
int topTile = (int)Math.Floor((float)bounds.Top / Tile_Data.Height);
int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile_Data.Height));

```

Setting up the bounds, and find some tile for our player.

```            // For each potentially colliding tile,
for (int y = topTile; y <= bottomTile; y++)
{
for (int x = leftTile; x <= rightTile; x++)
{

```

Start to loop through every tile.
```                    // If this tile is collidable,
try
{

```

I like try/catch statements, I think this was old code I need to clean up

```                        if (game_level.MapData[x, y, 5].Collision == TileCollision.Impassable || game_level.MapData[x, y, 4].Collision == TileCollision.Impassable)
{

```

This says "If map data layer 5 is impassible or map data layer 4 is impassible

```                            // Determine collision depth and magnitude.
Rectangle tileBounds = game_level.GetBounds(x, y);
Vector2 depth = Program_RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
if (depth != Vector2.Zero)
{
float absDepthX = Math.Abs(depth.X);
float absDepthY = Math.Abs(depth.Y);

// Resolve the collision along the shallow axis.
if (absDepthY < absDepthX)
{

// Ignore platforms, unless we are on the ground.
if (game_level.MapData[x, y, 5].Collision == TileCollision.Impassable)
{

```

No need to alter the platformers code here untill you hit the collision so you can check the layer 5 for impassible, it's the checker for Y collision

```                                        // Resolve the collision along the Y axis.
Position = new Vector2(Position.X, Position.Y + depth.Y);

// Perform further collisions with the new bounds.
bounds = BoundingRectangle;
}

}

else if (game_level.MapData[x, y, 5].Collision == TileCollision.Impassable || game_level.MapData[x, y, 4].Collision == TileCollision.Impassable)
{

```

X collision checker
```                                    // Resolve the collision along the X axis.
Position = new Vector2(Position.X + depth.X, Position.Y);

// Perform further collisions with the new bounds.
bounds = BoundingRectangle;
}
}
}

}
catch (Exception)
{
position.X = game_level.playerStartX;
position.Y = game_level.playerStartY;
}
}
}
}

```

If there's problems move the player position to the start so if we go out of bounds, it's kinda last minute coding which I'm going to go through and fix up.

I know it's UGLY but as I said I'm learning, and a lot of old code from months ago that I'm fixing up. Should be all done this weekend.

Edit: Messed up the code tags had them keybound to my g510.

This post has been edited by frostyraver: 22 April 2011 - 07:54 AM

Reputation: 142
• Posts: 664
• Joined: 16-January 10

## Re: Collision Detection

Posted 22 April 2011 - 10:59 AM

I won't recreate whole portions of my game to use your method of Layering but I have gotten a few ideas on how to modify my current methods, I will have to restrict Player movement to only 4 directions and make sure when a directional button is pressed while another is active that it ignores the new one. This is the only way I can think of to help since my Player sprite isn't part of the level map tiles and it is also smaller in overall size than a single tile as well. I think I can use this method with the current setup.

### #14 frostyraver

Reputation: 13
• Posts: 195
• Joined: 21-April 09

## Re: Collision Detection

Posted 22 April 2011 - 11:16 AM

I have a player class file that tracks the movements of my player.

I need smooth movements, so this works fine.

Thats great you got an idea, that's the type of spirit that will get you far, if you can work out a way that's different, that's still learning programming.

Reputation: 142
• Posts: 664
• Joined: 16-January 10

## Re: Collision Detection

Posted 22 April 2011 - 06:29 PM

It took me ages but after a long process of elimination I found the correct sequence of current and previous keyboardStates to stop Player movement with multiple directions being pressed at the same time.

So if Up is being pressed and the Down button is selected it will only stop the Player from moving, although ignoring the new button press would be perfect I will settle for movement pauses instead.

```/// <summary>
/// Lets the game respond to player input. Unlike the Update method,
/// this will only be called when the gameplay screen is active.
/// </summary>
public override void HandleInput(InputState input, GameTime gameTime)
{
if (input == null)
throw new ArgumentNullException("input");

// Look up inputs for the active player profile.
int playerIndex = (int)ControllingPlayer.Value;

// Otherwise move the player position.
Vector2 movement = Vector2.Zero;
Player p = gameLevel.LevelPlayer;

KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
KeyboardState lastKeyboardState = input.LastKeyboardStates[playerIndex];

// The game pauses either if the user presses the pause button, or if
// they unplug the active gamepad. This requires us to keep track of
// whether a gamepad was ever plugged in, because we don't want to pause
// on PC if they are playing with a keyboard and have no gamepad at all!

{
}
else
{
{
if (keyboardState.IsKeyDown(Keys.Up) && !(lastKeyboardState.IsKeyDown(Keys.Down)
|| lastKeyboardState.IsKeyDown(Keys.Left) || lastKeyboardState.IsKeyDown(Keys.Right)))
{
movement.Y--;
p.ChangeDirection(0);
}
else if (keyboardState.IsKeyDown(Keys.Down) && !(lastKeyboardState.IsKeyDown(Keys.Up)
|| lastKeyboardState.IsKeyDown(Keys.Left) || lastKeyboardState.IsKeyDown(Keys.Right)))
{
movement.Y++;
p.ChangeDirection(1);
}
else if (keyboardState.IsKeyDown(Keys.Left) && !(lastKeyboardState.IsKeyDown(Keys.Up)
|| lastKeyboardState.IsKeyDown(Keys.Down) || lastKeyboardState.IsKeyDown(Keys.Right)))
{
movement.X--;
p.ChangeDirection(2);
}
else if (keyboardState.IsKeyDown(Keys.Right) && !(lastKeyboardState.IsKeyDown(Keys.Up)
|| lastKeyboardState.IsKeyDown(Keys.Down) || lastKeyboardState.IsKeyDown(Keys.Left)))
{
movement.X++;
p.ChangeDirection(3);
}
}
else
{
{
movement.Y--;
p.ChangeDirection(0);
}
{
movement.Y++;
p.ChangeDirection(1);
}
{
movement.X--;
p.ChangeDirection(2);
}
{
movement.X++;
p.ChangeDirection(3);
}
}

if (movement.Length() > 1)
movement.Normalize();

p.Position += movement * 3;
p.Bounds = new Rectangle((int)p.Position.X, (int)p.Position.Y, p.Bounds.Width, p.Bounds.Height);

CollisionDetection(input, gameTime);
}
}

```