]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/player.c
(#639) Introduce rigid_bodies_collide_with_itself
[nothing.git] / src / game / level / player.c
index 14dfab04847c90dd665dc2395c046207260bc863..c9e06d3ddb3040836003080bf0195e6a10cf2e49 100644 (file)
@@ -1,37 +1,42 @@
 #include <SDL2/SDL.h>
-#include <assert.h>
+#include "system/stacktrace.h"
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "game/level/player/dying_rect.h"
 #include "game/level/player/rigid_rect.h"
+#include "game/level/script.h"
 #include "goals.h"
 #include "math/point.h"
 #include "platforms.h"
 #include "player.h"
-#include "system/error.h"
+#include "system/line_stream.h"
+#include "system/log.h"
 #include "system/lt.h"
+#include "system/nth_alloc.h"
 
 #define PLAYER_WIDTH 25.0f
 #define PLAYER_HEIGHT 25.0f
 #define PLAYER_SPEED 500.0f
 #define PLAYER_JUMP 32000.0f
 #define PLAYER_DEATH_DURATION 0.75f
-#define PLAYER_MAX_JUMP_COUNT 2
+#define PLAYER_MAX_JUMP_THRESHOLD 2
 
 typedef enum Player_state {
     PLAYER_STATE_ALIVE = 0,
     PLAYER_STATE_DYING
 } Player_state;
 
+/* TODO(#633): Player's alive_body should be a body from RigidBodies */
 struct Player {
     Lt *lt;
     Player_state state;
 
     Rigid_rect *alive_body;
     Dying_rect *dying_body;
+    Script *script;
 
-    int jump_count;
+    int jump_threshold;
     Color color;
 
     Vec checkpoint;
@@ -39,21 +44,42 @@ struct Player {
     int play_die_cue;
 };
 
-Player *create_player(float x, float y, Color color)
+Player *create_player_from_line_stream(LineStream *line_stream, Broadcast *broadcast)
 {
+    trace_assert(line_stream);
+
     Lt *lt = create_lt();
 
     if (lt == NULL) {
         return NULL;
     }
 
-    Player *player = PUSH_LT(lt, malloc(sizeof(Player)), free);
+    Player *player = PUSH_LT(lt, nth_alloc(sizeof(Player)), free);
     if (player == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
         RETURN_LT(lt, NULL);
     }
+    player->lt = lt;
 
-    player->state = PLAYER_STATE_ALIVE;
+    float x = 0.0f, y = 0.0f;
+    char colorstr[7];
+
+    if (sscanf(
+            line_stream_next(line_stream),
+            "%f%f%6s",
+            &x, &y, colorstr) == EOF) {
+        log_fail("Could not read player\n");
+        RETURN_LT(lt, NULL);
+    }
+
+    player->script = PUSH_LT(
+        lt,
+        create_script_from_line_stream(line_stream, broadcast),
+        destroy_script);
+    if (player->script == NULL) {
+        RETURN_LT(lt, NULL);
+    }
+
+    const Color color = hexstr(colorstr);
 
     player->alive_body = PUSH_LT(
         lt,
@@ -76,28 +102,15 @@ Player *create_player(float x, float y, Color color)
         RETURN_LT(lt, NULL);
     }
 
-    player->lt = lt;
-    player->jump_count = 0;
+    player->jump_threshold = 0;
     player->color = color;
     player->checkpoint = vec(x, y);
     player->play_die_cue = 0;
+    player->state = PLAYER_STATE_ALIVE;
 
     return player;
 }
 
-Player *create_player_from_stream(FILE *stream)
-{
-    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));
-}
-
 void destroy_player(Player * player)
 {
     RETURN_LT0(player->lt);
@@ -116,8 +129,8 @@ Solid_ref player_as_solid(Player *player)
 int player_render(const Player * player,
                   Camera *camera)
 {
-    assert(player);
-    assert(camera);
+    trace_assert(player);
+    trace_assert(camera);
 
     switch (player->state) {
     case PLAYER_STATE_ALIVE:
@@ -135,7 +148,7 @@ int player_render(const Player * player,
 void player_update(Player *player,
                    float delta_time)
 {
-    assert(player);
+    trace_assert(player);
 
     switch (player->state) {
     case PLAYER_STATE_ALIVE: {
@@ -172,48 +185,52 @@ void player_collide_with_solid(Player *player, Solid_ref solid)
         rigid_rect_collide_with_solid(player->alive_body, solid);
 
         if (rigid_rect_touches_ground(player->alive_body)) {
-            player->jump_count = 0;
+            player->jump_threshold = 0;
         }
     }
 }
 
 void player_move_left(Player *player)
 {
-    assert(player);
+    trace_assert(player);
     rigid_rect_move(player->alive_body, vec(-PLAYER_SPEED, 0.0f));
 }
 
 void player_move_right(Player *player)
 {
-    assert(player);
+    trace_assert(player);
 
     rigid_rect_move(player->alive_body, vec(PLAYER_SPEED, 0.0f));
 }
 
 void player_stop(Player *player)
 {
-    assert(player);
+    trace_assert(player);
 
     rigid_rect_move(player->alive_body, vec(0.0f, 0.0f));
 }
 
 void player_jump(Player *player)
 {
-    assert(player);
-    if (player->jump_count < PLAYER_MAX_JUMP_COUNT) {
+    trace_assert(player);
+    if (player->jump_threshold < PLAYER_MAX_JUMP_THRESHOLD) {
         rigid_rect_transform_velocity(player->alive_body,
                                       make_mat3x3(1.0f, 0.0f, 0.0f,
                                                   0.0f, 0.0f, 0.0f,
                                                   0.0f, 0.0f, 1.0f));
         rigid_rect_apply_force(player->alive_body,
                                vec(0.0f, -PLAYER_JUMP));
-        player->jump_count++;
+        player->jump_threshold++;
+
+        if (script_has_scope_value(player->script, "on-jump")) {
+            script_eval(player->script, "(on-jump)");
+        }
     }
 }
 
 void player_die(Player *player)
 {
-    assert(player);
+    trace_assert(player);
 
     if (player->state == PLAYER_STATE_ALIVE) {
         const Rect hitbox =
@@ -228,8 +245,8 @@ void player_die(Player *player)
 void player_focus_camera(Player *player,
                          Camera *camera)
 {
-    assert(player);
-    assert(camera);
+    trace_assert(player);
+    trace_assert(camera);
 
     const Rect player_hitbox = rigid_rect_hitbox(player->alive_body);
 
@@ -243,9 +260,9 @@ void player_focus_camera(Player *player,
 void player_hide_goals(const Player *player,
                        Goals *goals)
 {
-    assert(player);
-    assert(goals);
-    goals_hide(goals, rigid_rect_hitbox(player->alive_body));
+    trace_assert(player);
+    trace_assert(goals);
+    goals_hide_from_player(goals, rigid_rect_hitbox(player->alive_body));
 }
 
 void player_die_from_lava(Player *player,
@@ -293,8 +310,8 @@ void player_apply_force(Player *player, Vec force)
 
 Rigid_rect *player_rigid_rect(Player *player, const char *id)
 {
-    assert(player);
-    assert(id);
+    trace_assert(player);
+    trace_assert(id);
 
     if (player->state == PLAYER_STATE_ALIVE) {
         if (rigid_rect_has_id(player->alive_body, id)) {
@@ -304,3 +321,14 @@ Rigid_rect *player_rigid_rect(Player *player, const char *id)
 
     return NULL;
 }
+
+bool player_overlaps_rect(const Player *player,
+                          Rect rect)
+{
+    trace_assert(player);
+
+    return player->state == PLAYER_STATE_ALIVE
+        && rects_overlap(
+            rect, rigid_rect_hitbox(
+                player->alive_body));
+}