diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common.h | 19 | ||||
| -rw-r--r-- | src/graphics.c | 32 | ||||
| -rw-r--r-- | src/main.c | 55 | ||||
| -rw-r--r-- | src/physics.c | 112 | ||||
| -rw-r--r-- | src/physics.h | 6 |
5 files changed, 92 insertions, 132 deletions
diff --git a/src/common.h b/src/common.h index b56d70f..7664233 100644 --- a/src/common.h +++ b/src/common.h @@ -1,4 +1,8 @@ -// common.h +/** + * @file common.h + * @brief Functions and values used throughout most files + * @date 2026-04-27 +*/ #ifndef COMMON_H #define COMMON_H @@ -10,14 +14,6 @@ typedef int_least16_t i16; typedef uint_least32_t u32; typedef int_least32_t i32; -/* #define SHAPE_ENUM_SIZE 4 */ -/* typedef enum { */ -/* SHAPE_CIRCLE, */ -/* SHAPE_SQUARE, */ -/* SHAPE_RECTANGLE, */ -/* SHAPE_TRIANGLE */ -/* } shape_t; */ - typedef struct { Color color; float elast; @@ -33,6 +29,9 @@ typedef struct { float mass; Vector2* vertices; Vector2* edges; + float line_thickness; + u32 vertex_n; // number of vertices + u32 edge_n; // number of edges } object_t; @@ -50,8 +49,6 @@ typedef struct { #define ARR_LEN(arr) (sizeof(arr)/sizeof(arr[0])) -#define RANDOM_SHAPE() ((shape_t)(GetRandomValue(0, SHAPE_ENUM_SIZE - 1))) - #define RANDOM_COLOR() ((Color) { \ GetRandomValue(0, 255), \ GetRandomValue(0, 255), \ diff --git a/src/graphics.c b/src/graphics.c index 60ad4ff..0f31d6a 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1,10 +1,15 @@ -// graphics.c +/** + * @file graphics.c + * @brief All things related to graphics + * @date 2026-04-27 + */ #include <raylib.h> #include <stdint.h> #include <stdio.h> #include "graphics.h" #include "common.h" + void init_graphics(uint32_t x, uint32_t y, const char* title) { InitWindow(x, y, title); @@ -33,28 +38,17 @@ void clear_graphics(const Color color) void draw_graphics_object(const object_t* obj) { - const Color color = obj->color; - if(!obj->registered) return; - - Vector2 pos = obj->pos; + // shapes smaller than 3 don't make sense + if(obj->vertices == NULL || obj->vertex_n < 3) return; - switch(obj->obj_type) { - case SHAPE_CIRCLE: - DrawCircleV(pos, obj->size_x/2.0f, color); - break; - case SHAPE_SQUARE: - DrawRectangleV( - (Vector2){pos.x - obj->size_x/2, pos.y - obj->size_y/2}, - (Vector2){obj->size_x, obj->size_y}, color); - break; - case SHAPE_RECTANGLE: - DrawRectangleV( - (Vector2){pos.x - obj->size_x/2, pos.y - obj->size_y/2}, - (Vector2){obj->size_x, obj->size_y}, color); - break; + for(u32 iter = 0; iter < obj->vertex_n; iter++) { + Vector2 start = obj->vertices[iter]; + Vector2 end = obj->vertices[(iter + 1) % obj->vertex_n]; + DrawLineEx(start, end, obj->line_thickness, obj->color); } } + void draw_graphics_objects(const object_t* world, uint32_t count) { for (uint32_t iter = 0; iter < count; iter++) @@ -1,4 +1,8 @@ -// main.c +/** + * @file main.c + * @brief The main loop and controls + * @date 2026-04-27 + */ #include <math.h> #include <raylib.h> #include <stdbool.h> @@ -20,43 +24,29 @@ int main(void) object_t* grabbed_obj = NULL; bool anti_gravity_toggle = false; - world[0] = (object_t){ - .color = RANDOM_COLOR(), - .elast = 0.9f, - .frict = 0.99f, - .grabbed = true, - .pos_prev = {0}, - .registered = true, - .size_x = 75, - .size_y = 75, - .vel = {200, 200}, - .pos = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f }, - .obj_type = RANDOM_SHAPE() - }; - objs_count = 1; init_physics(world, MAX_OBJECTS); init_graphics(WINDOW_X, WINDOW_Y, SCREEN_TITLE); while(!WindowShouldClose()) { Vector2 pos_cursor = GetMousePosition(); - if(IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) { - if(objs_count == 0) { - grabbed_obj = NULL; - } else { - 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(IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) { */ + /* if(objs_count == 0) { */ + /* grabbed_obj = NULL; */ + /* } else { */ + /* 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)) { - obj->grabbed = true; - grabbed_obj = obj; - break; - } - } - } - } + /* if(hypot(dx, dy) <= (obj->size_x && obj->size_y)) { */ + /* obj->grabbed = true; */ + /* grabbed_obj = obj; */ + /* break; */ + /* } */ + /* } */ + /* } */ + /* } */ if (IsMouseButtonReleased(MOUSE_BUTTON_RIGHT)) { if(grabbed_obj != NULL) { @@ -80,9 +70,6 @@ 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 xbe too small - .size_y = GetRandomValue(50, 100), - .obj_type = RANDOM_SHAPE() }; } } diff --git a/src/physics.c b/src/physics.c index 1bb41fd..f61e0c8 100644 --- a/src/physics.c +++ b/src/physics.c @@ -1,63 +1,57 @@ -// physics.c +/** + * @file physics.h + * @brief All things related to physics + * @date 2026-04-27 + */ #include <raylib.h> +#include <raymath.h> #include <time.h> #include <string.h> #include <stdlib.h> +#include <math.h> #include "physics.h" #include "common.h" -bool check_collision(object_t obj1, object_t obj2) +/** + @brief iterate through all objects and check whether they are grabbed or registered +*/ +void init_physics(object_t* world, uint32_t max_objs) { - // 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 < max_objs; iter++) { + world[iter].registered = false; + world[iter].grabbed = false; } +} - 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; - } +/** + @brief uses the SAT to check whether a collision between two objects is happening +*/ +bool check_collision(object_t* obj1, object_t* obj2) +{ + for(u32 shape = 0; shape < 2; shape++) { + object_t* obj = (shape == 0) ? obj1 : obj2; - for(u32 iter2 = 0; iter2 < obj2_len; iter2++) { - dot = Vector2DotProduct(obj2.vertices[iter2], perp_stack[iter2]); + for(u32 iter = 0; iter < obj->vertex_n; iter++) { + Vector2 edge = obj->edges[iter]; + // perpendicular axis + Vector2 axis = Vector2Normalize((Vector2){-edge.y, edge.x}); + + float a_min = INFINITY, b_min = INFINITY; + float a_max = -INFINITY, b_max = -INFINITY; + + for(u32 iter2 = 0; iter2 < obj1->vertex_n; iter2++) { + float p = Vector2DotProduct(obj1->vertices[iter2], axis); + a_min = fminf(a_min, p); + a_max = fmaxf(a_max, p); + } - 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; + for(u32 iter2 = 0; iter2 < obj2->vertex_n; iter2++) { + float p = Vector2DotProduct(obj2->vertices[iter2], axis); + b_min = fminf(b_min, p); + b_max = fmaxf(b_max, p); + } + + if(a_max < b_min || b_max < a_min) return false; } } return true; @@ -65,36 +59,28 @@ bool check_collision(object_t obj1, object_t obj2) void resolve_collision(object_t* obj1, object_t* obj2, Vector2 normal) { - Vector2 rel_vel = Vector2Subtract(obj1->vel, obj1->vel); + Vector2 rel_vel = Vector2Subtract(obj1->vel, obj2->vel); float vel_along = Vector2DotProduct(rel_vel, normal); if(vel_along > 0) return; } -void init_physics(object_t* world, uint32_t max_objs) -{ - for(u32 iter = 0; iter < max_objs; iter++) { - world[iter].registered = false; - world[iter].grabbed = false; - } -} void update_physics(object_t* world, u32 objs_count, float gravity, float dt) { const u32 screen_width = GetScreenWidth(); const u32 screen_height = GetScreenHeight(); - Vector2 walls; for(u32 iter = 0; iter < objs_count; iter++) { object_t* obj = &world[iter]; // Clamp objects to the window boundaries if they move outside - obj = { - Clamp(obj->pos.x, 0.0f, (float)screen_width), - Clamp(obj->pos.y, 0.0f, (float)screen_height) - }; + obj->pos.x = Clamp(obj->pos.x, 0.0f, (float)screen_width); + obj->pos.y = Clamp(obj->pos.y, 0.0f, (float)screen_height); + obj->vel.x += gravity * dt; + obj->pos = Vector2Add(obj->pos, Vector2Scale(obj->vel, dt)); for(u32 iter2 = 0; iter2 < objs_count; iter2++) { - object_t obj_a = &world[iter]; - object_t obj_b = &world[iter++]; + object_t* obj_a = &world[iter]; + object_t* obj_b = &world[iter++]; if(check_collision(obj_a, obj_b)) { } diff --git a/src/physics.h b/src/physics.h index e9c0c0e..a191860 100644 --- a/src/physics.h +++ b/src/physics.h @@ -8,11 +8,7 @@ void init_physics(object_t* world, uint32_t max_objs); -bool check_collision(object_t obj1, object_t obj2); +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); void clear_all_physics(object_t* world, uint32_t* count); -void push_pos(object_t* world, uint32_t count, Vector2 pos, float radius, float strength); - #endif // PHYSICS_H |
