X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fgame%2Flevel%2Fplayer%2Frigid_rect.c;h=9a0aa9a6e17183282182b9708c5c8607993b4f1d;hb=113f22c1518d6a35be502c4a9458fdd83384405e;hp=c3acab1109099dfcaadf18a526ea050fd3b915ea;hpb=901cbdf7243a1e73b36087c55c44b6ebd951946a;p=nothing.git diff --git a/src/game/level/player/rigid_rect.c b/src/game/level/player/rigid_rect.c index c3acab11..9a0aa9a6 100644 --- a/src/game/level/player/rigid_rect.c +++ b/src/game/level/player/rigid_rect.c @@ -1,42 +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" -#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; - float floating; + 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, @@ -47,40 +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) { @@ -88,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 }; @@ -106,47 +125,39 @@ 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); rigid_rect->touches_ground = 0; - if (rigid_rect->floating > 1e-6) { - rigid_rect->velocity = vec_sum( - rigid_rect->velocity, - vec_scala_mult( - vec_sum( - vec(0.0f, RIGID_RECT_GRAVITY), - vec(0.0f, -RIGID_RECT_GRAVITY * 1.1f * rigid_rect->floating)), - delta_time)); - - } else { - rigid_rect->velocity = vec_sum( - rigid_rect->velocity, - vec_scala_mult( - vec(0.0f, 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, @@ -156,11 +167,13 @@ 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_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); @@ -173,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; - 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; - } - 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); } } -void rigid_rect_impact_rigid_rect(rigid_rect_t * rigid_rect, - rigid_rect_t * another_rect) -{ - 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)); - } -} - -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)); } -void rigid_rect_collide_with_lava(rigid_rect_t *rigid_rect, - lava_t *lava) +bool rigid_rect_has_id(Rigid_rect *rigid_rect, + const char *id) { assert(rigid_rect); - assert(lava); + assert(id); - 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); + return strcmp(rigid_rect->id, id) == 0; }