2 #include "system/stacktrace.h"
7 #include "math/triangle.h"
9 #include "system/line_stream.h"
10 #include "system/lt.h"
11 #include "system/nth_alloc.h"
12 #include "system/log.h"
14 #define GOAL_RADIUS 10.0f
15 #define GOAL_MAX_ID_SIZE 36
17 static int goals_is_goal_hidden(const Goals *goals, size_t i);
19 typedef enum Cue_state {
21 CUE_STATE_HIT_NOTHING,
22 CUE_STATE_SEEN_NOTHING
30 Cue_state *cue_states;
37 Goals *create_goals_from_line_stream(LineStream *line_stream)
39 trace_assert(line_stream);
41 Lt *const lt = create_lt();
46 Goals *const goals = PUSH_LT(lt, nth_alloc(sizeof(Goals)), free);
53 line_stream_next(line_stream),
55 &goals->count) == EOF) {
56 log_fail("Could not read amount of goals\n");
62 nth_alloc(sizeof(char*) * goals->count),
64 if (goals->ids == NULL) {
67 for (size_t i = 0; i < goals->count; ++i) {
68 goals->ids[i] = PUSH_LT(lt, nth_alloc(sizeof(char) * GOAL_MAX_ID_SIZE), free);
69 if (goals->ids[i] == NULL) {
74 goals->points = PUSH_LT(lt, nth_alloc(sizeof(Point) * goals->count), free);
75 if (goals->points == NULL) {
79 goals->colors = PUSH_LT(lt, nth_alloc(sizeof(Color) * goals->count), free);
80 if (goals->colors == NULL) {
84 goals->cue_states = PUSH_LT(lt, nth_alloc(sizeof(int) * goals->count), free);
85 if (goals->cue_states == NULL) {
89 goals->visible = PUSH_LT(lt, nth_alloc(sizeof(bool) * goals->count), free);
90 if (goals->visible == NULL) {
95 for (size_t i = 0; i < goals->count; ++i) {
97 line_stream_next(line_stream),
98 "%" STRINGIFY(GOAL_MAX_ID_SIZE) "s%f%f%6s",
103 log_fail("Could not read %dth goal\n", i);
106 goals->colors[i] = hexstr(color);
107 goals->cue_states[i] = CUE_STATE_VIRGIN;
108 goals->visible[i] = true;
117 void destroy_goals(Goals *goals)
120 RETURN_LT0(goals->lt);
123 static int goals_render_core(const Goals *goals,
128 trace_assert(camera);
130 const Point position = vec_sum(
131 goals->points[goal_index],
132 vec(0.0f, sinf(goals->angle) * 10.0f));
134 if (camera_fill_triangle(
136 triangle_mat3x3_product(
137 equilateral_triangle(),
139 trans_mat(position.x, position.y),
140 rot_mat(PI * -0.5f + goals->angle),
141 scale_mat(GOAL_RADIUS))),
142 goals->colors[goal_index]) < 0) {
146 if (camera_render_debug_text(
148 goals->ids[goal_index],
156 int goals_render(const Goals *goals,
160 trace_assert(camera);
162 for (size_t i = 0; i < goals->count; ++i) {
163 if (!goals_is_goal_hidden(goals, i)) {
164 if (goals_render_core(goals, i, camera) < 0) {
173 void goals_update(Goals *goals,
177 trace_assert(delta_time > 0.0f);
178 goals->angle = fmodf(goals->angle + 2.0f * delta_time, 2.0f * PI);
181 void goals_hide_from_player(Goals *goals,
184 goals->player_hitbox = player_hitbox;
188 int goals_sound(Goals *goals,
189 Sound_samples *sound_samples)
191 for (size_t i = 0; i < goals->count; ++i) {
192 switch (goals->cue_states[i]) {
193 case CUE_STATE_HIT_NOTHING:
194 sound_samples_play_sound(sound_samples, 0, 0);
195 goals->cue_states[i] = CUE_STATE_SEEN_NOTHING;
205 void goals_cue(Goals *goals,
206 const Camera *camera)
208 for (size_t i = 0; i < goals->count; ++i) {
209 switch (goals->cue_states[i]) {
210 case CUE_STATE_VIRGIN:
211 if (goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, goals->points[i])) {
212 goals->cue_states[i] = CUE_STATE_HIT_NOTHING;
217 case CUE_STATE_SEEN_NOTHING:
218 if (!goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, goals->points[i])) {
219 goals->cue_states[i] = CUE_STATE_VIRGIN;
228 void goals_checkpoint(const Goals *goals,
232 trace_assert(player);
234 for (size_t i = 0; i < goals->count; ++i) {
235 if (goals->cue_states[i] == CUE_STATE_HIT_NOTHING) {
236 player_checkpoint(player, goals->points[i]);
241 void goals_hide(Goals *goals, const char *id)
246 for (size_t i = 0; i < goals->count; ++i) {
247 if (strcmp(id, goals->ids[i]) == 0) {
248 goals->visible[i] = false;
254 void goals_show(Goals *goals, const char *id)
259 for (size_t i = 0; i < goals->count; ++i) {
260 if (strcmp(id, goals->ids[i]) == 0) {
261 goals->visible[i] = true;
267 /* Private Functions */
269 static int goals_is_goal_hidden(const Goals *goals, size_t i)
271 return !goals->visible[i];