6 #include "game/level/player/dying_rect.h"
7 #include "game/level/player/rigid_rect.h"
9 #include "math/point.h"
10 #include "platforms.h"
12 #include "system/error.h"
13 #include "system/lt.h"
15 #define PLAYER_WIDTH 25.0f
16 #define PLAYER_HEIGHT 25.0f
17 #define PLAYER_SPEED 500.0f
18 #define PLAYER_JUMP 32000.0f
19 #define PLAYER_DEATH_DURATION 0.75f
20 #define PLAYER_MAX_JUMP_COUNT 2
22 typedef enum player_state_t {
23 PLAYER_STATE_ALIVE = 0,
31 rigid_rect_t *alive_body;
32 dying_rect_t *dying_body;
42 player_t *create_player(float x, float y, color_t color)
44 lt_t *lt = create_lt();
50 player_t *player = PUSH_LT(lt, malloc(sizeof(player_t)), free);
52 throw_error(ERROR_TYPE_LIBC);
56 player->state = PLAYER_STATE_ALIVE;
58 player->alive_body = PUSH_LT(
61 rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT),
64 if (player->alive_body == NULL) {
68 player->dying_body = PUSH_LT(
72 PLAYER_DEATH_DURATION),
74 if (player->dying_body == NULL) {
79 player->jump_count = 0;
80 player->color = color;
81 player->checkpoint = vec(x, y);
82 player->play_die_cue = 0;
87 player_t *create_player_from_stream(FILE *stream)
89 float x = 0.0f, y = 0.0f;
92 if (fscanf(stream, "%f%f%6s", &x, &y, color) == EOF) {
93 throw_error(ERROR_TYPE_LIBC);
97 return create_player(x, y, color_from_hexstr(color));
100 void destroy_player(player_t * player)
102 RETURN_LT0(player->lt);
105 solid_ref_t player_as_solid(player_t *player)
109 .ptr = (void*) player
115 int player_render(const player_t * player,
121 switch (player->state) {
122 case PLAYER_STATE_ALIVE:
123 return rigid_rect_render(player->alive_body, camera);
125 case PLAYER_STATE_DYING:
126 return dying_rect_render(player->dying_body, camera);
134 void player_update(player_t *player,
139 switch (player->state) {
140 case PLAYER_STATE_ALIVE: {
141 rigid_rect_update(player->alive_body, delta_time);
143 const rect_t hitbox = rigid_rect_hitbox(player->alive_body);
145 if (hitbox.y > 1000.0f) {
150 case PLAYER_STATE_DYING: {
151 dying_rect_update(player->dying_body, delta_time);
153 if (dying_rect_is_dead(player->dying_body)) {
154 rigid_rect_transform_velocity(
156 make_mat3x3(0.0f, 0.0f, 0.0f,
159 rigid_rect_teleport_to(player->alive_body, player->checkpoint);
160 player->state = PLAYER_STATE_ALIVE;
168 void player_collide_with_solid(player_t *player, solid_ref_t solid)
170 if (player->state == PLAYER_STATE_ALIVE) {
171 rigid_rect_collide_with_solid(player->alive_body, solid);
173 if (rigid_rect_touches_ground(player->alive_body)) {
174 player->jump_count = 0;
179 void player_move_left(player_t *player)
182 rigid_rect_move(player->alive_body, vec(-PLAYER_SPEED, 0.0f));
185 void player_move_right(player_t *player)
189 rigid_rect_move(player->alive_body, vec(PLAYER_SPEED, 0.0f));
192 void player_stop(player_t *player)
196 rigid_rect_move(player->alive_body, vec(0.0f, 0.0f));
199 void player_jump(player_t *player)
202 if (player->jump_count < PLAYER_MAX_JUMP_COUNT) {
203 rigid_rect_transform_velocity(player->alive_body,
204 make_mat3x3(1.0f, 0.0f, 0.0f,
207 rigid_rect_apply_force(player->alive_body,
208 vec(0.0f, -PLAYER_JUMP));
209 player->jump_count++;
213 void player_die(player_t *player)
217 if (player->state == PLAYER_STATE_ALIVE) {
218 const rect_t hitbox =
219 rigid_rect_hitbox(player->alive_body);
221 player->play_die_cue = 1;
222 dying_rect_start_dying(player->dying_body, vec(hitbox.x, hitbox.y));
223 player->state = PLAYER_STATE_DYING;
227 void player_focus_camera(player_t *player,
233 const rect_t player_hitbox = rigid_rect_hitbox(player->alive_body);
238 vec(player_hitbox.x, player_hitbox.y),
239 vec(0.0f, -player_hitbox.h * 0.5f)));
242 void player_hide_goals(const player_t *player,
247 goals_hide(goals, rigid_rect_hitbox(player->alive_body));
250 void player_die_from_lava(player_t *player,
253 if (lava_overlaps_rect(lava, rigid_rect_hitbox(player->alive_body))) {
258 void player_checkpoint(player_t *player, vec_t checkpoint)
260 player->checkpoint = checkpoint;
263 int player_sound(player_t *player,
264 sound_samples_t *sound_samples)
266 if (player->play_die_cue) {
267 player->play_die_cue = 0;
269 if (sound_samples_play_sound(sound_samples, 0, 0) < 0) {
277 void player_touches_rect_sides(player_t *player,
279 int sides[RECT_SIDE_N])
281 if (player->state == PLAYER_STATE_ALIVE) {
282 rigid_rect_touches_rect_sides(player->alive_body, object, sides);
286 void player_apply_force(player_t *player, vec_t force)
288 if (player->state == PLAYER_STATE_ALIVE) {
289 rigid_rect_apply_force(player->alive_body, force);