+#include <SDL2/SDL.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
-#include <SDL2/SDL.h>
-#include "./lt.h"
-#include "./player.h"
-#include "./platforms.h"
-#include "./point.h"
-#include "./error.h"
-#include "./rigid_rect.h"
-#include "./dying_rect.h"
-#include "./goals.h"
+#include "game/level/player/dying_rect.h"
+#include "game/level/player/rigid_rect.h"
+#include "goals.h"
+#include "math/point.h"
+#include "platforms.h"
+#include "player.h"
+#include "system/error.h"
+#include "system/lt.h"
#define PLAYER_WIDTH 25.0f
#define PLAYER_HEIGHT 25.0f
#define PLAYER_SPEED 500.0f
-#define PLAYER_JUMP 550.0f
+#define PLAYER_JUMP 32000.0f
#define PLAYER_DEATH_DURATION 0.75f
+#define PLAYER_MAX_JUMP_COUNT 2
typedef enum player_state_t {
PLAYER_STATE_ALIVE = 0,
int jump_count;
color_t color;
- /* TODO(#110): introduce checkpoints */
vec_t checkpoint;
+
+ int play_die_cue;
};
player_t *create_player(float x, float y, color_t color)
player->dying_body = PUSH_LT(
lt,
create_dying_rect(
- rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT),
color,
PLAYER_DEATH_DURATION),
destroy_dying_rect);
player->jump_count = 0;
player->color = color;
player->checkpoint = vec(x, y);
+ player->play_die_cue = 0;
return player;
}
RETURN_LT0(player->lt);
}
+solid_ref_t player_as_solid(player_t *player)
+{
+ solid_ref_t ref = {
+ .tag = SOLID_PLAYER,
+ .ptr = (void*) player
+ };
+
+ return ref;
+}
+
int player_render(const player_t * player,
- SDL_Renderer *renderer,
- const camera_t *camera)
+ camera_t *camera)
{
assert(player);
- assert(renderer);
assert(camera);
switch (player->state) {
case PLAYER_STATE_ALIVE:
- return rigid_rect_render(player->alive_body, renderer, camera);
+ return rigid_rect_render(player->alive_body, camera);
case PLAYER_STATE_DYING:
- return dying_rect_render(player->dying_body, renderer, camera);
+ return dying_rect_render(player->dying_body, camera);
default: {}
}
}
void player_update(player_t *player,
- const platforms_t *platforms,
float delta_time)
{
assert(player);
- assert(platforms);
switch (player->state) {
case PLAYER_STATE_ALIVE: {
- rigid_rect_update(player->alive_body, platforms, delta_time);
-
- if (rigid_rect_touches_ground(player->alive_body)) {
- player->jump_count = 0;
- }
+ rigid_rect_update(player->alive_body, delta_time);
const rect_t hitbox = rigid_rect_hitbox(player->alive_body);
dying_rect_update(player->dying_body, delta_time);
if (dying_rect_is_dead(player->dying_body)) {
- player->alive_body = RESET_LT(
- player->lt,
+ rigid_rect_transform_velocity(
player->alive_body,
- create_rigid_rect(
- rect_from_vecs(
- player->checkpoint,
- vec(PLAYER_WIDTH, PLAYER_HEIGHT)),
- player->color));
+ make_mat3x3(0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f));
+ rigid_rect_teleport_to(player->alive_body, player->checkpoint);
player->state = PLAYER_STATE_ALIVE;
}
} break;
}
}
+void player_collide_with_solid(player_t *player, solid_ref_t solid)
+{
+ if (player->state == PLAYER_STATE_ALIVE) {
+ rigid_rect_collide_with_solid(player->alive_body, solid);
+
+ if (rigid_rect_touches_ground(player->alive_body)) {
+ player->jump_count = 0;
+ }
+ }
+}
+
void player_move_left(player_t *player)
{
assert(player);
void player_jump(player_t *player)
{
assert(player);
- if (player->jump_count < 2) {
- rigid_rect_jump(player->alive_body, PLAYER_JUMP);
+ if (player->jump_count < PLAYER_MAX_JUMP_COUNT) {
+ rigid_rect_transform_velocity(player->alive_body,
+ make_mat3x3(1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f));
+ rigid_rect_apply_force(player->alive_body,
+ vec(0.0f, -PLAYER_JUMP));
player->jump_count++;
}
}
assert(player);
if (player->state == PLAYER_STATE_ALIVE) {
- player->dying_body = RESET_LT(
- player->lt,
- player->dying_body,
- create_dying_rect(
- rigid_rect_hitbox(player->alive_body),
- player->color,
- PLAYER_DEATH_DURATION));
+ const rect_t hitbox =
+ rigid_rect_hitbox(player->alive_body);
+
+ player->play_die_cue = 1;
+ dying_rect_start_dying(player->dying_body, vec(hitbox.x, hitbox.y));
player->state = PLAYER_STATE_DYING;
}
}
{
player->checkpoint = checkpoint;
}
+
+int player_sound(player_t *player,
+ sound_samples_t *sound_samples)
+{
+ if (player->play_die_cue) {
+ player->play_die_cue = 0;
+
+ if (sound_samples_play_sound(sound_samples, 0, 0) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void player_touches_rect_sides(player_t *player,
+ rect_t object,
+ int sides[RECT_SIDE_N])
+{
+ if (player->state == PLAYER_STATE_ALIVE) {
+ rigid_rect_touches_rect_sides(player->alive_body, object, sides);
+ }
+}
+
+void player_apply_force(player_t *player, vec_t force)
+{
+ if (player->state == PLAYER_STATE_ALIVE) {
+ rigid_rect_apply_force(player->alive_body, force);
+ }
+}