I need help with per pixel collision detection! (collision with rotating sprites)

Hi, people. I already understood the per pixel collision logic, but in my tests, i always got unexpected results. Sorry for my English :slight_smile:
here is the code:

public class Game1 : Game
{
	GraphicsDeviceManager graphics;
	SpriteBatch spriteBatch;

	Color[] textureDataA;
	Color[] textureDataB;

	Texture2D objA;
	Texture2D objB;

	Vector2 objA_Position;
	Vector2 objB_Position;

	Color backgroundColor;

	SpriteFont Text;
	string message;

	public Game1()
	{
		graphics = new GraphicsDeviceManager(this);
		Content.RootDirectory = "Content";
	}

	/// <summary>
	/// Allows the game to perform any initialization it needs to before starting to run.
	/// This is where it can query for any required services and load any non-graphic
	/// related content.  Calling base.Initialize will enumerate through any components
	/// and initialize them as well.
	/// </summary>
	protected override void Initialize()
	{
		// TODO: Add your initialization logic here

		base.Initialize();

		objA_Position = new Vector2(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2);
	}

	/// <summary>
	/// LoadContent will be called once per game and is the place to load
	/// all of your content.
	/// </summary>
	protected override void LoadContent()
	{
		// Create a new SpriteBatch, which can be used to draw textures.
		spriteBatch = new SpriteBatch(GraphicsDevice);

		//TODO: use this.Content to load your game content here 

		objA = Content.Load<Texture2D>("ObjA");
		objB = Content.Load<Texture2D>("ObjB");
		Text = Content.Load<SpriteFont>("Text");

		textureDataA = new Color[objA.Width * objA.Height];
		textureDataB = new Color[objB.Width * objB.Height];

		objA.GetData<Color>(textureDataA);
		objB.GetData<Color>(textureDataB);
	}

	/// <summary>
	/// Allows the game to run logic such as updating the world,
	/// checking for collisions, gathering input, and playing audio.
	/// </summary>
	/// <param name="gameTime">Provides a snapshot of timing values.</param>
	protected override void Update(GameTime gameTime)
	{
		// TODO: Add your update logic here

		objB_Position = new Vector2(Mouse.GetState().Position.X, Mouse.GetState().Position.Y);

		if (CollisionDetection(new Rectangle((int)objB_Position.X, (int)objA_Position.Y, objA.Width, objA.Height),
							   textureDataA,
		                       new Rectangle((int)objB_Position.X, (int)objB_Position.Y, objB.Width, objB.Height),
							   textureDataB) == true)
		{
			backgroundColor = Color.Turquoise;
			message = "true";
		}
		else
		{
			backgroundColor = Color.White;
			message = "false";
		}

		base.Update(gameTime);
	}

	/// <summary>
	/// This is called when the game should draw itself.
	/// </summary>
	/// <param name="gameTime">Provides a snapshot of timing values.</param>
	protected override void Draw(GameTime gameTime)
	{
		GraphicsDevice.Clear(backgroundColor);

		//TODO: Add your drawing code here
		spriteBatch.Begin();
		spriteBatch.Draw(objA, objA_Position, Color.White);
		spriteBatch.Draw(objB, objB_Position, Color.White);
		spriteBatch.DrawString(Text, message, new Vector2(5, 5), Color.Black);
		spriteBatch.End();


		base.Draw(gameTime);
	}

	private bool CollisionDetection(Rectangle rectA, Color[] dataA, Rectangle rectB, Color[] dataB)
	{
		int top = Math.Max(rectA.Top, rectB.Top);
		int bottom = Math.Min(rectA.Bottom, rectB.Bottom);
		int left = Math.Max(rectA.Left, rectB.Left);
		int right = Math.Max(rectA.Right, rectB.Right);

		for (int i = top; i < bottom; i++)
		{
			for (int j = left; j < right; j++)
			{
				Color a = dataA[(j - rectA.Left) + (i - rectA.Top) * objA.Width];
				Color b = dataB[(j - rectB.Left) + (i - rectB.Top) * objB.Width];

				if (a.A != 0 && b.A != 0)
				{
					return (true);
				}
			}
		}

		return (false);
	}
}

}

remove…
(20 characters)

Should be Min. Also, like @PumpkinPudding said you should check that the rectangles actually overlap. You can use Rectangle.Intersect for that.
Other than that, I don’t see any issues (but I haven’t run the code).

However, I would like to recommend to never ever, ever use pixel perfect collision for textures larger than a few pixels. It’s horrible for performance and you can pretty much always get a good result with primitives like circles or rectangles.

1 Like

hey, the code is working perfectly. I am working in a space shooter game. I have asteroids that rotate, for this i need to use the perfect collision, but the problem is that this code doesn’t work properly when exists rotating sprites, i need help to find a properly solution for this. Someone can help me?

I was Reading about this and i found a topic in StackOverflow, the perfect collision may not be the correct way to resolve this, maybe i need primitive shapes and combine them with my sprites, but how can i make this?

if it just rectangle and circle then swept aabb

for other shapes (triangle, rotated rectangle…) SAT

1 Like

Depends on the shape of your sprites, but most commonly a bounding box (rectangle) is used. You can hardcode a rectangle and tweak until it feels right or use some rules for the bounding boxes e.g. the size of the texture or 0.9 * the size of the texture. If that doesn’t work well enough you can use some tooling to export bounding box data (in xml or whatever format you like), then load that into your game. For prototyping I recommend one of the first two options.

Usually it feels better to have seperate bounding boxes on your character for collision with environment and collision with things that hurt the player. Making the bounding box for collision with dangerous objects smaller makes the game feel more fair (even though it’s biased in favor of the player).

1 Like