]> git.lizzy.rs Git - nothing.git/blobdiff - src/player.c
(#111) Make Lava kill the Player
[nothing.git] / src / player.c
index d62215b69b1ccf8aa9b6a283df281578efc711ee..334061763c78d642a24c42911b02f4f9d0505662 100644 (file)
@@ -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);
+    }
 }