added collision detection functions
authorMatthew Owens <matthew@owens.tech>
Fri, 2 Oct 2020 13:00:06 +0000 (14:00 +0100)
committerMatthew Owens <matthew@owens.tech>
Fri, 2 Oct 2020 13:00:06 +0000 (14:00 +0100)
src/main.c

index e686468..e200376 100644 (file)
@@ -90,6 +90,37 @@ 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)
 {
        pad.v.x = 0;
@@ -112,18 +143,32 @@ static void paddle_update(const Uint8* keyStates, float dt)
 static void ball_update(float dt)
 {
        bool collisionResponded = false;
+       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;
 
-       vline[0].x = ball.r.x + ball.r.w / 2;
-       vline[0].y = ball.r.y + ball.r.h / 2;
-
-       // todo: fix
-       // terniary should be replaced with the size of the ball * normalised vel
-       vline[1].x = vline[0].x + ball.v.x + ( ball.v.x > 0 ? ball.r.w / 2 : 0);
-       vline[1].y = vline[0].y + ball.v.y + ( ball.v.y > 0 ? ball.r.h / 2 : 0);
-
+       // velocity projection start to center of ball
+       vline[0].x = ball.r.x + halfw;
+       vline[0].y = ball.r.y + halfh;
+
+       // setting velocity projection end
+       vline[1].x = vline[0].x + ball.v.x;
+       if(ball.v.x > 0) { vline[1].x += halfw; }
+       else if (ball.v.x < 0) {vline[1].x -= halfw; }
+       vline[1].y = vline[0].y + ball.v.y;
+       if(ball.v.y > 0) { vline[1].y += halfh; }
+       else if (ball.v.y < 0) {vline[1].y -= halfh; }
+
+       // are we going to collide with the paddle? 
+       {
+               int willCollide = lr_collision(vline[0], vline[1], pad.r, NULL);
+               switch(willCollide) {
+                       //TODO: set ball loc to colliding wall, invert vel & skip vel add
+               }
+       }
 
        // screen bounds checks & responses
        if(ball.r.x + ball.r.w > windowSize.x && !collisionResponded){
@@ -223,7 +268,6 @@ static void cleanup()
 
 int main()
 {
-       //TODO: run on primary display
        if(!init()) { return 1; }
 
        while(!quit) {