From: Matthew Owens <matthew@owens.tech>
Date: Fri, 2 Oct 2020 14:26:37 +0000 (+0100)
Subject: moved collisions to their own file & added ball/paddle collision response
X-Git-Url: https://git.owens.tech/assets/112-editable-focus.html/assets/112-editable-focus.html/git?a=commitdiff_plain;h=ffc97facfdcc5fecac3418fcdd869b9d61f7999b;p=pong.git

moved collisions to their own file & added ball/paddle collision response
---

diff --git a/src/collision.c b/src/collision.c
new file mode 100644
index 0000000..4682ece
--- /dev/null
+++ b/src/collision.c
@@ -0,0 +1,32 @@
+#include "collision.h"
+
+bool ll_collision(float x1, float y1, float x2, float y2,
+	   float x3, float y3, float x4, float y4, Vec2df *intersect)
+{
+	float uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) /
+			   ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
+	float uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) /
+			   ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
+
+	if(intersect) {
+		intersect->x = x1 + (uA * (x2-x1));
+		intersect->y = y1 + (uB * (y2-y1));
+	}
+
+	return (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1);
+}
+
+/*
+ * (v)box / line collision
+ * returns 0 on no collision, 1/2/3/4 on left/right/top/bottom
+ */
+int lr_collision(Vec2df start, Vec2df end, SDL_Rect r, Vec2df *i) {
+	if(ll_collision(start.x, start.y, end.x, end.y, r.x, r.y, r.x, r.y + r.h, i))
+		return 1; //left
+	if(ll_collision(start.x, start.y, end.x, end.y, r.x + r.w, r.y, r.x + r.w, r.y + r.h, i))
+		return 2; //right
+	if(ll_collision(start.x, start.y, end.x, end.y, r.x, r.y, r.x + r.w, r.y , i))
+		return 3; //top
+	if(ll_collision(start.x, start.y, end.x, end.y, r.x, r.y + r.h, r.x + r.w, r.y + r.h, i))
+		return 4; //bottom
+}
diff --git a/src/collision.h b/src/collision.h
new file mode 100644
index 0000000..38111a8
--- /dev/null
+++ b/src/collision.h
@@ -0,0 +1,8 @@
+#pragma once
+#include <SDL2/SDL.h>
+#include <stdbool.h>
+#include "vec2d.h"
+
+bool ll_collision(float x1, float y1, float x2, float y2,
+	   float x3, float y3, float x4, float y4, Vec2df *intersect);
+int lr_collision(Vec2df start, Vec2df end, SDL_Rect r, Vec2df *i);
diff --git a/src/main.c b/src/main.c
index e200376..8eb04c4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,16 +4,8 @@
 #include <SDL2/SDL.h>
 #include <stdbool.h>
 #include "timestep.h"
-
-typedef struct Vec2di {
-	int x;
-	int y;
-} Vec2di;
-
-typedef struct Vec2df {
-	float x;
-	float y;
-} Vec2df;
+#include "collision.h"
+#include "vec2d.h"
 
 typedef struct Colour {
 	Uint8 r;
@@ -90,36 +82,6 @@ static void vbox_render(const Vbox *b)
 	SDL_RenderFillRect(renderer, &b->r);
 }
 
-static bool ll_collision(float x1, float y1, float x2, float y2,
-	   float x3, float y3, float x4, float y4, Vec2df *intersect)
-{
-	float uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) /
-			   ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
-	float uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) /
-			   ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
-
-	if(intersect) {
-		intersect->x = x1 + (uA * (x2-x1));
-		intersect->y = y1 + (uB * (y2-y1));
-	}
-
-	return (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1);
-}
-
-/*
- * (v)box / line collision
- * returns 0 on no collision, 1/2/3/4 on left/right/top/bottom
- */
-static int lr_collision(Vec2df start, Vec2df end, SDL_Rect r, Vec2df *i) {
-	if(ll_collision(start.x, start.y, end.x, end.y, r.x, r.y, r.x, r.y + r.h, i))
-		return 1; //left
-	if(ll_collision(start.x, start.y, end.x, end.y, r.x + r.w, r.y, r.x + r.w, r.y + r.h, i))
-		return 2; //right
-	if(ll_collision(start.x, start.y, end.x, end.y, r.x, r.y, r.x + r.w, r.y , i))
-		return 3; //top
-	if(ll_collision(start.x, start.y, end.x, end.y, r.x, r.y + r.h, r.x + r.w, r.y + r.h, i))
-		return 4; //bottom
-}
 
 static void paddle_update(const Uint8* keyStates, float dt)
 {
@@ -146,10 +108,6 @@ static void ball_update(float dt)
 	float halfw = ball.r.w / 2;
 	float halfh = ball.r.h / 2;
 
-	// applying velocity
-	ball.r.x += ball.v.x * dt;
-	ball.r.y += ball.v.y * dt;
-
 	// velocity projection start to center of ball
 	vline[0].x = ball.r.x + halfw;
 	vline[0].y = ball.r.y + halfh;
@@ -165,17 +123,41 @@ static void ball_update(float dt)
 	// are we going to collide with the paddle? 
 	{
 		int willCollide = lr_collision(vline[0], vline[1], pad.r, NULL);
+		// left/right/top/bottom
 		switch(willCollide) {
 			//TODO: set ball loc to colliding wall, invert vel & skip vel add
+			case 1:
+				ball.r.x = pad.r.x - ball.r.w;
+				ball.v.x *= -1;
+				break;
+			case 2:
+				ball.r.x = pad.r.x + pad.r.w;
+				ball.v.x *= -1;
+				break;
+			case 3:
+				ball.r.y = pad.r.y - ball.r.h;
+				ball.v.y *= -1;
+				break;
+			case 4:
+				ball.r.y = pad.r.y + pad.r.h;
+				ball.v.y *= -1;
+				break;
 		}
+		if(willCollide != 0) { collisionResponded = true; }
+	}
+
+	// applying velocity if needed
+	if(!collisionResponded) {
+		ball.r.x += ball.v.x * dt;
+		ball.r.y += ball.v.y * dt;
 	}
 
 	// screen bounds checks & responses
-	if(ball.r.x + ball.r.w > windowSize.x && !collisionResponded){
+	if(ball.r.x + ball.r.w > windowSize.x){
 		ball.r.x = windowSize.x - ball.r.w;
 		ball.v.x *= -1;
 	}
-	if(ball.r.y + ball.r.h > windowSize.y && !collisionResponded){
+	if(ball.r.y + ball.r.h > windowSize.y){
 		ball.r.y = windowSize.y - ball.r.h;
 		ball.v.y *= -1;
 	}
diff --git a/src/vec2d.h b/src/vec2d.h
new file mode 100644
index 0000000..664718b
--- /dev/null
+++ b/src/vec2d.h
@@ -0,0 +1,12 @@
+#pragma once
+
+typedef struct Vec2di {
+	int x;
+	int y;
+} Vec2di;
+
+typedef struct Vec2df {
+	float x;
+	float y;
+} Vec2df;
+