Lt *lt;
Background *background;
+ RigidBodies *rigid_bodies;
Player *player;
Platforms *platforms;
Goals *goals;
Labels *labels;
Regions *regions;
Physical_world *physical_world;
- RigidBodies *rigid_bodies;
bool flying_mode;
Vec flying_camera_position;
RETURN_LT(lt, NULL);
}
+ level->rigid_bodies = PUSH_LT(lt, create_rigid_bodies(1024), destroy_rigid_bodies);
+ if (level->rigid_bodies == NULL) {
+ RETURN_LT(lt, NULL);
+ }
+
level->player = PUSH_LT(
lt,
- create_player_from_line_stream(level_stream, broadcast),
+ create_player_from_line_stream(level_stream, level->rigid_bodies, broadcast),
destroy_player);
if (level->player == NULL) {
RETURN_LT(lt, NULL);
if (level->physical_world == NULL) {
RETURN_LT(lt, NULL);
}
- if (physical_world_add_solid(
- level->physical_world,
- player_as_solid(level->player)) < 0) { RETURN_LT(lt, NULL); }
if (boxes_add_to_physical_world(
level->boxes,
level->physical_world) < 0) { RETURN_LT(lt, NULL); }
- level->rigid_bodies = PUSH_LT(lt, create_rigid_bodies(1024), destroy_rigid_bodies);
- if (level->rigid_bodies == NULL) {
- RETURN_LT(lt, NULL);
- }
-
level->flying_mode = false;
level->flying_camera_position = vec(0.0f, 0.0f);
level->flying_camera_scale = 1.0f;
return -1;
}
- if (rigid_bodies_render(level->rigid_bodies, camera) < 0) {
- return -1;
- }
-
return 0;
}
boxes_float_in_lava(level->boxes, level->lava);
rigid_bodies_apply_omniforce(level->rigid_bodies, vec(0.0f, LEVEL_GRAVITY));
- rigid_bodies_update(level->rigid_bodies, delta_time);
boxes_update(level->boxes, delta_time);
player_update(level->player, delta_time);
}
level->background = RESET_LT(level->lt, level->background, background);
- Player * const skipped_player = create_player_from_line_stream(level_stream, broadcast);
+ Player * const skipped_player = create_player_from_line_stream(level_stream, level->rigid_bodies, broadcast);
if (skipped_player == NULL) {
RETURN_LT(lt, -1);
}
level->regions = RESET_LT(level->lt, level->regions, regions);
physical_world_clean(level->physical_world);
- if (physical_world_add_solid(
- level->physical_world,
- player_as_solid(level->player)) < 0) { RETURN_LT(lt, -1); }
if (boxes_add_to_physical_world(
level->boxes,
level->physical_world) < 0) { RETURN_LT(lt, -1); }
trace_assert(level);
trace_assert(rigid_rect_id);
- Rigid_rect *rigid_rect = player_rigid_rect(level->player,
- rigid_rect_id);
- if (rigid_rect != NULL) {
- return rigid_rect;
- }
-
- rigid_rect = boxes_rigid_rect(level->boxes, rigid_rect_id);
+ Rigid_rect *rigid_rect = boxes_rigid_rect(level->boxes, rigid_rect_id);
if (rigid_rect != NULL) {
return rigid_rect;
}
#include "game/level/player/dying_rect.h"
#include "game/level/player/rigid_rect.h"
#include "game/level/script.h"
+#include "game/level/rigid_bodies.h"
#include "goals.h"
#include "math/point.h"
#include "platforms.h"
Lt *lt;
Player_state state;
- Rigid_rect *alive_body;
+ RigidBodies *rigid_bodies;
+
+ RigidBodyId alive_body_id;
Dying_rect *dying_body;
Script *script;
int play_die_cue;
};
-Player *create_player_from_line_stream(LineStream *line_stream, Broadcast *broadcast)
+Player *create_player_from_line_stream(LineStream *line_stream, RigidBodies *rigid_bodies, Broadcast *broadcast)
{
trace_assert(line_stream);
}
player->lt = lt;
+ player->rigid_bodies = rigid_bodies;
+
float x = 0.0f, y = 0.0f;
char colorstr[7];
const Color color = hexstr(colorstr);
- player->alive_body = PUSH_LT(
- lt,
- create_rigid_rect(
- rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT),
- color,
- "player"),
- destroy_rigid_rect);
- if (player->alive_body == NULL) {
- RETURN_LT(lt, NULL);
- }
+ player->alive_body_id = rigid_bodies_add(
+ rigid_bodies,
+ rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT),
+ color);
player->dying_body = PUSH_LT(
lt,
RETURN_LT0(player->lt);
}
-Solid_ref player_as_solid(Player *player)
-{
- Solid_ref ref = {
- .tag = SOLID_PLAYER,
- .ptr = (void*) player
- };
-
- return ref;
-}
-
int player_render(const Player * player,
Camera *camera)
{
trace_assert(player);
trace_assert(camera);
+ char debug_text[256];
+
switch (player->state) {
- case PLAYER_STATE_ALIVE:
- return rigid_rect_render(player->alive_body, camera);
+ case PLAYER_STATE_ALIVE: {
+ snprintf(debug_text, 256, "Jump: %d", player->jump_threshold);
+ Rect hitbox = rigid_bodies_hitbox(player->rigid_bodies, player->alive_body_id);
+
+ if (camera_render_debug_text(camera, debug_text, vec(hitbox.x, hitbox.y - 20.0f)) < 0) {
+ return -1;
+ }
+
+ return rigid_bodies_render(player->rigid_bodies, player->alive_body_id, camera);
+ }
case PLAYER_STATE_DYING:
return dying_rect_render(player->dying_body, camera);
switch (player->state) {
case PLAYER_STATE_ALIVE: {
- rigid_rect_update(player->alive_body, delta_time);
+ rigid_bodies_update(player->rigid_bodies, player->alive_body_id, delta_time);
+
+ const Rect hitbox = rigid_bodies_hitbox(player->rigid_bodies, player->alive_body_id);
- const Rect hitbox = rigid_rect_hitbox(player->alive_body);
if (hitbox.y > 1000.0f) {
player_die(player);
dying_rect_update(player->dying_body, delta_time);
if (dying_rect_is_dead(player->dying_body)) {
- rigid_rect_transform_velocity(
- player->alive_body,
+ rigid_bodies_transform_velocity(
+ player->rigid_bodies,
+ player->alive_body_id,
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);
+ rigid_bodies_teleport_to(
+ player->rigid_bodies,
+ player->alive_body_id,
+ player->checkpoint);
player->state = PLAYER_STATE_ALIVE;
}
} break;
}
}
-void player_collide_with_solid(Player *player, Solid_ref 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_threshold = 0;
- }
- }
-}
-
void player_move_left(Player *player)
{
trace_assert(player);
- rigid_rect_move(player->alive_body, vec(-PLAYER_SPEED, 0.0f));
+ rigid_bodies_move(player->rigid_bodies, player->alive_body_id, vec(-PLAYER_SPEED, 0.0f));
}
void player_move_right(Player *player)
{
trace_assert(player);
- rigid_rect_move(player->alive_body, vec(PLAYER_SPEED, 0.0f));
+ rigid_bodies_move(player->rigid_bodies, player->alive_body_id, vec(PLAYER_SPEED, 0.0f));
}
void player_stop(Player *player)
{
trace_assert(player);
- rigid_rect_move(player->alive_body, vec(0.0f, 0.0f));
+ rigid_bodies_move(player->rigid_bodies, player->alive_body_id, vec(0.0f, 0.0f));
}
void player_jump(Player *player)
{
trace_assert(player);
+
+ if (rigid_bodies_touches_ground(player->rigid_bodies, player->alive_body_id)) {
+ player->jump_threshold = 0;
+ }
+
if (player->jump_threshold < PLAYER_MAX_JUMP_THRESHOLD) {
- 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));
+ rigid_bodies_transform_velocity(
+ player->rigid_bodies,
+ player->alive_body_id,
+ make_mat3x3(1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f));
+ rigid_bodies_apply_force(
+ player->rigid_bodies,
+ player->alive_body_id,
+ vec(0.0f, -PLAYER_JUMP));
player->jump_threshold++;
if (script_has_scope_value(player->script, "on-jump")) {
if (player->state == PLAYER_STATE_ALIVE) {
const Rect hitbox =
- rigid_rect_hitbox(player->alive_body);
+ rigid_bodies_hitbox(
+ player->rigid_bodies,
+ player->alive_body_id);
player->play_die_cue = 1;
dying_rect_start_dying(player->dying_body, vec(hitbox.x, hitbox.y));
trace_assert(player);
trace_assert(camera);
- const Rect player_hitbox = rigid_rect_hitbox(player->alive_body);
+ const Rect player_hitbox = rigid_bodies_hitbox(
+ player->rigid_bodies,
+ player->alive_body_id);
camera_center_at(
camera,
{
trace_assert(player);
trace_assert(goals);
- goals_hide_from_player(goals, rigid_rect_hitbox(player->alive_body));
+ goals_hide_from_player(
+ goals,
+ rigid_bodies_hitbox(
+ player->rigid_bodies,
+ player->alive_body_id));
}
void player_die_from_lava(Player *player,
const Lava *lava)
{
- if (lava_overlaps_rect(lava, rigid_rect_hitbox(player->alive_body))) {
+ if (lava_overlaps_rect(
+ lava,
+ rigid_bodies_hitbox(
+ player->rigid_bodies,
+ player->alive_body_id))) {
player_die(player);
}
}
return 0;
}
-void player_touches_rect_sides(Player *player,
- Rect 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 *player, Vec force)
-{
- if (player->state == PLAYER_STATE_ALIVE) {
- rigid_rect_apply_force(player->alive_body, force);
- }
-}
-
-Rigid_rect *player_rigid_rect(Player *player, const char *id)
-{
- trace_assert(player);
- trace_assert(id);
-
- if (player->state == PLAYER_STATE_ALIVE) {
- if (rigid_rect_has_id(player->alive_body, id)) {
- return player->alive_body;
- }
- }
-
- return NULL;
-}
-
bool player_overlaps_rect(const Player *player,
Rect rect)
{
return player->state == PLAYER_STATE_ALIVE
&& rects_overlap(
- rect, rigid_rect_hitbox(
- player->alive_body));
+ rect, rigid_bodies_hitbox(
+ player->rigid_bodies,
+ player->alive_body_id));
}
typedef struct LineStream LineStream;
typedef struct Script Script;
typedef struct Broadcast Broadcast;
+typedef struct RigidBodies RigidBodies;
-Player *create_player_from_line_stream(LineStream *line_stream, Broadcast *broadcast);
+Player *create_player_from_line_stream(LineStream *line_stream, RigidBodies *rigid_bodies, Broadcast *broadcast);
void destroy_player(Player * player);
Solid_ref player_as_solid(Player *player);
int rigid_bodies_collide(RigidBodies *rigid_bodies,
const Platforms *platforms)
{
+ // TODO: RigidBodies should collide only the bodies that were updated on after a previous collision
+ memset(rigid_bodies->grounded, 0, sizeof(bool) * rigid_bodies->count);
+
if (rigid_bodies_collide_with_itself(rigid_bodies) < 0) {
return -1;
}
}
int rigid_bodies_update(RigidBodies *rigid_bodies,
+ RigidBodyId id,
float delta_time)
{
trace_assert(rigid_bodies);
- memset(rigid_bodies->grounded, 0,
- sizeof(bool) * rigid_bodies->count);
-
- for (size_t i = 0; i < rigid_bodies->count; ++i) {
- rigid_bodies->velocities[i] = vec_sum(
- rigid_bodies->velocities[i],
+ rigid_bodies->velocities[id] = vec_sum(
+ rigid_bodies->velocities[id],
vec_scala_mult(
- rigid_bodies->forces[i],
+ rigid_bodies->forces[id],
delta_time));
- }
- for (size_t i = 0; i < rigid_bodies->count; ++i) {
- Vec position = vec(rigid_bodies->bodies[i].x,
- rigid_bodies->bodies[i].y);
+ Vec position = vec(rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y);
- position = vec_sum(
- position,
- vec_scala_mult(
- vec_sum(
- rigid_bodies->velocities[i],
- rigid_bodies->movements[i]),
- delta_time));
+ position = vec_sum(
+ position,
+ vec_scala_mult(
+ vec_sum(
+ rigid_bodies->velocities[id],
+ rigid_bodies->movements[id]),
+ delta_time));
- rigid_bodies->bodies[i].x = position.x;
- rigid_bodies->bodies[i].y = position.y;
- }
+ rigid_bodies->bodies[id].x = position.x;
+ rigid_bodies->bodies[id].y = position.y;
- memset(rigid_bodies->forces, 0,
- sizeof(Vec) * rigid_bodies->count);
+ rigid_bodies->forces[id] = vec(0.0f, 0.0f);
return 0;
}
int rigid_bodies_render(RigidBodies *rigid_bodies,
+ RigidBodyId id,
Camera *camera)
{
trace_assert(rigid_bodies);
char text_buffer[256];
- for (size_t i = 0; i < rigid_bodies->count; ++i) {
- if (camera_fill_rect(
- camera,
- rigid_bodies->bodies[i],
- rigid_bodies->colors[i]) < 0) {
- return -1;
- }
+ if (camera_fill_rect(
+ camera,
+ rigid_bodies->bodies[id],
+ rigid_bodies->colors[id]) < 0) {
+ return -1;
+ }
- snprintf(text_buffer, ID_SIZE, "%ld", i);
+ snprintf(text_buffer, ID_SIZE, "id: %ld", id);
- if (camera_render_debug_text(
- camera,
- text_buffer,
- vec(rigid_bodies->bodies[i].x,
- rigid_bodies->bodies[i].y)) < 0) {
- return -1;
- }
+ if (camera_render_debug_text(
+ camera,
+ text_buffer,
+ vec(rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y)) < 0) {
+ return -1;
+ }
- snprintf(text_buffer, 256, "(%f, %f)",
- rigid_bodies->bodies[i].x,
- rigid_bodies->bodies[i].y);
- if (camera_render_debug_text(
- camera,
- text_buffer,
- vec(rigid_bodies->bodies[i].x,
- rigid_bodies->bodies[i].y + FONT_CHAR_HEIGHT * 2.0f))) {
- return -1;
- }
+ snprintf(text_buffer, 256, "pos:(%f, %f)",
+ rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y);
+ if (camera_render_debug_text(
+ camera,
+ text_buffer,
+ vec(rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y + FONT_CHAR_HEIGHT * 2.0f))) {
+ return -1;
}
return 0;
const Platforms *platforms);
int rigid_bodies_update(RigidBodies *rigid_bodies,
+ RigidBodyId id,
float delta_time);
int rigid_bodies_render(RigidBodies *rigid_bodies,
+ RigidBodyId id,
Camera *camera);
RigidBodyId rigid_bodies_add(RigidBodies *rigid_bodies,
Rect rect,
case SOLID_RIGID_RECT:
rigid_rect_touches_rect_sides((Rigid_rect *) solid.ptr, object, sides);
break;
-
- case SOLID_PLAYER:
- player_touches_rect_sides((Player *) solid.ptr, object, sides);
- break;
}
}
rigid_rect_apply_force((Rigid_rect *) solid.ptr, force);
break;
- case SOLID_PLAYER:
- player_apply_force((Player *) solid.ptr, force);
- break;
-
default: {}
}
}
rigid_rect_collide_with_solid((Rigid_rect *) solid.ptr, other_solid);
break;
- case SOLID_PLAYER:
- player_collide_with_solid((Player *) solid.ptr, other_solid);
- break;
-
default: {}
}
}
typedef enum Solid_tag {
SOLID_PLATFORMS = 0,
- SOLID_RIGID_RECT,
- SOLID_PLAYER
+ SOLID_RIGID_RECT
} Solid_tag;
typedef struct Solid_ref {