X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fgame%2Flevel%2Fplayer%2Frigid_rect.c;h=9a0aa9a6e17183282182b9708c5c8607993b4f1d;hb=113f22c1518d6a35be502c4a9458fdd83384405e;hp=b1097c04d195e374f2351bfb46e3c8c3f56f0f53;hpb=e652ba8bac44bc7efb53506d80a8e14aa463b9bb;p=nothing.git diff --git a/src/game/level/player/rigid_rect.c b/src/game/level/player/rigid_rect.c index b1097c04..9a0aa9a6 100644 --- a/src/game/level/player/rigid_rect.c +++ b/src/game/level/player/rigid_rect.c @@ -1,40 +1,47 @@ #include #include #include +#include #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" -#include "game/level/boxes.h" - -#define RIGID_RECT_GRAVITY 1500.0f -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; + 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, @@ -45,39 +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->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) { @@ -85,32 +107,58 @@ 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); } -int rigid_rect_render(const rigid_rect_t *rigid_rect, - const camera_t *camera) +Solid_ref rigid_rect_as_solid(Rigid_rect *rigid_rect) { - return camera_fill_rect( - camera, - rigid_rect_hitbox(rigid_rect), - rigid_rect->color); + const Solid_ref ref = { + .tag = SOLID_RIGID_RECT, + .ptr = rigid_rect + }; + + return ref; +} + +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 *rigid_rect, + Camera *camera) +{ + 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); rigid_rect->touches_ground = 0; - rigid_rect->velocity.y += RIGID_RECT_GRAVITY * delta_time; + /* TODO(#207): rigid_rect floating in lava is broken */ + rigid_rect->velocity = vec_sum( + rigid_rect->velocity, + vec_scala_mult( + rigid_rect->forces, + delta_time)); + rigid_rect->position = vec_sum( rigid_rect->position, vec_scala_mult( @@ -119,152 +167,120 @@ int rigid_rect_update(rigid_rect_t * rigid_rect, rigid_rect->movement), delta_time)); + rigid_rect->forces = vec(0.0f, 0.0f); + return 0; } -void rigid_rect_collide_with_platforms(rigid_rect_t * rigid_rect, - const platforms_t *platforms) +void rigid_rect_collide_with_solid(Rigid_rect * rigid_rect, + Solid_ref solid) { + assert(rigid_rect); + assert(rigid_rect != solid.ptr); + int sides[RECT_SIDE_N] = { 0, 0, 0, 0 }; - platforms_rect_object_collide(platforms, rigid_rect_hitbox(rigid_rect), sides); + solid_touches_rect_sides(solid, rigid_rect_hitbox(rigid_rect), sides); if (sides[RECT_SIDE_BOTTOM]) { rigid_rect->touches_ground = 1; } - vec_t opposing_force = opposing_force_by_sides(sides); - - for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) { - rigid_rect->position = vec_sum( - rigid_rect->position, - vec_scala_mult( - opposing_force, - 1e-2f)); - - 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; - } + Vec opforce_direction = opposing_force_by_sides(sides); - platforms_rect_object_collide( - platforms, - rigid_rect_hitbox(rigid_rect), - sides); - opposing_force = 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; } -} - -void rigid_rect_collide_with_rect(rigid_rect_t * rigid_rect, - rect_t rect) -{ - int sides[RECT_SIDE_N] = { 0, 0, 0, 0 }; - const rect_t object = rect_from_vecs(rigid_rect->position, rigid_rect->size); - rect_object_impact(&object, &rect, sides); + 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; - if (sides[RECT_SIDE_BOTTOM]) { - rigid_rect->touches_ground = 1; + if (vec_length(rigid_rect->velocity) > 1e-6) { + rigid_rect_apply_force( + rigid_rect, + vec_scala_mult( + vec_neg(rigid_rect->velocity), + 16.0f)); + } } - vec_t opposing_force = opposing_force_by_sides(sides); - 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)); - 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; - } - - rect_object_impact(&object, &rect, sides); - opposing_force = opposing_force_by_sides(sides); + memset(sides, 0, sizeof(int) * RECT_SIDE_N); + solid_touches_rect_sides( + solid, + rigid_rect_hitbox(rigid_rect), + sides); + opforce_direction = opposing_force_by_sides(sides); } } -void rigid_rect_collide_with_boxes(rigid_rect_t * rigid_rect, - const boxes_t *boxes) +Rect rigid_rect_hitbox(const Rigid_rect *rigid_rect) { - int sides[RECT_SIDE_N] = { 0, 0, 0, 0 }; - - boxes_rect_object_collide(boxes, rigid_rect_hitbox(rigid_rect), sides); - - if (sides[RECT_SIDE_BOTTOM]) { - rigid_rect->touches_ground = 1; - } - - vec_t opposing_force = opposing_force_by_sides(sides); - - for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) { - rigid_rect->position = vec_sum( - rigid_rect->position, - vec_scala_mult( - opposing_force, - 1e-2f)); - - 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; - } + return rect_from_vecs( + rigid_rect->position, + rigid_rect->size); +} - 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; - } +void rigid_rect_move(Rigid_rect *rigid_rect, + Vec movement) +{ + rigid_rect->movement = movement; +} - boxes_rect_object_collide( - boxes, - rigid_rect_hitbox(rigid_rect), - sides); - opposing_force = opposing_force_by_sides(sides); - } +int rigid_rect_touches_ground(const Rigid_rect *rigid_rect) +{ + return rigid_rect->touches_ground; } -void rigid_rect_impact_rigid_rect(rigid_rect_t * rigid_rect, - rigid_rect_t *another_rect) +void rigid_rect_apply_force(Rigid_rect * rigid_rect, + Vec force) { - if (rects_overlap(rigid_rect_hitbox(rigid_rect), rigid_rect_hitbox(another_rect))) { - rigid_rect_move(another_rect, - vec_sum( - rigid_rect->velocity, - rigid_rect->movement)); - } + rigid_rect->forces = vec_sum(rigid_rect->forces, force); } -rect_t rigid_rect_hitbox(const rigid_rect_t *rigid_rect) +void rigid_rect_transform_velocity(Rigid_rect *rigid_rect, + mat3x3 trans_mat) { - return rect_from_vecs( - rigid_rect->position, - rigid_rect->size); + rigid_rect->velocity = point_mat3x3_product(rigid_rect->velocity, + trans_mat); } -void rigid_rect_move(rigid_rect_t *rigid_rect, - vec_t movement) +void rigid_rect_teleport_to(Rigid_rect *rigid_rect, + Vec position) { - rigid_rect->movement = movement; + rigid_rect->position = position; } -void rigid_rect_jump(rigid_rect_t *rigid_rect, - float force) +void rigid_rect_damper(Rigid_rect *rigid_rect, Vec v) { - rigid_rect->velocity.y = -force; + rigid_rect_apply_force( + rigid_rect, + vec(rigid_rect->velocity.x * v.x, rigid_rect->velocity.y * v.y)); } -int rigid_rect_touches_ground(const rigid_rect_t *rigid_rect) +bool rigid_rect_has_id(Rigid_rect *rigid_rect, + const char *id) { - return rigid_rect->touches_ground; + assert(rigid_rect); + assert(id); + + return strcmp(rigid_rect->id, id) == 0; }