8 #include "./platforms.h"
11 #include "./rigid_rect.h"
12 #include "./dying_rect.h"
14 #define PLAYER_WIDTH 25.0f
15 #define PLAYER_HEIGHT 25.0f
16 #define PLAYER_SPEED 500.0f
17 #define PLAYER_JUMP 550.0f
18 #define PLAYER_DEATH_DURATION 250
20 typedef enum player_state_t {
21 PLAYER_STATE_ALIVE = 0,
29 rigid_rect_t *alive_body;
30 dying_rect_t *dying_body;
35 /* TODO(#110): introduce checkpoints */
39 player_t *create_player(float x, float y, color_t color)
41 lt_t *lt = create_lt();
47 player_t *player = PUSH_LT(lt, malloc(sizeof(player_t)), free);
49 throw_error(ERROR_TYPE_LIBC);
53 player->state = PLAYER_STATE_ALIVE;
55 player->alive_body = PUSH_LT(
58 rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT),
61 if (player->alive_body == NULL) {
65 player->dying_body = PUSH_LT(
68 rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT),
70 PLAYER_DEATH_DURATION),
72 if (player->dying_body == NULL) {
77 player->jump_count = 0;
78 player->color = color;
79 player->checkpoint = vec(x, y);
84 player_t *create_player_from_stream(FILE *stream)
86 float x = 0.0f, y = 0.0f;
89 if (fscanf(stream, "%f%f%6s", &x, &y, color) == EOF) {
90 throw_error(ERROR_TYPE_LIBC);
94 return create_player(x, y, color_from_hexstr(color));
97 void destroy_player(player_t * player)
99 RETURN_LT0(player->lt);
102 int player_render(const player_t * player,
103 SDL_Renderer *renderer,
104 const camera_t *camera)
110 switch (player->state) {
111 case PLAYER_STATE_ALIVE:
112 return rigid_rect_render(player->alive_body, renderer, camera);
114 case PLAYER_STATE_DYING:
115 return dying_rect_render(player->dying_body, renderer, camera);
123 void player_update(player_t *player,
124 const platforms_t *platforms,
130 switch (player->state) {
131 case PLAYER_STATE_ALIVE: {
132 rigid_rect_update(player->alive_body, platforms, delta_time);
134 if (rigid_rect_touches_ground(player->alive_body)) {
135 player->jump_count = 0;
138 const rect_t hitbox = rigid_rect_hitbox(player->alive_body);
140 if (hitbox.y > 1000.0f) {
145 case PLAYER_STATE_DYING: {
146 dying_rect_update(player->dying_body, delta_time);
148 if (dying_rect_is_dead(player->dying_body)) {
149 player->alive_body = RESET_LT(
155 vec(PLAYER_WIDTH, PLAYER_HEIGHT)),
157 player->state = PLAYER_STATE_ALIVE;
165 void player_move_left(player_t *player)
168 rigid_rect_move(player->alive_body, vec(-PLAYER_SPEED, 0.0f));
171 void player_move_right(player_t *player)
175 rigid_rect_move(player->alive_body, vec(PLAYER_SPEED, 0.0f));
178 void player_stop(player_t *player)
182 rigid_rect_move(player->alive_body, vec(0.0f, 0.0f));
185 void player_jump(player_t *player)
188 if (player->jump_count < 2) {
189 rigid_rect_jump(player->alive_body, PLAYER_JUMP);
190 player->jump_count++;
194 void player_die(player_t *player)
198 if (player->state == PLAYER_STATE_ALIVE) {
199 player->dying_body = RESET_LT(
203 rigid_rect_hitbox(player->alive_body),
205 PLAYER_DEATH_DURATION));
206 player->state = PLAYER_STATE_DYING;
210 void player_focus_camera(player_t *player,
216 const rect_t player_hitbox = rigid_rect_hitbox(player->alive_body);
221 vec(player_hitbox.x, player_hitbox.y),
222 vec(0.0f, -player_hitbox.h * 0.5f)));
225 void player_hide_goals(const player_t *player,
230 goals_hide(goals, rigid_rect_hitbox(player->alive_body));
233 void player_die_from_lava(player_t *player,
236 if (lava_overlaps_rect(lava, rigid_rect_hitbox(player->alive_body))) {