10 #include "./triangle.h"
12 #define GOAL_RADIUS 10.0f
14 static int goals_is_goal_hidden(const goals_t *goals, size_t i);
16 typedef enum cue_state_t {
18 CUE_STATE_HIT_NOTHING,
19 CUE_STATE_SEEN_NOTHING
27 cue_state_t *cue_states;
33 goals_t *create_goals_from_stream(FILE *stream)
37 lt_t *const lt = create_lt();
42 goals_t *const goals = PUSH_LT(lt, malloc(sizeof(goals_t)), free);
44 throw_error(ERROR_TYPE_LIBC);
48 goals->goals_count = 0;
49 if (fscanf(stream, "%lu", &goals->goals_count) == EOF) {
50 throw_error(ERROR_TYPE_LIBC);
54 goals->points = PUSH_LT(lt, malloc(sizeof(point_t) * goals->goals_count), free);
55 if (goals->points == NULL) {
56 throw_error(ERROR_TYPE_LIBC);
60 goals->regions = PUSH_LT(lt, malloc(sizeof(rect_t) * goals->goals_count), free);
61 if (goals->regions == NULL) {
62 throw_error(ERROR_TYPE_LIBC);
66 goals->colors = PUSH_LT(lt, malloc(sizeof(color_t) * goals->goals_count), free);
67 if (goals->colors == NULL) {
68 throw_error(ERROR_TYPE_LIBC);
72 goals->cue_states = PUSH_LT(lt, malloc(sizeof(int) * goals->goals_count), free);
73 if (goals->cue_states == NULL) {
74 throw_error(ERROR_TYPE_LIBC);
79 for (size_t i = 0; i < goals->goals_count; ++i) {
80 if (fscanf(stream, "%f%f%f%f%f%f%6s",
88 throw_error(ERROR_TYPE_LIBC);
91 goals->colors[i] = color_from_hexstr(color);
92 goals->cue_states[i] = CUE_STATE_VIRGIN;
101 void destroy_goals(goals_t *goals)
104 RETURN_LT0(goals->lt);
107 static int goals_render_core(const goals_t *goals,
109 SDL_Renderer *renderer,
110 const camera_t *camera)
116 const point_t position = vec_sum(
117 goals->points[goal_index],
118 vec(0.0f, sinf(goals->angle) * 10.0f));
120 return camera_fill_triangle(
123 triangle_mat3x3_product(
124 equilateral_triangle(),
126 trans_mat(position.x, position.y),
127 rot_mat(PI * -0.5f + goals->angle),
128 scale_mat(GOAL_RADIUS))),
129 goals->colors[goal_index]);
132 int goals_render(const goals_t *goals,
133 SDL_Renderer *renderer,
134 const camera_t *camera)
141 for (size_t i = 0; i < goals->goals_count; ++i) {
142 if (!goals_is_goal_hidden(goals, i)) {
143 if (goals_render_core(goals, i, renderer, camera) < 0) {
152 void goals_update(goals_t *goals,
156 assert(delta_time > 0.0f);
157 goals->angle = fmodf(goals->angle + 2.0f * delta_time, 2.0f * PI);
160 void goals_hide(goals_t *goals,
161 rect_t player_hitbox)
163 goals->player_hitbox = player_hitbox;
167 int goals_sound(goals_t *goals,
168 sound_medium_t *sound_medium)
170 for (size_t i = 0; i < goals->goals_count; ++i) {
171 switch (goals->cue_states[i]) {
172 case CUE_STATE_HIT_NOTHING:
173 sound_medium_play_sound(sound_medium, 0, goals->points[i], 0);
174 goals->cue_states[i] = CUE_STATE_SEEN_NOTHING;
184 void goals_cue(goals_t *goals,
185 SDL_Renderer *renderer,
186 const camera_t *camera)
188 for (size_t i = 0; i < goals->goals_count; ++i) {
189 switch (goals->cue_states[i]) {
190 case CUE_STATE_VIRGIN:
191 if (goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, renderer, goals->points[i])) {
192 goals->cue_states[i] = CUE_STATE_HIT_NOTHING;
197 case CUE_STATE_SEEN_NOTHING:
198 if (!goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, renderer, goals->points[i])) {
199 goals->cue_states[i] = CUE_STATE_VIRGIN;
208 void goals_checkpoint(const goals_t *goals,
214 for (size_t i = 0; i < goals->goals_count; ++i) {
215 if (goals->cue_states[i] == CUE_STATE_HIT_NOTHING) {
216 player_checkpoint(player, goals->points[i]);
221 /* Private Functions */
223 static int goals_is_goal_hidden(const goals_t *goals, size_t i)
225 return rects_overlap(goals->regions[i], goals->player_hitbox);