Collision detection rotated rectangle

I wanted to implement a collision detection for my little car game to improve my java skills. I have an image of a car that i can rotate with left and right key and drive forward/backward. I can detect if a collision of two cars occurs but I can’t determine on wich side that happens and I would like to calculate the corner points of the given rectangle. The problem is I can’t figure out what’s wrong with my code and I need some help. Bare in mind that my math skills are a bit rusty but I thought I calculated this right with simple sine/cosine but maybe I did it completely wrong?
I tested this by drawing the path (encloses picture nicely and rotates with it) but when I calculate the corner points and draw them with drawLine both points don’t get rotated with the picture. Maybe I am doing it too complicated and help is much appreciated.

g2d.drawImage(colorImage, 0, 0, null);

			af = new AffineTransform();
			af.translate(player1.getMapPositionX(), player1.getMapPositionY());
			af.rotate(player1.theta);

			g2d.drawImage(player1.carImage, af, this);

			bf = new AffineTransform();
			bf.translate(player2.getMapPositionX(), player2.getMapPositionY());
			bf.rotate(player2.theta);
			g2d.drawImage(player2.carImage, bf, this);

			Rectangle r1 = new Rectangle(10, 5,
					(int) (player1.carImage.getWidth() * 0.6),
					(int) (player1.carImage.getHeight() * 0.55));
			Path2D.Double path1 = new Path2D.Double();
			path1.append(r1, false);

			AffineTransform t1 = new AffineTransform();
			t1.translate(player1.getMapPositionX(), player1.getMapPositionY());
			t1.rotate(player1.theta);
			path1.transform(t1);

			//g2d.draw(path1);

			Rectangle r2 = new Rectangle(10, 5,
					(int) (player2.carImage.getWidth() * 0.6),
					(int) (player2.carImage.getHeight() * 0.55));
			Path2D.Double path2 = new Path2D.Double();
			path2.append(r2, false);

			AffineTransform t2 = new AffineTransform();
			t2.translate(player2.getMapPositionX(), player2.getMapPositionY());
			t2.rotate(player2.theta);
			path2.transform(t2);
			// g2d.draw(path2);

			r1 = path1.getBounds();
			r2 = path2.getBounds();


			int p1x = (int) r1.getX();
			int p1y = (int) r1.getY();

			int p2x = (int) (p1x + Math.cos(player1.theta * delta)
					* r1.getWidth());
			int p2y = (int) (p1y + Math.sin(player1.theta * delta)
					* r1.getWidth());

			int p3x = (int) (p1x + Math.cos(player1.theta * delta)
					* r1.getHeight());
			int p3y = (int) (p1y + Math.sin(player1.theta * delta)
					* r1.getHeight());

			int p4x = (int) (p3x + Math.cos(player1.theta * delta)
					* r1.getWidth());
			int p4y = (int) (p3y + Math.sin(player1.theta * delta)
					* r1.getWidth());

			g2d.drawLine(p1x, p1y, p2x, p2y);

I have this bad boy written here.

The way it works is, you define a simple rectangle(x,y,width,height). You can rotate that rectangle around specified point in .rotate method.

If you want access to the rotated coordinates, you have x1,y1,x2,y2,x3,y3,x4,y4 which basically represent the rotated corners. You might also want to make a move method or something so that these 8 values get updated when you change x,y values.

Although .translate does that I think.

Here is the code. You will also need to put Rotation class somewhere. It might be pretty helpful too.

PS I have no idea how to make my rect class work again. I tried rewriting it today, but the collision were kinda off. So I thought I would just use this one, because it works magic :smiley:

Ow and to people who say “He isn’t asking for code, he is asking for help”. Well most of you say “Don’t reinvent the wheel” so here you go.

So here is the Rect.java class.


public class Rect {

	public float x, y, width, height, rot, px, py;

	public float x1, y1, x2, y2, x3, y3, x4, y4;

	public Rect(float x, float y, float width, float height) {
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		this.px = x + width / 2;
		this.py = y + height / 2;
		set(x, y, x + width, y, x + width, y + height, x, y + height);
	}

	public Rect(Rect rect) {
		this(rect.x, rect.y, rect.width, rect.height);
		rot = rect.rot;
		px = rect.px;
		py = rect.py;

		x1 = rect.x1;
		y1 = rect.y1;
		x2 = rect.x2;
		y2 = rect.y2;
		x3 = rect.x3;
		y3 = rect.y3;
		x4 = rect.x4;
		y4 = rect.y4;
	}

	private void set(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
		this.x3 = x3;
		this.y3 = y3;
		this.x4 = x4;
		this.y4 = y4;
	}

