From 3c6188de4729a31e41fa1a90dd13065170972e36 Mon Sep 17 00:00:00 2001 From: kotorifan Date: Mon, 27 Apr 2026 12:57:51 +0200 Subject: Added SAT collision detection --- src/common.h | 50 ++++++++++----------- src/graphics.c | 5 +-- src/main.c | 43 ++++++++++-------- src/physics.c | 134 +++++++++++++++++++++++++++++++++++++++++++-------------- src/physics.h | 1 + 5 files changed, 154 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/common.h b/src/common.h index b8fb306..85a4c98 100644 --- a/src/common.h +++ b/src/common.h @@ -10,27 +10,29 @@ typedef int_least16_t i16; typedef uint_least32_t u32; typedef int_least32_t i32; -#define SHAPE_ENUM_SIZE 3 -typedef enum { - SHAPE_CIRCLE, - SHAPE_SQUARE, - SHAPE_RECTANGLE -} shape_t; +/* #define SHAPE_ENUM_SIZE 4 */ +/* typedef enum { */ +/* SHAPE_CIRCLE, */ +/* SHAPE_SQUARE, */ +/* SHAPE_RECTANGLE, */ +/* SHAPE_TRIANGLE */ +/* } shape_t; */ typedef struct { - Color color; - float elast; -// Vector2 force; - float frict; - Vector2 pos; - Vector2 pos_prev; - Vector2 vel; - bool grabbed; - bool registered; - float mass; - float size_x; - float size_y; - shape_t obj_type; + Color color; + float elast; + float frict; + Vector2 angle; + Vector2 pos; + Vector2 pos_prev; + Vector2 vel; + bool grabbed; + bool registered; + float mass; + float size_x; + float size_y; + Vector2* vertices; + Vector2* edges; } object_t; @@ -51,11 +53,11 @@ typedef struct { #define RANDOM_SHAPE() ((shape_t)(GetRandomValue(0, SHAPE_ENUM_SIZE - 1))) #define RANDOM_COLOR() ((Color) { \ - GetRandomValue(0, 255), \ - GetRandomValue(0, 255), \ - GetRandomValue(0, 255), \ - 255 \ - }) + GetRandomValue(0, 255), \ + GetRandomValue(0, 255), \ + GetRandomValue(0, 255), \ + 255 \ + }) #endif // COMMON_H diff --git a/src/graphics.c b/src/graphics.c index ecc0a58..60ad4ff 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -72,13 +72,10 @@ void draw_graphics_info(uint32_t objs) DrawText(buffer, 10, 35, 20, BLACK); DrawText("ESC: Exit", 10, 60, 20, BLACK); DrawText("R: Random velocity", 10, 85, 20, BLACK); - DrawText("G: Random gravity", 10, 110, 20, BLACK); + DrawText("G: Anti-Gravity", 10, 110, 20, BLACK); DrawText("C: Clear screen", 10, 135, 20, BLACK); DrawText("RCLICK: Push object", 10, 160, 20, BLACK); DrawText("LCLICK: Add object", 10, 185, 20, BLACK); - DrawText("1: Spawn Circle", 10, 210, 20, BLACK); - DrawText("2: Spawn Square", 10, 235, 20, BLACK); - DrawText("3: Spawn Rectangle", 10, 260, 20, BLACK); } bool should_close_graphics(void) diff --git a/src/main.c b/src/main.c index af9bf06..5ea6def 100644 --- a/src/main.c +++ b/src/main.c @@ -18,7 +18,8 @@ int main(void) uint32_t objs_count = 0; float force_gravity = FORCE_GRAVITY_DEFAULT; object_t* grabbed_obj = NULL; - + bool anti_gravity_toggle = false; + world[0] = (object_t){ .color = RANDOM_COLOR(), .elast = 0.9f, @@ -36,29 +37,21 @@ int main(void) objs_count = 1; init_physics(world, MAX_OBJECTS); init_graphics(WINDOW_X, WINDOW_Y, SCREEN_TITLE); - while(!WindowShouldClose()) - { - /* handle_input(world) */ - // physics_update - /* float dt = GetFrameTime(); delta time */ + while(!WindowShouldClose()) { Vector2 pos_cursor = GetMousePosition(); - if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) - { - if(objs_count == 0) - { + if(IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) { + if(objs_count == 0) { grabbed_obj = NULL; } else { - for(uint32_t iter = objs_count; iter > 0; iter--) - { + for(uint32_t iter = objs_count; iter > 0; iter--) { object_t* obj = &world[iter - 1]; float dx = pos_cursor.x - obj->pos.x; float dy = pos_cursor.y - obj->pos.y; - if(hypot(dx, dy) <= (obj->size_x && obj->size_y)) - { + if(hypot(dx, dy) <= (obj->size_x && obj->size_y)) { obj->grabbed = true; grabbed_obj = obj; break; @@ -67,15 +60,14 @@ int main(void) } } - if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) - { + if (IsMouseButtonReleased(MOUSE_BUTTON_RIGHT)) { if(grabbed_obj != NULL) { grabbed_obj->grabbed = false; grabbed_obj = NULL; } } - if(IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) { + if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { if(objs_count < MAX_OBJECTS) { world[objs_count++] = (object_t){ .color = RANDOM_COLOR(), @@ -90,13 +82,28 @@ int main(void) .grabbed = false, .registered = true, .mass = GetRandomValue(3, 100), // will be done later - .size_x = GetRandomValue(50, 100), //everything smaller than 3 would be too small + .size_x = GetRandomValue(50, 100), //everything smaller than 3 would xbe too small .size_y = GetRandomValue(50, 100), .obj_type = RANDOM_SHAPE() }; } } + if(IsKeyPressed(KEY_G)) { + if(anti_gravity_toggle) { + force_gravity = -75.0f; + anti_gravity_toggle = false; + } else if(!anti_gravity_toggle) { + force_gravity = FORCE_GRAVITY_DEFAULT; + anti_gravity_toggle = true; + } + } + + // to-do + /* if(IsKeyPressed(KEY_C)) { */ + /* clear_world(world); */ + /* } */ + float dt = GetFrameTime(); update_physics(world, objs_count, force_gravity, dt); diff --git a/src/physics.c b/src/physics.c index 28c5428..10f5abb 100644 --- a/src/physics.c +++ b/src/physics.c @@ -1,56 +1,124 @@ // physics.c #include #include +#include +#include #include "physics.h" #include "common.h" +#define GET_RECTANGLE_CENTER(rec) ((Vector2) { \ + rec.x + rec.width/2, rec.y + rec.height/2 \ + };) + + +bool get_sat(object_t obj1, object_t obj2) +{ + // perp = perpendicular here + void* perpendicular_line = NULL; + Vector2* perp_stack = NULL; + float dot = 0; + float a_min, a_max, b_min, b_max; + + Vector2 obj1_len = sizeof(obj1->edges)/sizeof(Vector2); + Vector2 obj2_len = sizeof(obj2->edges)/sizeof(Vector2); + perp_stack = (Vector2*)malloc((obj1_len + obj2_len) * sizeof(Vector2)); + + for(u32 iter = 0; iter < obj1_len; iter++) { + Vector2 perp = { + .x = -obj1->edges[iter].x, + .y = obj1->edges[iter].y + }; + perp_stack[perp_stack_size++] = perp; + } + + for(u32 iter = 0; iter < obj2_len; iter++) { + Vector2 perp = { + .x = -obj2->edges[i].y, + .y = obj2->edges[i].x + }; + perp_stack[perp_stack_size++] = perp; + } + + for(u32 iter = 0; iter < perp_count; iter++) { + a_min = INFINITY; + a_max = -INFINITY; + b_min = INFINITY; + b_max = -INFINITY; + + for(u32 iter2 = 0; iter2 < obj1_len; iter2++) { + dot = Vector2DotProduct(obj1.vertices[iter2], perp_stack[iter2]); + + if(a_max == NULL || dot < a_min) a_max = dot; + if(a_min == NULL || dot < a_min) a_min = dot; + } + + for(u32 iter2 = 0; iter2 < obj2_len; iter2++) { + dot = Vector2DotProduct(obj2.vertices[iter2], perp_stack[iter2]); + + if(b_max == NULL || dot > b_max) b_max = dot; + if(b_min == NULL || dot < b_min) b_min = dot; + } + + if((a_min < b_max && a_min > b_min) || (b_min < a_max && b_min > a_min)) { + continue; + } else { + return false; + } + } + return true; +} void init_physics(object_t* world, uint32_t max_objs) { - for(uint32_t iter = 0; iter < max_objs; iter++) { + for(u32 iter = 0; iter < max_objs; iter++) { world[iter].registered = false; world[iter].grabbed = false; } } -void update_physics(object_t* world, uint32_t objs_count, float gravity, float dt) -{ - const uint32_t screen_width = GetScreenWidth(); - const uint32_t screen_height = GetScreenHeight(); +/* void update_physics(object_t* world, uint32_t objs_count, float gravity, float dt) */ +/* { */ +/* const uint32_t screen_width = GetScreenWidth(); */ +/* const uint32_t screen_height = GetScreenHeight(); */ - for(uint32_t iter = 0; iter < objs_count; iter++) { - object_t* obj = &world[iter]; - if(!obj->grabbed && obj->registered) { +/* for(u32 iter = 0; iter < objs_count; iter++) { */ +/* object_t* obj = &world[iter]; */ +/* if(!obj->grabbed && obj->registered) { */ - obj->pos.x += obj->vel.x * dt; - obj->pos.y += obj->vel.y * dt; +/* obj->pos.x += obj->vel.x * dt; */ +/* obj->pos.y += obj->vel.y * dt; */ - if((obj->pos.x + obj->size_x) >= screen_width) { - obj->pos.x = screen_width - obj->size_x; - obj->vel.x = -obj->vel.x * obj->elast; +/* if((obj->pos.x + obj->size_x) >= screen_width) { */ +/* obj->pos.x = screen_width - obj->size_x; */ +/* obj->vel.x = -obj->vel.x * obj->elast; */ - } else if((obj->pos.x - obj->size_x) <= 0) { - obj->pos.x = obj->size_x; - obj->vel.x = -obj->vel.x * obj->elast; +/* } else if((obj->pos.x - obj->size_x) <= 0) { */ +/* obj->pos.x = obj->size_x; */ +/* obj->vel.x = -obj->vel.x * obj->elast; */ - } else if((obj->pos.y + obj->size_y) >= screen_height) { - obj->pos.y = screen_height - obj->size_y; - obj->vel.y = -obj->vel.y * obj->elast; +/* } else if((obj->pos.y + obj->size_y) >= screen_height) { */ +/* obj->pos.y = screen_height - obj->size_y; */ +/* obj->vel.y = -obj->vel.y * obj->elast; */ - } else if((obj->pos.y - obj->size_y) <= 0) { - obj->pos.y = obj->size_y; - obj->vel.y = -obj->vel.y * obj->elast; +/* } else if((obj->pos.y - obj->size_y) <= 0) { */ +/* obj->pos.y = obj->size_y; */ +/* obj->vel.y = -obj->vel.y * obj->elast; */ - } +/* } */ - obj->vel.x = obj->vel.x * obj->frict; - obj->vel.y = (obj->vel.y + gravity * dt) * obj->frict; - } +/* obj->vel.x = obj->vel.x * obj->frict; */ +/* obj->vel.y = (obj->vel.y + gravity * dt) * obj->frict; */ +/* } */ - if(obj->grabbed) { - Vector2 cursor_pos = GetMousePosition(); - obj->pos = cursor_pos; - obj->vel = (Vector2){0, 0}; - } - } -} +/* for (u32 iter2 = 0; iter2 < objs_count; iter2++) { */ +/* if(check_collision(&world[iter], &world[iter2])) { */ +/* } */ +/* } */ +/* } */ +/* /\* if(obj->grabbed) { *\/ */ +/* /\* Vector2 cursor_pos = GetMousePosition(); *\/ */ +/* /\* obj->pos = cursor_pos; *\/ */ +/* /\* obj->vel = (Vector2){0, 0}; *\/ */ +/* /\* } *\/ */ + +/* } */ diff --git a/src/physics.h b/src/physics.h index a5168cd..e9c0c0e 100644 --- a/src/physics.h +++ b/src/physics.h @@ -8,6 +8,7 @@ void init_physics(object_t* world, uint32_t max_objs); +bool check_collision(object_t obj1, object_t obj2); void update_physics(object_t* world, uint32_t objs_count, float gravity, float dt); void apply_force(object_t* obj, Vector2 force); void add_object(object_t* world, uint32_t* count, shape_t type, Vector2 pos); -- cgit v1.3