X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fplayer.c;h=334061763c78d642a24c42911b02f4f9d0505662;hb=d6dcc416e81e0838642b19b4a4ae98c85d2fc022;hp=a1d0adc141056dac23b50acd4465d8b391a969e4;hpb=cb12b1f9871e3a97717fab31ea9f999763d96e6e;p=nothing.git diff --git a/src/player.c b/src/player.c index a1d0adc1..33406176 100644 --- a/src/player.c +++ b/src/player.c @@ -3,59 +3,103 @@ #include #include +#include "./lt.h" #include "./player.h" #include "./platforms.h" #include "./point.h" #include "./error.h" +#include "./rigid_rect.h" +#include "./dying_rect.h" -#define PLAYER_WIDTH 50.0f -#define PLAYER_HEIGHT 50.0f +#define PLAYER_WIDTH 25.0f +#define PLAYER_HEIGHT 25.0f #define PLAYER_SPEED 500.0f -#define PLAYER_GRAVITY 1500.0f +#define PLAYER_JUMP 550.0f +#define PLAYER_DEATH_DURATION 500 + +typedef enum player_state_t { + PLAYER_STATE_ALIVE = 0, + PLAYER_STATE_DYING +} player_state_t; struct player_t { - vec_t position; - vec_t velocity; - vec_t movement; + lt_t *lt; + player_state_t state; + + rigid_rect_t *alive_body; + dying_rect_t *dying_body; + + int jump_count; + color_t color; + + /* TODO(#110): introduce checkpoints */ + vec_t checkpoint; }; -player_t *create_player(float x, float y) +player_t *create_player(float x, float y, color_t color) { - player_t *player = malloc(sizeof(player_t)); + lt_t *lt = create_lt(); + if (lt == NULL) { + return NULL; + } + + player_t *player = PUSH_LT(lt, malloc(sizeof(player_t)), free); if (player == NULL) { throw_error(ERROR_TYPE_LIBC); - return NULL; + RETURN_LT(lt, NULL); } - 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->state = PLAYER_STATE_ALIVE; + + player->alive_body = PUSH_LT( + lt, + create_rigid_rect( + rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT), + color), + destroy_rigid_rect); + if (player->alive_body == NULL) { + RETURN_LT(lt, NULL); + } + + player->dying_body = PUSH_LT( + lt, + create_dying_rect( + rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT), + color, + PLAYER_DEATH_DURATION), + destroy_dying_rect); + if (player->dying_body == NULL) { + RETURN_LT(lt, NULL); + } + + player->lt = lt; + player->jump_count = 0; + player->color = color; + player->checkpoint = vec(x, y); return player; } -void destroy_player(player_t * player) +player_t *create_player_from_stream(FILE *stream) { - free(player); + float x = 0.0f, y = 0.0f; + + char color[7]; + if (fscanf(stream, "%f%f%6s", &x, &y, color) == EOF) { + throw_error(ERROR_TYPE_LIBC); + return NULL; + } + + return create_player(x, y, color_from_hexstr(color)); } -rect_t player_hitbox(const player_t *player) +void destroy_player(player_t * player) { - rect_t hitbox = { - .x = player->position.x, - .y = player->position.y, - .w = PLAYER_WIDTH, - .h = PLAYER_HEIGHT - }; - - return hitbox; + RETURN_LT0(player->lt); } -int render_player(const player_t * player, +int player_render(const player_t * player, SDL_Renderer *renderer, const camera_t *camera) { @@ -63,96 +107,104 @@ int render_player(const player_t * player, assert(renderer); assert(camera); - if (SDL_SetRenderDrawColor(renderer, 96, 255, 96, 255) < 0) { - throw_error(ERROR_TYPE_SDL2); - return -1; - } - rect_t player_object = { - .x = player->position.x, - .y = player->position.y, - .w = PLAYER_WIDTH, - .h = PLAYER_HEIGHT - }; + switch (player->state) { + case PLAYER_STATE_ALIVE: + return rigid_rect_render(player->alive_body, renderer, camera); + case PLAYER_STATE_DYING: + return dying_rect_render(player->dying_body, renderer, camera); - return camera_fill_rect(camera, renderer, &player_object); + default: {} + } + + return 0; } -void update_player(player_t *player, +void player_update(player_t *player, const platforms_t *platforms, Uint32 delta_time) { assert(player); assert(platforms); - float d = (float) delta_time / 1000.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); - - vec_t opposing_force = platforms_rect_object_collide( - platforms, - player_hitbox(player)); - - for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++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; + switch (player->state) { + case PLAYER_STATE_ALIVE: { + rigid_rect_update(player->alive_body, platforms, delta_time); + + if (rigid_rect_touches_ground(player->alive_body)) { + player->jump_count = 0; } - 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; + const rect_t hitbox = rigid_rect_hitbox(player->alive_body); + + if (hitbox.y > 1000.0f) { + player_die(player); + } + } break; + + case PLAYER_STATE_DYING: { + dying_rect_update(player->dying_body, delta_time); + + if (dying_rect_is_dead(player->dying_body)) { + player->alive_body = RESET_LT( + player->lt, + player->alive_body, + create_rigid_rect( + rect_from_vecs( + player->checkpoint, + vec(PLAYER_WIDTH, PLAYER_HEIGHT)), + player->color)); + player->state = PLAYER_STATE_ALIVE; } + } break; - opposing_force = platforms_rect_object_collide( - platforms, - player_hitbox(player)); + default: {} } } void player_move_left(player_t *player) { assert(player); - - player->movement.x = -PLAYER_SPEED; - player->movement.y = 0.0f; + rigid_rect_move(player->alive_body, vec(-PLAYER_SPEED, 0.0f)); } void player_move_right(player_t *player) { assert(player); - player->movement.x = PLAYER_SPEED; - player->movement.y = 0.0f; + rigid_rect_move(player->alive_body, vec(PLAYER_SPEED, 0.0f)); } void player_stop(player_t *player) { assert(player); - player->movement.x = 0.0f; - player->movement.y = 0.0f; + rigid_rect_move(player->alive_body, vec(0.0f, 0.0f)); } void player_jump(player_t *player) +{ + assert(player); + if (player->jump_count < 2) { + rigid_rect_jump(player->alive_body, PLAYER_JUMP); + player->jump_count++; + } +} + +void player_die(player_t *player) { assert(player); - player->velocity.y = -500.0f; + if (player->state == PLAYER_STATE_ALIVE) { + player->dying_body = RESET_LT( + player->lt, + player->dying_body, + create_dying_rect( + rigid_rect_hitbox(player->alive_body), + player->color, + PLAYER_DEATH_DURATION)); + player->state = PLAYER_STATE_DYING; + } } void player_focus_camera(player_t *player, @@ -161,9 +213,27 @@ void player_focus_camera(player_t *player, assert(player); assert(camera); + const rect_t player_hitbox = rigid_rect_hitbox(player->alive_body); + camera_center_at( camera, vec_sum( - player->position, - vec(PLAYER_WIDTH * 0.5f, PLAYER_HEIGHT * 0.5f))); + vec(player_hitbox.x, player_hitbox.y), + vec(0.0f, -player_hitbox.h * 0.5f))); +} + +void player_hide_goals(const player_t *player, + goals_t *goals) +{ + assert(player); + assert(goals); + goals_hide(goals, rigid_rect_hitbox(player->alive_body)); +} + +void player_die_from_lava(player_t *player, + const lava_t *lava) +{ + if (lava_overlaps_rect(lava, rigid_rect_hitbox(player->alive_body))) { + player_die(player); + } }