X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fgame%2Flevel%2Fplayer%2Frigid_rect.c;h=9a0aa9a6e17183282182b9708c5c8607993b4f1d;hb=113f22c1518d6a35be502c4a9458fdd83384405e;hp=5b800652df0066d079f55a6f157ae45359cba3db;hpb=74fe51da6daa74d685d14d6f6be4bf33cfee9418;p=nothing.git diff --git a/src/game/level/player/rigid_rect.c b/src/game/level/player/rigid_rect.c index 5b800652..9a0aa9a6 100644 --- a/src/game/level/player/rigid_rect.c +++ b/src/game/level/player/rigid_rect.c @@ -1,38 +1,47 @@ -#include #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" -#define RIGID_RECT_GRAVITY 1500.0f +#define MAX_ID_SIZE 36 +#define STRINGIFY(x) STRINGIFY2(x) +#define STRINGIFY2(x) #x -struct rigid_rect_t { - lt_t *lt; - vec_t position; - vec_t velocity; - vec_t movement; - vec_t size; - color_t color; +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, @@ -43,58 +52,113 @@ 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; } -void destroy_rigid_rect(rigid_rect_t *rigid_rect) +Rigid_rect *create_rigid_rect_from_stream(FILE *stream) +{ + assert(stream); + + char color[7]; + Rect rect; + char id[MAX_ID_SIZE]; + + 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) { + throw_error(ERROR_TYPE_LIBC); + return NULL; + } + + return create_rigid_rect(rect, color_from_hexstr(color), id); +} + +void destroy_rigid_rect(Rigid_rect *rigid_rect) { RETURN_LT0(rigid_rect->lt); } -int rigid_rect_render(const rigid_rect_t *rigid_rect, - SDL_Renderer *renderer, - const camera_t *camera) +Solid_ref rigid_rect_as_solid(Rigid_rect *rigid_rect) +{ + 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) { - return camera_fill_rect( - camera, - renderer, - 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, - const platforms_t *platforms, +int rigid_rect_update(Rigid_rect * rigid_rect, float delta_time) { assert(rigid_rect); - assert(platforms); 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( @@ -103,63 +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_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); + 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; - for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) { + 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(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; - } - - platforms_rect_object_collide( - platforms, + 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); } - - return 0; } -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; } -void rigid_rect_jump(rigid_rect_t *rigid_rect, - float force) +int rigid_rect_touches_ground(const Rigid_rect *rigid_rect) { - rigid_rect->velocity.y = -force; + return rigid_rect->touches_ground; } -int rigid_rect_touches_ground(const rigid_rect_t *rigid_rect) +void rigid_rect_apply_force(Rigid_rect * rigid_rect, + Vec force) { - return rigid_rect->touches_ground; + rigid_rect->forces = vec_sum(rigid_rect->forces, force); +} + +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; }