]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/goals.c
Merge pull request #595 from tsoding/594
[nothing.git] / src / game / level / goals.c
index 75d0f05fc7d919086596ca8fc29470b8783bf6e8..47c9f4b0d45bf31a402c9e7a5971a65a54c653a4 100644 (file)
-#include <assert.h>
-#include <math.h>
-
 #include <SDL2/SDL.h>
+#include "system/stacktrace.h"
+#include <math.h>
 
-#include "./lt.h"
-#include "./goals.h"
-#include "./error.h"
-#include "./math/pi.h"
-#include "./triangle.h"
+#include "goals.h"
+#include "math/pi.h"
+#include "math/triangle.h"
+#include "str.h"
+#include "system/line_stream.h"
+#include "system/lt.h"
+#include "system/nth_alloc.h"
+#include "system/log.h"
 
 #define GOAL_RADIUS 10.0f
+#define GOAL_MAX_ID_SIZE 36
 
-static int goals_is_goal_hidden(const goals_t *goals, size_t i);
+static int goals_is_goal_hidden(const Goals *goals, size_t i);
 
-typedef enum cue_state_t {
+typedef enum Cue_state {
     CUE_STATE_VIRGIN = 0,
     CUE_STATE_HIT_NOTHING,
     CUE_STATE_SEEN_NOTHING
-} cue_state_t;
-
-struct goals_t {
-    lt_t *lt;
-    point_t *points;
-    rect_t *regions;
-    color_t *colors;
-    cue_state_t *cue_states;
-    size_t goals_count;
-    rect_t player_hitbox;
+} Cue_state;
+
+struct Goals {
+    Lt *lt;
+    char **ids;
+    Point *points;
+    Color *colors;
+    Cue_state *cue_states;
+    bool *visible;
+    size_t count;
+    Rect player_hitbox;
     float angle;
 };
 
-goals_t *create_goals_from_stream(FILE *stream)
+Goals *create_goals_from_line_stream(LineStream *line_stream)
 {
-    assert(stream);
+    trace_assert(line_stream);
 
-    lt_t *const lt = create_lt();
+    Lt *const lt = create_lt();
     if (lt == NULL) {
         return NULL;
     }
 
-    goals_t *const goals = PUSH_LT(lt, malloc(sizeof(goals_t)), free);
+    Goals *const goals = PUSH_LT(lt, nth_alloc(sizeof(Goals)), free);
     if (goals == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
         RETURN_LT(lt, NULL);
     }
 
-    goals->goals_count = 0;
-    if (fscanf(stream, "%lu", &goals->goals_count) == EOF) {
-        throw_error(ERROR_TYPE_LIBC);
+    goals->count = 0;
+    if (sscanf(
+            line_stream_next(line_stream),
+            "%lu",
+            &goals->count) == EOF) {
+        log_fail("Could not read amount of goals\n");
         RETURN_LT(lt, NULL);
     }
 
-    goals->points = PUSH_LT(lt, malloc(sizeof(point_t) * goals->goals_count), free);
-    if (goals->points == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
+    goals->ids = PUSH_LT(
+        lt,
+        nth_alloc(sizeof(char*) * goals->count),
+        free);
+    if (goals->ids == NULL) {
         RETURN_LT(lt, NULL);
     }
+    for (size_t i = 0; i < goals->count; ++i) {
+        goals->ids[i] = PUSH_LT(lt, nth_alloc(sizeof(char) * GOAL_MAX_ID_SIZE), free);
+        if (goals->ids[i] == NULL) {
+            RETURN_LT(lt, NULL);
+        }
+    }
 
-    goals->regions = PUSH_LT(lt, malloc(sizeof(rect_t) * goals->goals_count), free);
-    if (goals->regions == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
+    goals->points = PUSH_LT(lt, nth_alloc(sizeof(Point) * goals->count), free);
+    if (goals->points == NULL) {
         RETURN_LT(lt, NULL);
     }
 
-    goals->colors = PUSH_LT(lt, malloc(sizeof(color_t) * goals->goals_count), free);
+    goals->colors = PUSH_LT(lt, nth_alloc(sizeof(Color) * goals->count), free);
     if (goals->colors == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
         RETURN_LT(lt, NULL);
     }
 
-    goals->cue_states = PUSH_LT(lt, malloc(sizeof(int) * goals->goals_count), free);
+    goals->cue_states = PUSH_LT(lt, nth_alloc(sizeof(int) * goals->count), free);
     if (goals->cue_states == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
+        RETURN_LT(lt, NULL);
+    }
+
+    goals->visible = PUSH_LT(lt, nth_alloc(sizeof(bool) * goals->count), free);
+    if (goals->visible == NULL) {
         RETURN_LT(lt, NULL);
     }
 
     char color[7];
-    for (size_t i = 0; i < goals->goals_count; ++i) {
-        if (fscanf(stream, "%f%f%f%f%f%f%6s",
-                   &goals->points[i].x,
-                   &goals->points[i].y,
-                   &goals->regions[i].x,
-                   &goals->regions[i].y,
-                   &goals->regions[i].w,
-                   &goals->regions[i].h,
-                   color) < 0) {
-            throw_error(ERROR_TYPE_LIBC);
+    for (size_t i = 0; i < goals->count; ++i) {
+        if (sscanf(
+                line_stream_next(line_stream),
+                "%" STRINGIFY(GOAL_MAX_ID_SIZE) "s%f%f%6s",
+                goals->ids[i],
+                &goals->points[i].x,
+                &goals->points[i].y,
+                color) < 0) {
+            log_fail("Could not read %dth goal\n", i);
             RETURN_LT(lt, NULL);
         }
-        goals->colors[i] = color_from_hexstr(color);
+        goals->colors[i] = hexstr(color);
         goals->cue_states[i] = CUE_STATE_VIRGIN;
+        goals->visible[i] = true;
     }
 
     goals->lt = lt;
@@ -98,49 +114,54 @@ goals_t *create_goals_from_stream(FILE *stream)
     return goals;
 }
 
-void destroy_goals(goals_t *goals)
+void destroy_goals(Goals *goals)
 {
-    assert(goals);
+    trace_assert(goals);
     RETURN_LT0(goals->lt);
 }
 
-static int goals_render_core(const goals_t *goals,
+static int goals_render_core(const Goals *goals,
                              size_t goal_index,
-                             SDL_Renderer *renderer,
-                             const camera_t *camera)
+                             Camera *camera)
 {
-    assert(goals);
-    assert(renderer);
-    assert(camera);
+    trace_assert(goals);
+    trace_assert(camera);
 
-    const point_t position = vec_sum(
+    const Point position = vec_sum(
         goals->points[goal_index],
         vec(0.0f, sinf(goals->angle) * 10.0f));
 
-    return camera_fill_triangle(
-        camera,
-        renderer,
-        triangle_mat3x3_product(
-            equilateral_triangle(),
-            mat3x3_product2(
-                trans_mat(position.x, position.y),
-                rot_mat(PI * -0.5f + goals->angle),
-                scale_mat(GOAL_RADIUS))),
-        goals->colors[goal_index]);
-}
+    if (camera_fill_triangle(
+            camera,
+            triangle_mat3x3_product(
+                equilateral_triangle(),
+                mat3x3_product2(
+                    trans_mat(position.x, position.y),
+                    rot_mat(PI * -0.5f + goals->angle),
+                    scale_mat(GOAL_RADIUS))),
+            goals->colors[goal_index]) < 0) {
+        return -1;
+    }
 
-int goals_render(const goals_t *goals,
-                 SDL_Renderer *renderer,
-                 const camera_t *camera)
+    if (camera_render_debug_text(
+            camera,
+            goals->ids[goal_index],
+            position) < 0) {
+        return -1;
+    }
 
+    return 0;
+}
+
+int goals_render(const Goals *goals,
+                 Camera *camera)
 {
-    assert(goals);
-    assert(renderer);
-    assert(camera);
+    trace_assert(goals);
+    trace_assert(camera);
 
-    for (size_t i = 0; i < goals->goals_count; ++i) {
+    for (size_t i = 0; i < goals->count; ++i) {
         if (!goals_is_goal_hidden(goals, i)) {
-            if (goals_render_core(goals, i, renderer, camera) < 0) {
+            if (goals_render_core(goals, i, camera) < 0) {
                 return -1;
             }
         }
@@ -149,28 +170,28 @@ int goals_render(const goals_t *goals,
     return 0;
 }
 
-void goals_update(goals_t *goals,
+void goals_update(Goals *goals,
                   float delta_time)
 {
-    assert(goals);
-    assert(delta_time > 0.0f);
+    trace_assert(goals);
+    trace_assert(delta_time > 0.0f);
     goals->angle = fmodf(goals->angle + 2.0f * delta_time, 2.0f * PI);
 }
 
-void goals_hide(goals_t *goals,
-                rect_t player_hitbox)
+void goals_hide_from_player(Goals *goals,
+                            Rect player_hitbox)
 {
     goals->player_hitbox = player_hitbox;
 
 }
 
-int goals_sound(goals_t *goals,
-                sound_medium_t *sound_medium)
+int goals_sound(Goals *goals,
+                Sound_samples *sound_samples)
 {
-    for (size_t i = 0; i < goals->goals_count; ++i) {
+    for (size_t i = 0; i < goals->count; ++i) {
         switch (goals->cue_states[i]) {
         case CUE_STATE_HIT_NOTHING:
-            sound_medium_play_sound(sound_medium, 0, goals->points[i], 0);
+            sound_samples_play_sound(sound_samples, 0, 0);
             goals->cue_states[i] = CUE_STATE_SEEN_NOTHING;
             break;
 
@@ -181,21 +202,20 @@ int goals_sound(goals_t *goals,
     return 0;
 }
 
-void goals_cue(goals_t *goals,
-               SDL_Renderer *renderer,
-               const camera_t *camera)
+void goals_cue(Goals *goals,
+               const Camera *camera)
 {
-    for (size_t i = 0; i < goals->goals_count; ++i) {
+    for (size_t i = 0; i < goals->count; ++i) {
         switch (goals->cue_states[i]) {
         case CUE_STATE_VIRGIN:
-            if (goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, renderer, goals->points[i])) {
+            if (goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, goals->points[i])) {
                 goals->cue_states[i] = CUE_STATE_HIT_NOTHING;
             }
 
             break;
 
         case CUE_STATE_SEEN_NOTHING:
-            if (!goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, renderer, goals->points[i])) {
+            if (!goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, goals->points[i])) {
                 goals->cue_states[i] = CUE_STATE_VIRGIN;
             }
             break;
@@ -205,22 +225,48 @@ void goals_cue(goals_t *goals,
     }
 }
 
-void goals_checkpoint(const goals_t *goals,
-                      player_t *player)
+void goals_checkpoint(const Goals *goals,
+                      Player *player)
 {
-    assert(goals);
-    assert(player);
+    trace_assert(goals);
+    trace_assert(player);
 
-    for (size_t i = 0; i < goals->goals_count; ++i) {
+    for (size_t i = 0; i < goals->count; ++i) {
         if (goals->cue_states[i] == CUE_STATE_HIT_NOTHING) {
             player_checkpoint(player, goals->points[i]);
         }
     }
 }
 
+void goals_hide(Goals *goals, const char *id)
+{
+    trace_assert(goals);
+    trace_assert(id);
+
+    for (size_t i = 0; i < goals->count; ++i) {
+        if (strcmp(id, goals->ids[i]) == 0) {
+            goals->visible[i] = false;
+            return;
+        }
+    }
+}
+
+void goals_show(Goals *goals, const char *id)
+{
+    trace_assert(goals);
+    trace_assert(id);
+
+    for (size_t i = 0; i < goals->count; ++i) {
+        if (strcmp(id, goals->ids[i]) == 0) {
+            goals->visible[i] = true;
+            return;
+        }
+    }
+}
+
 /* Private Functions */
 
-static int goals_is_goal_hidden(const goals_t *goals, size_t i)
+static int goals_is_goal_hidden(const Goals *goals, size_t i)
 {
-    return rects_overlap(goals->regions[i], goals->player_hitbox);
+    return !goals->visible[i];
 }