	public Rect rotate(float px, float py, float rot) {

		this.px = px;
		this.py = py;

		float sin = (float) (Math.sin(Math.toRadians(rot)));
		float cos = (float) (Math.cos(Math.toRadians(rot)));

		float x = this.x - px;
		float y = this.y - py;

		float x1 = cos * (x) - sin * (y) + px;
		float y1 = sin * (x) + cos * (y) + py;

		float x2 = cos * (x + width) - sin * (y) + px;
		float y2 = sin * (x + width) + cos * (y) + py;

		float x3 = cos * (x + width) - sin * (y + height) + px;
		float y3 = sin * (x + width) + cos * (y + height) + py;

		float x4 = cos * (x) - sin * (y + height) + px;
		float y4 = sin * (x) + cos * (y + height) + py;

		set(x1, y1, x2, y2, x3, y3, x4, y4);

		return this;

	}

	public boolean collides(float x, float y) {

		vec2 p = Rotation.point(new vec2(px, py), new vec2(x, y), -this.rot);

		x = p.x;
		y = p.y;

		return collidesSimple(x, y);
	}

	public Rect translate(float x, float y) {
		this.x += x;
		this.y += y;
		px += x;
		py += y;
		x1 += x;
		y1 += y;
		x2 += x;
		y2 += y;
		x3 += x;
		y3 += y;
		x4 += x;
		y4 += y;
		return this;
	}

	public boolean collidesSimple(float x, float y) {
		return x >= this.x && x < this.x + width && y >= this.y && y < this.y + height;
	}

	public boolean collidesSimple(Rect rect) {
		return this.collides(rect.x, rect.y) || this.collides(rect.x + rect.width, rect.y) || this.collides(rect.x + rect.width, rect.y + rect.height) || this.collides(rect.x, rect.y + rect.height);
	}

	public Rect rotate(float rot) {
		return this.rotate(x + width / 2, y + height / 2, rot);
	}

	public void updateSimpleData() {
		x1=x;
		y1=y;
		x2=x+width;
		y2=y;
		x3=x+width;
		y3=y+height;
		x4=x;
		y4=y+height;
	}
	
	public vec2 getCenter() {
		return new vec2(x + getWidth() / 2, y + getHeight() / 2);
	}

	public int getX() {
		return (int) x;
	}

	public int getY() {
		return (int) y;
	}

	public int getWidth() {
		return (int) width;
	}

	public int getHeight() {
		return (int) height;
	}

	public float[] rotateData(float rot, float px, float py) {

		float[] values = new float[8];

		if (rot != 0) {

			float x1 = this.x1 - px;
			float y1 = this.y1 - py;

			float x2 = this.x2 - px;
			float y2 = this.y2 - py;

			float x3 = this.x3 - px;
			float y3 = this.y3 - py;

			float x4 = this.x4 - px;
			float y4 = this.y4 - py;

			float sin = (float) Math.sin(Math.toRadians(rot));
			float cos = (float) Math.cos(Math.toRadians(rot));

			int pos = 0;

			values[pos++] = cos * x1 - sin * y1 + px;
			values[pos++] = sin * x1 + cos * y1 + py;

			values[pos++] = cos * x2 - sin * y2 + px;
			values[pos++] = sin * x2 + cos * y2 + py;

			values[pos++] = cos * x3 - sin * y3 + px;
			values[pos++] = sin * x3 + cos * y3 + py;

			values[pos++] = cos * x4 - sin * y4 + px;
			values[pos++] = sin * x4 + cos * y4 + py;
		} else {
			int pos = 0;

			values[pos++] = x1;
			values[pos++] = y1;
			values[pos++] = x2;
			values[pos++] = y2;
			values[pos++] = x3;
			values[pos++] = y3;
			values[pos++] = x4;
			values[pos++] = y4;

		}

		return values;
	}

	public static boolean collides(Rect r1, Rect r2) {
		return r1.collidesSimple(r2) || r2.collidesSimple(r1);
	}

}

And here is the Rotation class used in .collides(float, float) method.


public class Rotation {

	public static int angle(vec2 pivot, vec2 point) {

		float xdiff = pivot.x - point.x;
		float ydiff = pivot.y - point.y;
		
		float angle = (float) ((Math.atan2(xdiff, ydiff)) * 180 / Math.PI);
		
		return -(int)angle;
	}
	
	public static float angle(float x0, float y0, float x1, float y1) {
		return angle(new vec2(x0, y0), new vec2(x1, y1));
	}
	
	public static vec2 point(vec2 pivot, vec2 point, float rotation) {
		
		float rot = (float)(1f / 180 * rotation * Math.PI);
		
		float x = point.x - pivot.x;
		float y = point.y - pivot.y;
		
		float newx = (float)(x * Math.cos(rot) - y * Math.sin(rot));
		float newy = (float)(x * Math.sin(rot) + y * Math.cos(rot));
		
		
		newx += pivot.x;
		newy += pivot.y;
		
		return new vec2(newx, newy);
	}
	
}

@trollwarrior1

thanks for the reply. I just looked into it and it seems very convenient to use. I probably will implement this but still am a bit confused why my method didn’t work.