]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/player/rigid_rect.c
(#348) Stringify MAX_ID_SIZE
[nothing.git] / src / game / level / player / rigid_rect.c
index ff2ed6dfcbd3eaa451fb35d4c425e4837c60a8a2..9a0aa9a6e17183282182b9708c5c8607993b4f1d 100644 (file)
@@ -1,43 +1,47 @@
 #include <SDL2/SDL.h>
 #include <assert.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "color.h"
 #include "game/level/boxes.h"
 #include "game/level/solid.h"
+#include "math/minmax.h"
 #include "rigid_rect.h"
 #include "system/error.h"
 #include "system/lt.h"
 
-
-
-struct rigid_rect_t {
-    lt_t *lt;
-    vec_t position;
-    vec_t velocity;
-    vec_t movement;
-    vec_t size;
-    color_t color;
+#define MAX_ID_SIZE 36
+#define STRINGIFY(x) STRINGIFY2(x)
+#define STRINGIFY2(x) #x
+
+struct Rigid_rect {
+    Lt *lt;
+    char *id;
+    Vec position;
+    Vec velocity;
+    Vec movement;
+    Vec size;
+    Color color;
     int touches_ground;
-    float floating;
-    vec_t forces;
+    Vec forces;
 };
 
-static const vec_t opposing_rect_side_forces[RECT_SIDE_N] = {
+static const Vec opposing_rect_side_forces[RECT_SIDE_N] = {
     { .x = 1.0f,  .y =  0.0f  },  /* RECT_SIDE_LEFT = 0, */
     { .x = -1.0f, .y =  0.0f  },  /* RECT_SIDE_RIGHT, */
     { .x = 0.0f,  .y =  1.0f, },  /* RECT_SIDE_TOP, */
     { .x = 0.0f,  .y = -1.0f, }   /* RECT_SIDE_BOTTOM, */
 };
 
-static vec_t opposing_force_by_sides(int sides[RECT_SIDE_N])
+static Vec opposing_force_by_sides(int sides[RECT_SIDE_N])
 {
-    vec_t opposing_force = {
+    Vec opposing_force = {
         .x = 0.0f,
         .y = 0.0f
     };
 
-    for (rect_side_t side = 0; side < RECT_SIDE_N; ++side) {
+    for (Rect_side side = 0; side < RECT_SIDE_N; ++side) {
         if (sides[side]) {
             vec_add(
                 &opposing_force,
@@ -48,41 +52,54 @@ static vec_t opposing_force_by_sides(int sides[RECT_SIDE_N])
     return opposing_force;
 }
 
-rigid_rect_t *create_rigid_rect(rect_t rect, color_t color)
+Rigid_rect *create_rigid_rect(Rect rect, Color color, const char *id)
 {
-    lt_t *lt = create_lt();
+    assert(id);
+
+    Lt *lt = create_lt();
 
     if (lt == NULL) {
         return NULL;
     }
 
-    rigid_rect_t *rigid_rect = PUSH_LT(lt, malloc(sizeof(rigid_rect_t)), free);
+    Rigid_rect *rigid_rect = PUSH_LT(lt, malloc(sizeof(Rigid_rect)), free);
     if (rigid_rect == NULL) {
         throw_error(ERROR_TYPE_LIBC);
         RETURN_LT(lt, NULL);
     }
-
     rigid_rect->lt = lt;
+
+    rigid_rect->id = malloc(sizeof(char) * MAX_ID_SIZE);
+    if (rigid_rect->id == NULL) {
+        throw_error(ERROR_TYPE_LIBC);
+        RETURN_LT(lt, NULL);
+    }
+
+    const size_t len_id = min_size(MAX_ID_SIZE - 1, strlen(id));
+    memcpy(rigid_rect->id, id, len_id);
+    rigid_rect->id[len_id] = 0;
+
     rigid_rect->position = vec(rect.x, rect.y);
     rigid_rect->velocity = vec(0.0f, 0.0f);
     rigid_rect->movement = vec(0.0f, 0.0f);
     rigid_rect->size = vec(rect.w, rect.h);
     rigid_rect->color = color;
     rigid_rect->touches_ground = 0;
-    rigid_rect->floating = 0.0f;
     rigid_rect->forces = vec(0.0f, 0.0f);
 
     return rigid_rect;
 }
 
-rigid_rect_t *create_rigid_rect_from_stream(FILE *stream)
+Rigid_rect *create_rigid_rect_from_stream(FILE *stream)
 {
     assert(stream);
 
     char color[7];
-    rect_t rect;
+    Rect rect;
+    char id[MAX_ID_SIZE];
 
-    if (fscanf(stream, "%f%f%f%f%6s\n",
+    if (fscanf(stream, "%" STRINGIFY(MAX_ID_SIZE) "s%f%f%f%f%6s\n",
+               id,
                &rect.x, &rect.y,
                &rect.w, &rect.h,
                color) < 0) {
@@ -90,17 +107,17 @@ rigid_rect_t *create_rigid_rect_from_stream(FILE *stream)
         return NULL;
     }
 
-    return create_rigid_rect(rect, color_from_hexstr(color));
+    return create_rigid_rect(rect, color_from_hexstr(color), id);
 }
 
-void destroy_rigid_rect(rigid_rect_t *rigid_rect)
+void destroy_rigid_rect(Rigid_rect *rigid_rect)
 {
     RETURN_LT0(rigid_rect->lt);
 }
 
-solid_ref_t rigid_rect_as_solid(rigid_rect_t *rigid_rect)
+Solid_ref rigid_rect_as_solid(Rigid_rect *rigid_rect)
 {
-    const solid_ref_t ref = {
+    const Solid_ref ref = {
         .tag = SOLID_RIGID_RECT,
         .ptr = rigid_rect
     };
@@ -108,24 +125,27 @@ solid_ref_t rigid_rect_as_solid(rigid_rect_t *rigid_rect)
     return ref;
 }
 
-void rigid_rect_touches_rect_sides(rigid_rect_t *rigid_rect,
-                                   rect_t object,
+void rigid_rect_touches_rect_sides(Rigid_rect *rigid_rect,
+                                   Rect object,
                                    int sides[RECT_SIDE_N])
 {
     rect_object_impact(object, rigid_rect_hitbox(rigid_rect), sides);
 }
 
-int rigid_rect_render(const rigid_rect_t *rigid_rect,
-                      const camera_t *camera)
+int rigid_rect_render(const Rigid_rect *rigid_rect,
+                      Camera *camera)
 {
-    return camera_fill_rect(
-        camera,
-        rigid_rect_hitbox(rigid_rect),
-        rigid_rect->color);
+    if (camera_fill_rect(
+            camera,
+            rigid_rect_hitbox(rigid_rect),
+            rigid_rect->color) < 0) {
+        return -1;
+    }
 
+    return 0;
 }
 
-int rigid_rect_update(rigid_rect_t * rigid_rect,
+int rigid_rect_update(Rigid_rect * rigid_rect,
                       float delta_time)
 {
     assert(rigid_rect);
@@ -152,8 +172,8 @@ int rigid_rect_update(rigid_rect_t * rigid_rect,
     return 0;
 }
 
-void rigid_rect_collide_with_solid(rigid_rect_t * rigid_rect,
-                                   solid_ref_t solid)
+void rigid_rect_collide_with_solid(Rigid_rect * rigid_rect,
+                                   Solid_ref solid)
 {
     assert(rigid_rect);
     assert(rigid_rect != solid.ptr);
@@ -166,75 +186,101 @@ void rigid_rect_collide_with_solid(rigid_rect_t * rigid_rect,
         rigid_rect->touches_ground = 1;
     }
 
-    vec_t opposing_force = opposing_force_by_sides(sides);
+    Vec opforce_direction = opposing_force_by_sides(sides);
+
+    solid_apply_force(
+        solid,
+        vec_scala_mult(
+            vec_neg(vec_norm(opforce_direction)),
+            vec_length(
+                vec_sum(
+                    rigid_rect->velocity,
+                    rigid_rect->movement)) * 8.0f));
+
+    if (fabs(opforce_direction.x) > 1e-6 && (opforce_direction.x < 0.0f) != ((rigid_rect->velocity.x + rigid_rect->movement.x) < 0.0f)) {
+        rigid_rect->velocity.x = 0.0f;
+        rigid_rect->movement.x = 0.0f;
+    }
+
+    if (fabs(opforce_direction.y) > 1e-6 && (opforce_direction.y < 0.0f) != ((rigid_rect->velocity.y + rigid_rect->movement.y) < 0.0f)) {
+        rigid_rect->velocity.y = 0.0f;
+        rigid_rect->movement.y = 0.0f;
 
-    /* TODO(#219): apply opposing_force to solid from rigid_rect_t collision */
+        if (vec_length(rigid_rect->velocity) > 1e-6) {
+            rigid_rect_apply_force(
+                rigid_rect,
+                vec_scala_mult(
+                    vec_neg(rigid_rect->velocity),
+                    16.0f));
+        }
+    }
 
-    for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) {
+
+    for (int i = 0; i < 1000 && vec_length(opforce_direction) > 1e-6; ++i) {
         rigid_rect->position = vec_sum(
             rigid_rect->position,
             vec_scala_mult(
-                opposing_force,
+                opforce_direction,
                 1e-2f));
 
-        /* TODO(#220): implement friction for rigid_rect_t */
-
-        if (fabs(opposing_force.x) > 1e-6 && (opposing_force.x < 0.0f) != ((rigid_rect->velocity.x + rigid_rect->movement.x) < 0.0f)) {
-            rigid_rect->velocity.x = 0.0f;
-            rigid_rect->movement.x = 0.0f;
-        }
-
-        if (fabs(opposing_force.y) > 1e-6 && (opposing_force.y < 0.0f) != ((rigid_rect->velocity.y + rigid_rect->movement.y) < 0.0f)) {
-            rigid_rect->velocity.y = 0.0f;
-            rigid_rect->movement.y = 0.0f;
-        }
-
         memset(sides, 0, sizeof(int) * RECT_SIDE_N);
         solid_touches_rect_sides(
             solid,
             rigid_rect_hitbox(rigid_rect),
             sides);
-        opposing_force = opposing_force_by_sides(sides);
+        opforce_direction = opposing_force_by_sides(sides);
     }
 }
 
-rect_t rigid_rect_hitbox(const rigid_rect_t *rigid_rect)
+Rect rigid_rect_hitbox(const Rigid_rect *rigid_rect)
 {
     return rect_from_vecs(
         rigid_rect->position,
         rigid_rect->size);
 }
 
-void rigid_rect_move(rigid_rect_t *rigid_rect,
-                           vec_t movement)
+void rigid_rect_move(Rigid_rect *rigid_rect,
+                           Vec movement)
 {
     rigid_rect->movement = movement;
 }
 
-int rigid_rect_touches_ground(const rigid_rect_t *rigid_rect)
+int rigid_rect_touches_ground(const Rigid_rect *rigid_rect)
 {
     return rigid_rect->touches_ground;
 }
 
-void rigid_rect_collide_with_lava(rigid_rect_t *rigid_rect,
-                                  lava_t *lava)
-{
-    assert(rigid_rect);
-    assert(lava);
-
-    rect_t overlap_area = lava_overlap_area(lava, rigid_rect_hitbox(rigid_rect));
-    rigid_rect->floating = (overlap_area.w * overlap_area.h) / (rigid_rect->size.x * rigid_rect->size.y);
-}
-
-void rigid_rect_apply_force(rigid_rect_t * rigid_rect,
-                            vec_t force)
+void rigid_rect_apply_force(Rigid_rect * rigid_rect,
+                            Vec force)
 {
     rigid_rect->forces = vec_sum(rigid_rect->forces, force);
 }
 
-void rigid_rect_transform_velocity(rigid_rect_t *rigid_rect,
+void rigid_rect_transform_velocity(Rigid_rect *rigid_rect,
                                    mat3x3 trans_mat)
 {
     rigid_rect->velocity = point_mat3x3_product(rigid_rect->velocity,
                                                 trans_mat);
 }
+
+void rigid_rect_teleport_to(Rigid_rect *rigid_rect,
+                            Vec position)
+{
+    rigid_rect->position = position;
+}
+
+void rigid_rect_damper(Rigid_rect *rigid_rect, Vec v)
+{
+    rigid_rect_apply_force(
+        rigid_rect,
+        vec(rigid_rect->velocity.x * v.x, rigid_rect->velocity.y * v.y));
+}
+
+bool rigid_rect_has_id(Rigid_rect *rigid_rect,
+                       const char *id)
+{
+    assert(rigid_rect);
+    assert(id);
+
+    return strcmp(rigid_rect->id, id) == 0;
+}