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_PLAY_SOMETHING,
20 CUE_STATE_PLAY_NOTHING,
29 cue_state_t *cue_states;
35 goals_t *create_goals_from_stream(FILE *stream)
39 lt_t *const lt = create_lt();
44 goals_t *const goals = PUSH_LT(lt, malloc(sizeof(goals_t)), free);
46 throw_error(ERROR_TYPE_LIBC);
50 goals->goals_count = 0;
51 if (fscanf(stream, "%lu", &goals->goals_count) == EOF) {
52 throw_error(ERROR_TYPE_LIBC);
56 goals->points = PUSH_LT(lt, malloc(sizeof(point_t) * goals->goals_count), free);
57 if (goals->points == NULL) {
58 throw_error(ERROR_TYPE_LIBC);
62 goals->regions = PUSH_LT(lt, malloc(sizeof(rect_t) * goals->goals_count), free);
63 if (goals->regions == NULL) {
64 throw_error(ERROR_TYPE_LIBC);
68 goals->colors = PUSH_LT(lt, malloc(sizeof(color_t) * goals->goals_count), free);
69 if (goals->colors == NULL) {
70 throw_error(ERROR_TYPE_LIBC);
74 goals->cue_states = PUSH_LT(lt, malloc(sizeof(int) * goals->goals_count), free);
75 if (goals->cue_states == NULL) {
76 throw_error(ERROR_TYPE_LIBC);
81 for (size_t i = 0; i < goals->goals_count; ++i) {
82 if (fscanf(stream, "%f%f%f%f%f%f%6s",
90 throw_error(ERROR_TYPE_LIBC);
93 goals->colors[i] = color_from_hexstr(color);
94 goals->cue_states[i] = CUE_STATE_VIRGIN;
103 void destroy_goals(goals_t *goals)
106 RETURN_LT0(goals->lt);
109 static int goals_render_core(const goals_t *goals,
111 SDL_Renderer *renderer,
112 const camera_t *camera)
118 const point_t position = vec_sum(
119 goals->points[goal_index],
120 vec(0.0f, sinf(goals->angle) * 10.0f));
122 return camera_fill_triangle(
125 triangle_mat3x3_product(
126 equilateral_triangle(),
128 trans_mat(position.x, position.y),
129 rot_mat(PI * -0.5f + goals->angle),
130 scale_mat(GOAL_RADIUS))),
131 goals->colors[goal_index]);
134 int goals_render(const goals_t *goals,
135 SDL_Renderer *renderer,
136 const camera_t *camera)
143 for (size_t i = 0; i < goals->goals_count; ++i) {
144 if (!goals_is_goal_hidden(goals, i)) {
145 if (goals_render_core(goals, i, renderer, camera) < 0) {
154 void goals_update(goals_t *goals,
158 assert(delta_time > 0.0f);
159 goals->angle = fmodf(goals->angle + 2.0f * delta_time, 2.0f * PI);
162 void goals_hide(goals_t *goals,
163 rect_t player_hitbox)
165 goals->player_hitbox = player_hitbox;
169 int goals_sound(goals_t *goals,
170 sound_medium_t *sound_medium)
172 for (size_t i = 0; i < goals->goals_count; ++i) {
173 switch (goals->cue_states[i]) {
174 case CUE_STATE_PLAY_SOMETHING:
175 sound_medium_play_sound(sound_medium, 1, goals->points[i], 0);
176 goals->cue_states[i] = CUE_STATE_SOMETHING;
179 case CUE_STATE_PLAY_NOTHING:
180 sound_medium_play_sound(sound_medium, 0, goals->points[i], 0);
181 goals->cue_states[i] = CUE_STATE_NOTHING;
191 void goals_cue(goals_t *goals,
192 SDL_Renderer *renderer,
193 const camera_t *camera)
195 for (size_t i = 0; i < goals->goals_count; ++i) {
196 switch (goals->cue_states[i]) {
197 case CUE_STATE_VIRGIN:
198 if (!goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, renderer, goals->points[i])) {
199 goals->cue_states[i] = CUE_STATE_PLAY_SOMETHING;
204 case CUE_STATE_SOMETHING:
205 if (goals_is_goal_hidden(goals, i) && camera_is_point_visible(camera, renderer, goals->points[i])) {
206 goals->cue_states[i] = CUE_STATE_PLAY_NOTHING;
211 case CUE_STATE_NOTHING:
212 if (goals_is_goal_hidden(goals, i) && !camera_is_point_visible(camera, renderer, goals->points[i])) {
213 goals->cue_states[i] = CUE_STATE_VIRGIN;
222 /* Private Functions */
224 static int goals_is_goal_hidden(const goals_t *goals, size_t i)
226 return rects_overlap(goals->regions[i], goals->player_hitbox);