A different take on collision detection

So this was an interesting experience, I didn’t follow the tutorial that closely cause I’m a bit more advanced in experience than this section was targeted at but it was kinda fun. I actually went another direction with collision entirely however to account for the radius of the circle over treating it like a square with a bit of maths taking the 2d coordinates of the circle and edges of the rect and checking if their distance is less than the radius of the circle. it’s a bit more intense math wise using sqrt and pow many times each loop but I cut back on calls when further away by checking if the circle and rectangle are anywhere close enough to potentially collide in the first place. This could be simplified massively if you turn the “axe” into a circle also cause you would then only need to check if the range is less than each radius added together

My final product :slight_smile:

#include "raylib.h"
#include "raymath.h"

char gameOverText[] = "Game Over\nPress R to Restart";

int width{500};
int height{350};

int circlePosX{100};
int circlePosY{100};
int circleRadius{25};

int rectPosX{width/2};
int rectPosY{0};
int rectSize{50};
int rectDirection{5};

int moveSpeed{3};
int runMultiplier{3};

bool gameOver{};

bool isStrafing() {
    return ((IsKeyDown(KEY_W) || IsKeyDown(KEY_S)) && (IsKeyDown(KEY_A) || IsKeyDown(KEY_D)));
}

int getSpeed() {
    if(IsKeyDown(KEY_LEFT_SHIFT)) { // Running?
        return isStrafing() ? (moveSpeed * runMultiplier) * 0.8 : moveSpeed * runMultiplier;
    } else {
        return isStrafing() ? moveSpeed * 0.8 : moveSpeed;
    }
}

int limitBounds(int input, int max) {
    return Clamp(input, 0 + circleRadius, max - circleRadius);
}

void HandleInput() {
    if(IsKeyDown(KEY_D)) {
        circlePosX = limitBounds(circlePosX + getSpeed(), width);
    }
    if(IsKeyDown(KEY_A)) {
        circlePosX = limitBounds(circlePosX - getSpeed(), width);
    }
    if(IsKeyDown(KEY_W)) {
        circlePosY = limitBounds(circlePosY - getSpeed(), height);
    } 
    if(IsKeyDown(KEY_S)) {
        circlePosY = limitBounds(circlePosY + getSpeed(), height);
    }
}

int inRange(int ax, int ay, int bx, int by, int range) {
    return sqrt(pow(ax - bx, 2) + pow(ay - by, 2) * 1.0) < range;
}

void HandlePhysics() {
    int rectX = rectPosX + (rectSize / 2);
    int rectY = rectPosY + (rectSize / 2);
    if (inRange(rectX, rectY, circlePosX, circlePosY, circleRadius + rectSize)) { // close
        if (
            inRange(rectPosX, rectPosY, circlePosX, circlePosY, circleRadius) ||
            inRange(rectPosX + rectSize, rectPosY, circlePosX, circlePosY, circleRadius) ||
            inRange(rectPosX, rectPosY + rectSize, circlePosX, circlePosY, circleRadius) ||
            inRange(rectPosX + rectSize, rectPosY + rectSize, circlePosX, circlePosY, circleRadius)
        ) {
            gameOver = true;
        }
    }
}

void Render() {
    DrawCircle(circlePosX, circlePosY, circleRadius, BLUE);
    DrawRectangle(rectPosX, rectPosY, rectSize, rectSize, RED);
    rectPosY += rectDirection;
    if (rectPosY > height - rectSize || rectPosY < 0) {
        rectDirection = -rectDirection;
    }
}

int main() {
    InitWindow(width, height, "My Game");
    SetTargetFPS(60);
    while(!WindowShouldClose()) {
        BeginDrawing();
        ClearBackground({20, 20, 20, 255});
        if (!gameOver) {
            HandleInput();
            HandlePhysics();
            Render();
        } else {
            int textWidth = MeasureText(gameOverText, 20);
            DrawText(gameOverText, (width*0.5)-(textWidth*0.5), height/2, 20, RED);
            if(IsKeyDown(KEY_R)) {
                circlePosX = 100;
                circlePosY = 100;
                gameOver = false;
            } 
        }
        EndDrawing();
    }
}
1 Like

I like that you broke so much down into individual functions. I bet he teaches that next.
What does this ? do in:
return isStrafing() ? (moveSpeed * runMultiplier) * 0.8 : moveSpeed * runMultiplier;
How do I get raymath.h to use so I can build your project?
You should share a .gif or video.

The ? combined with the : is called a ternary operator and works the same way in many languages. It takes the first value as a condition and if it’s true it returns the the left of the : and if false it does the right side. so

value = (5 > 3) ? "Yes" : "No"; // value would be "Yes" since 5 is greater than 3
value = (5 < 3) ? "Yes" : "No"; // value would be "No" since 5 is NOT less than 3

So in my code it’s checking if the function isStrafing() is true and if so it it cuts the speed by 2%


As for the header file, it’s a part of raylib so if you installed that and it’s in the directory configured in the guide it should just find it instantly and work without issue. and Sure I can make a quick gif:
axe_game_sgSo7WVWP3

2 Likes

This issue also gets solved at about the 6-minute mark on the 4th video of the final project called “Movement”. He sets this up by explaining Vectors in the Video before and uses raymath.h functions to “Normalize” or convert the vector created by inputs to a length of 1 so that a combination of inputs still yields an output of the same strength. It’s really cool to see this after seeing the other way you had created to accomplish this.

1 Like

Privacy & Terms