From 47264c3da3c9d186b167c976dbcd4e08e219e756 Mon Sep 17 00:00:00 2001 From: Sara Date: Sun, 8 Oct 2023 23:10:37 +0200 Subject: [PATCH] added tilemap collision --- src/physics_world.c | 94 +++++++++++++++++++++++++++++++++++++++++++-- src/physics_world.h | 4 ++ 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/physics_world.c b/src/physics_world.c index 0000963..66a6d4f 100644 --- a/src/physics_world.c +++ b/src/physics_world.c @@ -1,23 +1,37 @@ #include "physics_world.h" #include "debug.h" #include "collision.h" +#include "tilemap.h" static PhysicsEntity* _world_bodies = NULL; static size_t _world_bodies_cap = 0; static size_t _world_bodies_len = 0; +static Tilemap** _world_maps = NULL; +static size_t _world_maps_cap = 0; +static size_t _world_maps_len = 0; + void physics_world_init() { _world_bodies = malloc(8 * sizeof(PhysicsEntity)); - _world_bodies_cap = 0; + _world_bodies_cap = 8; + _world_bodies_len = 0; + + _world_maps = malloc(4 * (sizeof(Tilemap*))); + _world_maps_cap = 4; + _world_maps_len = 0; } void physics_world_clean() { free(_world_bodies); _world_bodies_cap = 0; - _world_bodies_cap = 0; + _world_bodies_len = 0; + + free(_world_maps); + _world_maps_cap = 0; + _world_maps_len = 0; } -void _physics_world_resize(size_t minimum) { +void _internal_physics_world_resize_entities(size_t minimum) { if(minimum < _world_bodies_cap) { return; } @@ -35,7 +49,7 @@ void _physics_world_resize(size_t minimum) { } void physics_world_add_entity(PhysicsEntity entity) { - _physics_world_resize(_world_bodies_len + 1); + _internal_physics_world_resize_entities(_world_bodies_len + 1); _world_bodies[_world_bodies_len] = entity; ++_world_bodies_len; @@ -59,6 +73,50 @@ void physics_world_remove_entity(PhysicsEntity entity) { ASSERT_RETURN(0,, "Physics entity with data at %p is not registered in physics world", entity.data); } +static +void _internal_physics_world_resize_maps(size_t minimum) { + if(minimum < _world_maps_cap) { + return; + } + + size_t amount = _world_maps_cap; + while(amount < minimum) { + amount *= 2; + } + + Tilemap** new = realloc(_world_maps, amount * sizeof(Tilemap*)); + ASSERT_RETURN(new != NULL,, "Could not grow physics tilemaps array"); + + _world_maps = new; + _world_maps_cap = amount; +} + +void physics_world_add_map(Tilemap* map) { + _internal_physics_world_resize_maps(_world_maps_len + 1); + + _world_maps[_world_maps_len] = map; + ++_world_maps_len; +} + +static +void _internal_physics_world_remove_map(Tilemap** at) { + Tilemap** from = at + 1; + memmove(at, from, (at - _world_maps + _world_bodies_len) * sizeof(Tilemap*)); + --_world_bodies_len; +} + +void physics_world_remove_map(Tilemap* map) { + Tilemap** end = _world_maps + _world_maps_len; + for(Tilemap** itr = _world_maps; itr < end; ++itr) { + if(*itr == map) { + _internal_physics_world_remove_map(itr); + return; + } + } + + ASSERT_RETURN(0,, "Physics tilemap with data at %p is not registered in physics world and cannot be removed.", map); +} + static void _internal_physics_narrow_collision() { PhysicsEntity* end = _world_bodies + _world_bodies_len; @@ -75,6 +133,33 @@ void _internal_physics_narrow_collision() { } } +static +void _internal_tilemap_entity_collision_check(Tilemap* map, PhysicsEntity entity) { + Collision collision_a; + Collision collision_b; + PhysicsEntity tileentity; + + size_t len = tilemap_get_tile_count(map); + for(size_t i = 0; i < len; ++i) { + tileentity = TileInstance_as_PhysicsEntity(tilemap_get_tile(map, i)); + + if(collision_check(entity, tileentity, &collision_a, &collision_b)) { + entity.tc->on_collision(entity.data, collision_a); + } + } +} + +static +void _internal_physics_tilemap_collision() { + PhysicsEntity* bodies_end = _world_bodies + _world_bodies_len; + Tilemap** maps_end = _world_maps + _world_maps_len; + for(PhysicsEntity* entity = _world_bodies; entity < bodies_end; ++entity) { + for(Tilemap** map = _world_maps; map < maps_end; ++map) { + _internal_tilemap_entity_collision_check(*map, *entity); + } + } +} + static void _internal_physics_move() { PhysicsEntity* end = _world_bodies + _world_bodies_len; @@ -89,5 +174,6 @@ void _internal_physics_move() { void physics_world_tick() { // _internal_physics_broad_collision(); _internal_physics_narrow_collision(); + _internal_physics_tilemap_collision(); _internal_physics_move(); } diff --git a/src/physics_world.h b/src/physics_world.h index 088b251..5aacb7e 100644 --- a/src/physics_world.h +++ b/src/physics_world.h @@ -2,6 +2,7 @@ #define _fencer_physics_world_h #include "physics_entity.h" +#include "tilemap.h" extern void physics_world_init(); extern void physics_world_clean(); @@ -9,6 +10,9 @@ extern void physics_world_clean(); extern void physics_world_add_entity(PhysicsEntity entity); extern void physics_world_remove_entity(PhysicsEntity entity); +extern void physics_world_add_map(Tilemap* map); +extern void physics_world_remove_map(Tilemap* map); + extern void physics_world_tick(); #endif // !_fencer_physics_world_h