X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fplayer.c;h=334061763c78d642a24c42911b02f4f9d0505662;hb=d6dcc416e81e0838642b19b4a4ae98c85d2fc022;hp=d62215b69b1ccf8aa9b6a283df281578efc711ee;hpb=8932297833a1448d75d27d6efa6a3ef22f7324ba;p=nothing.git diff --git a/src/player.c b/src/player.c index d62215b6..33406176 100644 --- a/src/player.c +++ b/src/player.c @@ -9,17 +9,31 @@ #include "./point.h" #include "./error.h" #include "./rigid_rect.h" +#include "./dying_rect.h" #define PLAYER_WIDTH 25.0f #define PLAYER_HEIGHT 25.0f #define PLAYER_SPEED 500.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 { lt_t *lt; - rigid_rect_t *player_body; - /* TODO(#105): fix player jump_count */ + 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, color_t color) @@ -36,18 +50,33 @@ player_t *create_player(float x, float y, color_t color) RETURN_LT(lt, NULL); } - player->player_body = PUSH_LT( + 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->player_body == NULL) { + 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; } @@ -77,7 +106,18 @@ int player_render(const player_t * player, assert(player); assert(renderer); assert(camera); - return rigid_rect_render(player->player_body, renderer, camera); + + 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); + + default: {} + } + + return 0; } void player_update(player_t *player, @@ -86,33 +126,85 @@ void player_update(player_t *player, { assert(player); assert(platforms); - rigid_rect_update(player->player_body, platforms, delta_time); + + 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; + } + + 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; + + default: {} + } } void player_move_left(player_t *player) { assert(player); - rigid_rect_move(player->player_body, vec(-PLAYER_SPEED, 0.0f)); + rigid_rect_move(player->alive_body, vec(-PLAYER_SPEED, 0.0f)); } void player_move_right(player_t *player) { assert(player); - rigid_rect_move(player->player_body, vec(PLAYER_SPEED, 0.0f)); + rigid_rect_move(player->alive_body, vec(PLAYER_SPEED, 0.0f)); } void player_stop(player_t *player) { assert(player); - rigid_rect_move(player->player_body, vec(0.0f, 0.0f)); + rigid_rect_move(player->alive_body, vec(0.0f, 0.0f)); } void player_jump(player_t *player) { assert(player); - rigid_rect_jump(player->player_body, PLAYER_JUMP); + if (player->jump_count < 2) { + rigid_rect_jump(player->alive_body, PLAYER_JUMP); + player->jump_count++; + } +} + +void player_die(player_t *player) +{ + assert(player); + + 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, @@ -121,7 +213,7 @@ void player_focus_camera(player_t *player, assert(player); assert(camera); - const rect_t player_hitbox = rigid_rect_hitbox(player->player_body); + const rect_t player_hitbox = rigid_rect_hitbox(player->alive_body); camera_center_at( camera, @@ -135,5 +227,13 @@ void player_hide_goals(const player_t *player, { assert(player); assert(goals); - goals_hide(goals, rigid_rect_hitbox(player->player_body)); + 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); + } }