X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fplayer.c;h=7e1a1a7717f4b1e6d4d4d39f733f4d0aa86b03b8;hb=5af75a0cd35d57d9de638d886f826ac4764c8697;hp=5a1adcbb3dcfdf0cb9b86ecc2ea75b9a7f5e6022;hpb=08a5a1dbe67460682e93a52999f2f97625f77f65;p=nothing.git diff --git a/src/player.c b/src/player.c index 5a1adcbb..7e1a1a77 100644 --- a/src/player.c +++ b/src/player.c @@ -1,109 +1,224 @@ +#include #include #include #include #include "./player.h" #include "./platforms.h" +#include "./point.h" +#include "./error.h" #define PLAYER_WIDTH 50.0f #define PLAYER_HEIGHT 50.0f #define PLAYER_SPEED 500.0f #define PLAYER_GRAVITY 1500.0f +#define PLAYER_INFLATION 100.0f struct player_t { - float x, y; - float dx, dy; + vec_t position; + vec_t velocity; + vec_t movement; + float height; + float width; }; -struct player_t *create_player(float x, float y) +static const vec_t 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]) +{ + vec_t opposing_force = { + .x = 0.0f, + .y = 0.0f + }; + + for (rect_side_t side = 0; side < RECT_SIDE_N; ++side) { + if (sides[side]) { + vec_add( + &opposing_force, + opposing_rect_side_forces[side]); + } + } + + return opposing_force; +} + +static int squishing_horizontal_force(int sides[RECT_SIDE_N]) { - struct player_t *player = malloc(sizeof(struct player_t)); + return sides[RECT_SIDE_LEFT] && sides[RECT_SIDE_RIGHT]; +} + +static int squishing_vertical_force(int sides[RECT_SIDE_N]) +{ + return sides[RECT_SIDE_TOP] && sides[RECT_SIDE_BOTTOM]; +} + +player_t *create_player(float x, float y) +{ + player_t *player = malloc(sizeof(player_t)); if (player == NULL) { + throw_error(ERROR_TYPE_LIBC); return NULL; } - player->x = x; - player->y = y; - player->dx = 0.0f; - player->dy = 0.0f; + player->position.x = x; + player->position.y = y; + player->velocity.x = 0.0f; + player->velocity.y = 0.0f; + player->movement.x = 0.0f; + player->movement.y = 0.0f; + player->height = PLAYER_HEIGHT; + player->width = PLAYER_WIDTH; return player; } -void destroy_player(struct player_t * player) +void destroy_player(player_t * player) { free(player); } -int render_player(const struct player_t * player, - SDL_Renderer *renderer) +rect_t player_hitbox(const player_t *player) { - if (SDL_SetRenderDrawColor(renderer, 96, 255, 96, 255) < 0) { - return -1; - } + rect_t hitbox = { + .x = player->position.x - player->width / 2, + .y = player->position.y - player->height, + .w = player->width, + .h = player->height + }; - SDL_Rect rect; - rect.x = roundf(player->x); - rect.y = roundf(player->y); - rect.w = roundf(PLAYER_WIDTH); - rect.h = roundf(PLAYER_HEIGHT); + return hitbox; +} + +int render_player(const player_t * player, + SDL_Renderer *renderer, + const camera_t *camera) +{ + assert(player); + assert(renderer); + assert(camera); - if (SDL_RenderFillRect(renderer, &rect) < 0) { + if (SDL_SetRenderDrawColor(renderer, 96, 255, 96, 255) < 0) { + throw_error(ERROR_TYPE_SDL2); return -1; } + rect_t player_object = player_hitbox(player); + - return 0; + return camera_fill_rect(camera, renderer, &player_object); } -void update_player(struct player_t * player, - const struct platforms_t *platforms, - int delta_time) +void update_player(player_t *player, + const platforms_t *platforms, + Uint32 delta_time) { - float d = delta_time / 1000.0; + assert(player); + assert(platforms); - float dx = player->dx; - float dy = player->dy + PLAYER_GRAVITY * d; + float d = (float) delta_time / 1000.0f; - float x = player->x + dx * d; - float y = fmod(player->y + dy * d, 600.0f); + player->velocity.y += PLAYER_GRAVITY * d; + player->position = vec_sum( + player->position, + vec_scala_mult( + vec_sum( + player->velocity, + player->movement), + d)); + player->position.y = fmodf(player->position.y, 800.0f); - struct rect_t player_object = { - .x = x, - .y = y, - .w = PLAYER_WIDTH, - .h = PLAYER_HEIGHT - }; + player->height = fminf(player->height + PLAYER_INFLATION * d, PLAYER_HEIGHT); + player->width = (PLAYER_WIDTH * PLAYER_HEIGHT) / player->height; + + + int sides[RECT_SIDE_N] = { 0, 0, 0, 0 }; + + platforms_rect_object_collide(platforms, player_hitbox(player), sides); + vec_t opposing_force = opposing_force_by_sides(sides); - /* TODO(#6): Implement collision for the left/right sides */ - if (platforms_rect_object_collide(platforms, &player_object)) { - dy = -player->dy * 0.75; - x = player->x + dx * d; - y = fmod(player->y + dy * d, 600.0f); + if (opposing_force.y < 0.0f && (player->velocity.y + player->movement.y) > 800.0f) { + player->height = PLAYER_HEIGHT / 2; } - player->dx = dx; - player->dy = dy; - player->x = x; - player->y = y; + for (int i = 0; i < 1000 + && (vec_length(opposing_force) > 1e-6 + || squishing_vertical_force(sides) + || squishing_horizontal_force(sides)); ++i) { + player->position = vec_sum( + player->position, + vec_scala_mult( + opposing_force, + 1e-2f)); + + if (fabs(opposing_force.x) > 1e-6 && (opposing_force.x < 0.0f) != ((player->velocity.x + player->movement.x) < 0.0f)) { + player->velocity.x = 0.0f; + player->movement.x = 0.0f; + } + + if (fabs(opposing_force.y) > 1e-6 && (opposing_force.y < 0.0f) != ((player->velocity.y + player->movement.y) < 0.0f)) { + player->velocity.y = 0.0f; + player->movement.y = 0.0f; + } + + if (squishing_vertical_force(sides)) { + player->height -= 1e-2f; + /* player->width = (PLAYER_WIDTH * PLAYER_HEIGHT) / player->height; */ + } + + if (squishing_horizontal_force(sides)) { + player->width -= 1e-2f; + /* player->height = (PLAYER_WIDTH * PLAYER_HEIGHT) / player->width; */ + } + + platforms_rect_object_collide( + platforms, + player_hitbox(player), + sides); + opposing_force = opposing_force_by_sides(sides); + } } -void player_move_left(struct player_t *player) +void player_move_left(player_t *player) { - player->dx = -PLAYER_SPEED; + assert(player); + + player->movement.x = -PLAYER_SPEED; + player->movement.y = 0.0f; } -void player_move_right(struct player_t *player) +void player_move_right(player_t *player) { - player->dx = PLAYER_SPEED; + assert(player); + + player->movement.x = PLAYER_SPEED; + player->movement.y = 0.0f; } -void player_stop(struct player_t *player) +void player_stop(player_t *player) { - player->dx = 0.0f; + assert(player); + + player->movement.x = 0.0f; + player->movement.y = 0.0f; } -void player_jump(struct player_t *player) +void player_jump(player_t *player) { - player->dy = -500.0f; + assert(player); + + player->velocity.y = -500.0f; +} + +void player_focus_camera(player_t *player, + camera_t *camera) +{ + assert(player); + assert(camera); + + camera_center_at(camera, player->position); }