add collisions
This commit is contained in:
parent
937693b16e
commit
c3a4a06403
29
src/entity.h
Normal file
29
src/entity.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
enum EntityType {
|
||||||
|
ENTITY_TYPE_NIL = 0,
|
||||||
|
ENTITY_TYPE_PLAYER,
|
||||||
|
ENTITY_TYPE_WALL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntityFlags {
|
||||||
|
bool has_friction : 1;
|
||||||
|
bool has_max_speed : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Entity {
|
||||||
|
enum EntityType type;
|
||||||
|
struct EntityFlags flags;
|
||||||
|
|
||||||
|
Vector2 position;
|
||||||
|
Vector2 velocity;
|
||||||
|
Vector2 accelaration;
|
||||||
|
float max_speed;
|
||||||
|
float friction;
|
||||||
|
// TODO: Remove this, because this is just a temporary value for resolving collisions
|
||||||
|
Vector2 step;
|
||||||
|
|
||||||
|
Rectangle collision_rect;
|
||||||
|
};
|
||||||
12
src/entity_id_list.c
Normal file
12
src/entity_id_list.c
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "entity_id_list.h"
|
||||||
|
|
||||||
|
DEFINE_VECTOR_ENSURE_METHOD_CAPACITY(entity_id_list_ensure_capacity, struct EntityIdList, EntityId);
|
||||||
|
DEFINE_VECTOR_METHOD_FREE(entity_id_list_free, struct EntityIdList);
|
||||||
|
DEFINE_VECTOR_METHOD_FREE(entity_id_list_clear_retaining_capacity, struct EntityIdList);
|
||||||
|
|
||||||
|
void entity_id_list_add(struct EntityIdList *list, EntityId id)
|
||||||
|
{
|
||||||
|
entity_id_list_ensure_capacity(list, list->len + 1);
|
||||||
|
|
||||||
|
list->items[list->len++] = id;
|
||||||
|
}
|
||||||
11
src/entity_id_list.h
Normal file
11
src/entity_id_list.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "entity_id.h"
|
||||||
|
#include "generic_vector.h"
|
||||||
|
|
||||||
|
DEFINE_VECTOR_STRUCT(EntityIdList, EntityId);
|
||||||
|
|
||||||
|
void entity_id_list_add(struct EntityIdList *list, EntityId id);
|
||||||
|
void entity_id_list_free(struct EntityIdList *list);
|
||||||
|
void entity_id_list_clear_retaining_capacity(struct EntityIdList *list);
|
||||||
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "entity_id.h"
|
#include "entity_id.h"
|
||||||
|
#include "entity.h"
|
||||||
struct Entity {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EntitySlot {
|
struct EntitySlot {
|
||||||
bool used;
|
bool used;
|
||||||
|
|||||||
12
src/float_list.c
Normal file
12
src/float_list.c
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "float_list.h"
|
||||||
|
|
||||||
|
DEFINE_VECTOR_ENSURE_METHOD_CAPACITY(float_list_ensure_capacity, struct FloatList, float);
|
||||||
|
DEFINE_VECTOR_METHOD_FREE(float_list_free, struct FloatList);
|
||||||
|
DEFINE_VECTOR_METHOD_FREE(float_list_clear_retaining_capacity, struct FloatList);
|
||||||
|
|
||||||
|
void float_list_add(struct FloatList *list, float value)
|
||||||
|
{
|
||||||
|
float_list_ensure_capacity(list, list->len + 1);
|
||||||
|
|
||||||
|
list->items[list->len++] = value;
|
||||||
|
}
|
||||||
8
src/float_list.h
Normal file
8
src/float_list.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "generic_vector.h"
|
||||||
|
|
||||||
|
DEFINE_VECTOR_STRUCT(FloatList, float);
|
||||||
|
|
||||||
|
void float_list_add(struct FloatList *list, float value);
|
||||||
|
void float_list_free(struct FloatList *list);
|
||||||
405
src/game.c
405
src/game.c
@ -1,14 +1,316 @@
|
|||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "entity.h"
|
||||||
|
#include "entity_id_list.h"
|
||||||
|
#include "float_list.h"
|
||||||
|
#include "raymath.h"
|
||||||
|
#include <raylib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
void game_init(struct Game *game)
|
void game_init(struct Game *game)
|
||||||
{
|
{
|
||||||
*game = (struct Game){
|
*game = (struct Game){
|
||||||
.canvas_size = { 800, 600 }
|
.canvas_size = { 800, 600 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
struct Entity *player = entity_list_add(&game->entities);
|
||||||
|
player->type = ENTITY_TYPE_PLAYER;
|
||||||
|
player->position = Vector2Scale(game->canvas_size, 0.5);
|
||||||
|
player->collision_rect = (Rectangle){
|
||||||
|
.x = -10,
|
||||||
|
.y = -10,
|
||||||
|
.width = 20,
|
||||||
|
.height = 20
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
float wall_thickness = 10;
|
||||||
|
|
||||||
|
// Canvas bounds
|
||||||
|
{
|
||||||
|
game_add_wall(game, (Rectangle){
|
||||||
|
.x = -wall_thickness,
|
||||||
|
.y = -wall_thickness,
|
||||||
|
.width = game->canvas_size.x + 2*wall_thickness,
|
||||||
|
.height = wall_thickness
|
||||||
|
});
|
||||||
|
|
||||||
|
game_add_wall(game, (Rectangle){
|
||||||
|
.x = -wall_thickness,
|
||||||
|
.y = game->canvas_size.y,
|
||||||
|
.width = game->canvas_size.x + 2*wall_thickness,
|
||||||
|
.height = wall_thickness
|
||||||
|
});
|
||||||
|
|
||||||
|
game_add_wall(game, (Rectangle){
|
||||||
|
.x = -wall_thickness,
|
||||||
|
.y = -wall_thickness,
|
||||||
|
.width = wall_thickness,
|
||||||
|
.height = game->canvas_size.y + 2*wall_thickness
|
||||||
|
});
|
||||||
|
|
||||||
|
game_add_wall(game, (Rectangle){
|
||||||
|
.x = game->canvas_size.x,
|
||||||
|
.y = -wall_thickness,
|
||||||
|
.width = wall_thickness,
|
||||||
|
.height = game->canvas_size.y + 2*wall_thickness
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
game_add_wall(game, (Rectangle){
|
||||||
|
.x = 10 + 45 * i,
|
||||||
|
.y = 10,
|
||||||
|
.width = 40,
|
||||||
|
.height = 40
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EntityId wall_id = game_add_wall(game, (Rectangle){
|
||||||
|
.x = 10,
|
||||||
|
.y = 10,
|
||||||
|
.width = 40,
|
||||||
|
.height = 200
|
||||||
|
});
|
||||||
|
struct Entity *wall = entity_list_get(&game->entities, wall_id);
|
||||||
|
wall->velocity.x = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EntityId wall_id = game_add_wall(game, (Rectangle){
|
||||||
|
.x = 700,
|
||||||
|
.y = 10,
|
||||||
|
.width = 40,
|
||||||
|
.height = 200
|
||||||
|
});
|
||||||
|
struct Entity *wall = entity_list_get(&game->entities, wall_id);
|
||||||
|
wall->velocity.x = -100;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_free(struct Game *game)
|
void game_free(struct Game *game)
|
||||||
{
|
{
|
||||||
|
entity_list_free(&game->entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityId game_add_wall(struct Game *game, Rectangle rect)
|
||||||
|
{
|
||||||
|
struct Entity *wall = entity_list_add(&game->entities);
|
||||||
|
|
||||||
|
wall->type = ENTITY_TYPE_WALL;
|
||||||
|
wall->position = (Vector2){
|
||||||
|
.x = rect.x,
|
||||||
|
.y = rect.y,
|
||||||
|
};
|
||||||
|
wall->collision_rect = (Rectangle){
|
||||||
|
.width = rect.width,
|
||||||
|
.height = rect.height
|
||||||
|
};
|
||||||
|
|
||||||
|
return entity_list_get_id(&game->entities, wall);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float game_aabb(Rectangle b1, Rectangle b2)
|
||||||
|
{
|
||||||
|
return CheckCollisionRecs(b1, b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CollisionResult {
|
||||||
|
float time;
|
||||||
|
Vector2 normal;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool game_swept_aabb(Rectangle b1, Vector2 v1, Rectangle b2, struct CollisionResult *result)
|
||||||
|
{
|
||||||
|
float entryX, exitX;
|
||||||
|
if (v1.x > 0) {
|
||||||
|
entryX = b2.x - (b1.x + b1.width);
|
||||||
|
exitX = (b2.x + b2.width) - b1.x;
|
||||||
|
} else {
|
||||||
|
entryX = (b2.x + b2.width) - b1.x;
|
||||||
|
exitX = b2.x - (b1.x + b1.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
float entryY, exitY;
|
||||||
|
if (v1.y > 0) {
|
||||||
|
entryY = b2.y - (b1.y + b1.height);
|
||||||
|
exitY = (b2.y + b2.height) - b1.y;
|
||||||
|
} else {
|
||||||
|
entryY = (b2.y + b2.height) - b1.y;
|
||||||
|
exitY = b2.y - (b1.y + b1.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
float entryXTime, exitXTime;
|
||||||
|
if (v1.x == 0) {
|
||||||
|
entryXTime = -INFINITY;
|
||||||
|
exitXTime = INFINITY;
|
||||||
|
} else {
|
||||||
|
entryXTime = entryX / v1.x;
|
||||||
|
exitXTime = exitX / v1.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float entryYTime, exitYTime;
|
||||||
|
if (v1.y == 0) {
|
||||||
|
entryYTime = -INFINITY;
|
||||||
|
exitYTime = INFINITY;
|
||||||
|
} else {
|
||||||
|
entryYTime = entryY / v1.y;
|
||||||
|
exitYTime = exitY / v1.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
float entryTime = MAX(entryXTime, entryYTime);
|
||||||
|
float exitTime = MIN(exitXTime, exitYTime);
|
||||||
|
|
||||||
|
if (entryTime > exitTime || (entryXTime < 0 && entryYTime < 0) || entryXTime > 1.0f || entryYTime > 1.0f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(0 <= entryTime && entryTime <= 1);
|
||||||
|
|
||||||
|
*result = (struct CollisionResult){
|
||||||
|
.time = entryTime,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (entryXTime > entryYTime) {
|
||||||
|
result->normal.x = entryX < 0.0 ? 1 : -1;
|
||||||
|
} else {
|
||||||
|
result->normal.y = entryY < 0.0 ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Rectangle rect_add_position(Rectangle rect, Vector2 pos)
|
||||||
|
{
|
||||||
|
rect.x += pos.x;
|
||||||
|
rect.y += pos.y;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Rectangle rect_get_step_bounds(Rectangle rect, Vector2 step)
|
||||||
|
{
|
||||||
|
if (step.x >= 0) {
|
||||||
|
rect.width += step.x;
|
||||||
|
} else {
|
||||||
|
rect.x += step.x;
|
||||||
|
rect.width -= step.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (step.y >= 0) {
|
||||||
|
rect.height += step.y;
|
||||||
|
} else {
|
||||||
|
rect.y += step.y;
|
||||||
|
rect.height -= step.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector2 rect_get_center(Rectangle rect)
|
||||||
|
{
|
||||||
|
return (Vector2){
|
||||||
|
.x = rect.x + rect.width / 2,
|
||||||
|
.y = rect.y + rect.height / 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void game_list_nearest_walls(struct Game *game, struct EntityIdList *walls, Rectangle bounds, struct EntityIdList *result)
|
||||||
|
{
|
||||||
|
struct FloatList distances = { 0 };
|
||||||
|
entity_id_list_clear_retaining_capacity(result);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < walls->len; i++) {
|
||||||
|
EntityId wall_id = walls->items[i];
|
||||||
|
struct Entity *wall = entity_list_get(&game->entities, wall_id);
|
||||||
|
ASSERT(wall != NULL);
|
||||||
|
|
||||||
|
Rectangle wall_collider = rect_add_position(wall->collision_rect, wall->position);
|
||||||
|
if (game_aabb(wall_collider, bounds)) {
|
||||||
|
float distance_sqr = Vector2DistanceSqr(
|
||||||
|
rect_get_center(wall_collider),
|
||||||
|
rect_get_center(bounds)
|
||||||
|
);
|
||||||
|
entity_id_list_add(result, wall_id);
|
||||||
|
float_list_add(&distances, distance_sqr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)result->len - 1; i++) {
|
||||||
|
for (int j = i + 1; j < (int)result->len; j++) {
|
||||||
|
if (distances.items[i] < distances.items[j]) {
|
||||||
|
{
|
||||||
|
float tmp = distances.items[i];
|
||||||
|
distances.items[i] = distances.items[j];
|
||||||
|
distances.items[j] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EntityId tmp = result->items[i];
|
||||||
|
result->items[i] = result->items[j];
|
||||||
|
result->items[j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float_list_free(&distances);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void game_collision_response_slide(Vector2 *step, struct CollisionResult collision)
|
||||||
|
{
|
||||||
|
Vector2 new_step = Vector2Scale(*step, collision.time);
|
||||||
|
|
||||||
|
float remaining_time = 1 - collision.time;
|
||||||
|
float dotprod = (step->x * collision.normal.y + step->y * collision.normal.x) * remaining_time;
|
||||||
|
new_step.x += dotprod * collision.normal.y;
|
||||||
|
new_step.y += dotprod * collision.normal.x;
|
||||||
|
|
||||||
|
*step = new_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void game_collide_against_walls(struct Game *game, struct EntityIdList *walls, Rectangle collider, Vector2 *step)
|
||||||
|
{
|
||||||
|
TracyCZoneN(game_collide_against_walls, "game_collide_against_walls", true);
|
||||||
|
|
||||||
|
struct EntityIdList nearest_walls = { 0 };
|
||||||
|
game_list_nearest_walls(
|
||||||
|
game,
|
||||||
|
walls,
|
||||||
|
rect_get_step_bounds(
|
||||||
|
collider,
|
||||||
|
*step
|
||||||
|
),
|
||||||
|
&nearest_walls
|
||||||
|
);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nearest_walls.len; i++) {
|
||||||
|
struct Entity *wall = entity_list_get(&game->entities, nearest_walls.items[i]);
|
||||||
|
ASSERT(wall != NULL);
|
||||||
|
|
||||||
|
Rectangle wall_collider = rect_add_position(wall->collision_rect, wall->position);
|
||||||
|
|
||||||
|
struct CollisionResult collision = { 0 };
|
||||||
|
if (!game_swept_aabb(collider, *step, wall_collider, &collision)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
game_collision_response_slide(step, collision);
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_id_list_free(&nearest_walls);
|
||||||
|
|
||||||
|
TracyCZoneEnd(game_collide_against_walls)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int signf(float value) {
|
||||||
|
if (value > 0) {
|
||||||
|
return 1;
|
||||||
|
} else if (value < 0) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_tick(struct Game *game)
|
void game_tick(struct Game *game)
|
||||||
@ -28,10 +330,109 @@ void game_tick(struct Game *game)
|
|||||||
if (IsKeyDown(KEY_A)) {
|
if (IsKeyDown(KEY_A)) {
|
||||||
dir.x -= 1;
|
dir.x -= 1;
|
||||||
}
|
}
|
||||||
|
dir = Vector2Normalize(dir);
|
||||||
|
|
||||||
game->player_position = Vector2Add(game->player_position, Vector2Scale(dir, 50 * game->input.dt));
|
float dt = game->input.dt;
|
||||||
|
|
||||||
DrawRectangleV(game->player_position, (Vector2){ 50, 50 }, RED);
|
struct Entity *entity = NULL;
|
||||||
|
entity_list_foreach(&game->entities, entity) {
|
||||||
|
if (entity->type == ENTITY_TYPE_PLAYER) {
|
||||||
|
entity->velocity = Vector2Scale(dir, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
entity->velocity = Vector2Add(entity->velocity, Vector2Scale(entity->accelaration, dt));
|
||||||
|
if (entity->flags.has_max_speed) {
|
||||||
|
entity->velocity = Vector2ClampValue(entity->velocity, 0, entity->max_speed);
|
||||||
|
}
|
||||||
|
if (entity->flags.has_friction) {
|
||||||
|
float friction_force = pow(1 - entity->friction, dt);
|
||||||
|
entity->velocity = Vector2Scale(entity->velocity, friction_force);
|
||||||
|
}
|
||||||
|
entity->step = Vector2Scale(entity->velocity, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EntityIdList walls = { 0 };
|
||||||
|
struct EntityIdList players = { 0 };
|
||||||
|
|
||||||
|
entity_list_foreach(&game->entities, entity) {
|
||||||
|
EntityId entity_id = entity_list_get_id(&game->entities, entity);
|
||||||
|
if (entity->type == ENTITY_TYPE_WALL) {
|
||||||
|
entity_id_list_add(&walls, entity_id);
|
||||||
|
} else if (entity->type == ENTITY_TYPE_PLAYER) {
|
||||||
|
entity_id_list_add(&players, entity_id);
|
||||||
|
} else {
|
||||||
|
entity->position = Vector2Add(entity->position, entity->step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < walls.len; i++) {
|
||||||
|
struct Entity *wall = entity_list_get(&game->entities, walls.items[i]);
|
||||||
|
ASSERT(wall != NULL);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < players.len; i++) {
|
||||||
|
struct Entity *player = entity_list_get(&game->entities, players.items[i]);
|
||||||
|
ASSERT(player != NULL);
|
||||||
|
|
||||||
|
Rectangle wall_collider = rect_add_position(wall->collision_rect, wall->position);
|
||||||
|
Rectangle player_collider = rect_add_position(player->collision_rect, player->position);
|
||||||
|
|
||||||
|
if (!game_aabb(player_collider, rect_get_step_bounds(wall_collider, wall->step))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CollisionResult collision = { 0 };
|
||||||
|
if (game_swept_aabb(wall_collider, wall->step, player_collider, &collision)) {
|
||||||
|
if (collision.normal.x != 0 && signf(collision.normal.x) == signf(player->step.x)) {
|
||||||
|
player->step.x = 0;
|
||||||
|
}
|
||||||
|
if (collision.normal.y != 0 && signf(collision.normal.y) == signf(player->step.y)) {
|
||||||
|
player->step.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
player->step.x += wall->step.x * (1 - collision.time);
|
||||||
|
player->step.y += wall->step.y * (1 - collision.time);
|
||||||
|
|
||||||
|
player->step.x -= collision.normal.x * 0.001;
|
||||||
|
player->step.y -= collision.normal.y * 0.001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wall->position = Vector2Add(wall->position, wall->step);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < players.len; i++) {
|
||||||
|
struct Entity *player = entity_list_get(&game->entities, players.items[i]);
|
||||||
|
ASSERT(player != NULL);
|
||||||
|
|
||||||
|
game_collide_against_walls(
|
||||||
|
game,
|
||||||
|
&walls,
|
||||||
|
rect_add_position(player->collision_rect, player->position),
|
||||||
|
&player->step
|
||||||
|
);
|
||||||
|
|
||||||
|
player->position = Vector2Add(player->position, player->step);
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_list_foreach(&game->entities, entity) {
|
||||||
|
if (entity->type == ENTITY_TYPE_PLAYER) {
|
||||||
|
Vector2 size = (Vector2){ 20, 20 };
|
||||||
|
DrawRectangleV(Vector2Subtract(entity->position, Vector2Scale(size, 0.5)), size, RED);
|
||||||
|
DrawCircleV(entity->position, 4, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity->type == ENTITY_TYPE_WALL || entity->type == ENTITY_TYPE_PLAYER) {
|
||||||
|
Rectangle rect = entity->collision_rect;
|
||||||
|
rect.x += entity->position.x;
|
||||||
|
rect.y += entity->position.y;
|
||||||
|
Color color = BLUE;
|
||||||
|
DrawRectangleRec(rect, ColorAlpha(color, 0.5));
|
||||||
|
DrawRectangleLinesEx(rect, 2, ColorAlpha(color, 0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_id_list_free(&walls);
|
||||||
|
entity_id_list_free(&players);
|
||||||
|
|
||||||
TracyCZoneEnd(game_tick)
|
TracyCZoneEnd(game_tick)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,11 +12,10 @@ struct Game {
|
|||||||
Vector2 canvas_size;
|
Vector2 canvas_size;
|
||||||
struct EntityList entities;
|
struct EntityList entities;
|
||||||
|
|
||||||
Vector2 player_position;
|
|
||||||
|
|
||||||
struct Input input;
|
struct Input input;
|
||||||
};
|
};
|
||||||
|
|
||||||
void game_init(struct Game *game);
|
void game_init(struct Game *game);
|
||||||
void game_free(struct Game *game);
|
void game_free(struct Game *game);
|
||||||
void game_tick(struct Game *game);
|
void game_tick(struct Game *game);
|
||||||
|
EntityId game_add_wall(struct Game *game, Rectangle rect);
|
||||||
|
|||||||
38
src/generic_vector.h
Normal file
38
src/generic_vector.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#define DEFINE_VECTOR_STRUCT(vector_name, item_t) \
|
||||||
|
struct vector_name { \
|
||||||
|
item_t *items; \
|
||||||
|
size_t len; \
|
||||||
|
size_t capacity; \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFINE_VECTOR_ENSURE_METHOD_CAPACITY(func_name, list_t, item_t) \
|
||||||
|
void func_name(list_t *list, size_t expected_capacity) \
|
||||||
|
{ \
|
||||||
|
if (list->capacity < expected_capacity) { \
|
||||||
|
size_t larger_capacity = MAX(MAX(list->capacity*2, expected_capacity), 4); \
|
||||||
|
item_t *larger_items = realloc(list->items, larger_capacity * sizeof(item_t)); \
|
||||||
|
if (larger_items == NULL) { \
|
||||||
|
PANIC_OOM(); \
|
||||||
|
} \
|
||||||
|
list->items = larger_items; \
|
||||||
|
list->capacity = larger_capacity; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_VECTOR_METHOD_FREE(func_name, list_t) \
|
||||||
|
void func_name(list_t *list) \
|
||||||
|
{ \
|
||||||
|
free(list->items); \
|
||||||
|
list->len = 0; \
|
||||||
|
list->capacity = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_VECTOR_METHOD_CLEAR_RETAINING_CAPACITY(func_name, list_t) \
|
||||||
|
void func_name(list_t *list) \
|
||||||
|
{ \
|
||||||
|
list->len = 0; \
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user