diff options
| author | nathan <nathansmith@disroot.org> | 2026-01-05 09:30:25 +0000 |
|---|---|---|
| committer | nathan <nathansmith@disroot.org> | 2026-01-05 09:30:25 +0000 |
| commit | a8d803916883e49790981beed6438726406e0995 (patch) | |
| tree | cc354d1231c94dbfdb67268f57a3819e03949dce | |
| parent | e507ecbb95a2c7a1ffb8c13f1bd39433d6c49ba3 (diff) | |
| download | FindThings-a8d803916883e49790981beed6438726406e0995.tar.gz FindThings-a8d803916883e49790981beed6438726406e0995.tar.bz2 FindThings-a8d803916883e49790981beed6438726406e0995.zip | |
Collision with buildings working
| -rw-r--r-- | src/entity.c | 29 | ||||
| -rw-r--r-- | src/entity.h | 3 | ||||
| -rw-r--r-- | src/player.c | 95 | ||||
| -rw-r--r-- | src/player.h | 2 |
4 files changed, 116 insertions, 13 deletions
diff --git a/src/entity.c b/src/entity.c index 4895d9e..f094f8d 100644 --- a/src/entity.c +++ b/src/entity.c @@ -326,10 +326,10 @@ BoundingBox entityBoxFromScale(float scale, float width, float height) EntityBuilding* createEntityBuilding(Image heightmap) { - EntityBuilding* entityBuilding = + EntityBuilding* building = (EntityBuilding*)FT_MALLOC(sizeof(EntityBuilding)); - if (entityBuilding == NULL) + if (building == NULL) { ALLOCATION_ERROR; return NULL; @@ -338,7 +338,7 @@ EntityBuilding* createEntityBuilding(Image heightmap) float widthInWorld = heightmap.width * ENTITY_BUILDING_CUBE_SIZE.x; float heightInWorld = heightmap.height * ENTITY_BUILDING_CUBE_SIZE.z; - *entityBuilding = (EntityBuilding){ + *building = (EntityBuilding){ .model = LoadModelFromMesh(GenMeshCubicmap(heightmap, ENTITY_BUILDING_CUBE_SIZE)), .pixelMap = LoadImageColors(heightmap), @@ -354,19 +354,30 @@ EntityBuilding* createEntityBuilding(Image heightmap) } }; - return entityBuilding; + return building; } -void freeEntityBuilding(EntityBuilding* entityBuilding) +void freeEntityBuilding(EntityBuilding* building) { - if (entityBuilding != NULL) + if (building != NULL) { - UnloadModel(entityBuilding->model); - UnloadImageColors(entityBuilding->pixelMap); - FT_FREE(entityBuilding); + UnloadModel(building->model); + UnloadImageColors(building->pixelMap); + FT_FREE(building); } } +bool isBuildingBlockWall(const EntityBuilding* building, int x, int y) +{ + if (x < 0 || x >= building->width || + y < 0 || y >= building->height) + { + return false; + } + + return building->pixelMap[y * building->width + x].r == 255; +} + void drawBuildingRoof(const EntityBuilding* building, Vector3 position, Color color) { diff --git a/src/entity.h b/src/entity.h index e92fbb2..8cfcad6 100644 --- a/src/entity.h +++ b/src/entity.h @@ -119,7 +119,8 @@ int getInteractionMenuIndex(Selection selection); BoundingBox entityBoxFromScale(float scale, float width, float height); EntityBuilding* createEntityBuilding(Image heightmap); -void freeEntityBuilding(EntityBuilding* entityBuilding); +void freeEntityBuilding(EntityBuilding* building); +bool isBuildingBlockWall(const EntityBuilding* building, int x, int y); void drawBuildingRoof(const EntityBuilding* building, Vector3 position, Color color); diff --git a/src/player.c b/src/player.c index 11bc307..7917545 100644 --- a/src/player.c +++ b/src/player.c @@ -7,6 +7,7 @@ Player createPlayer() .position = Vector3Zero(), .direction = (Vector3){0.0, 0.0, 0.0}, .velocity = Vector3Zero(), + .speed = 0.0, .relativeBox = (BoundingBox){ .min = (Vector3){-PLAYER_WIDTH / 2.0, -PLAYER_HEIGHT / 2.0, -PLAYER_WIDTH / 2.0}, @@ -71,6 +72,72 @@ WorldUID playerCheckCollisionWithBuildings(Player* player, Game* game) return ENTITY_NONE; } +// Returns true if collision detection should end. +bool playerHandleCollisionWithBuildingBlock(Player* player, + EntityBuilding* building, + BoundingBox block, + Vector3 blockPosition, + int x, + int y, + bool* isFirstCollision, + Vector3* lastNormal) +{ + int normalsCount = 4; + + Vector3 normals[] = { + (Vector3){1.0, 0.0, 0.0}, + (Vector3){-1.0, 0.0, 0.0}, + (Vector3){0.0, 0.0, 1.0}, + (Vector3){0.0, 0.0, -1.0} + }; + + int closestNormalIndex = 0; + float closestDistance = WORLD_SIZE.x; + + // Get closest normal. + for (int index = 0; index < normalsCount; ++index) + { + float distance = Vector3Distance( + player->position, + Vector3Add(normals[index], blockPosition)); + + // Avoid issues with neighboring blocks. + bool isNormalBlocked = isBuildingBlockWall(building, + x + normals[index].x, + y + normals[index].z); + + if (!isNormalBlocked && distance < closestDistance) + { + closestDistance = distance; + closestNormalIndex = index; + } + } + + Vector3 normal = normals[closestNormalIndex]; + + // Is facing wall. + if (Vector3DotProduct(player->velocity, normal) < 0.0) + { + // Handle collision. + float dotProduct = Vector3DotProduct(player->direction, normal); + player->velocity = Vector3Subtract(player->direction, + Vector3Scale(normal, dotProduct)); + player->velocity = Vector3Scale(player->velocity, player->speed); + + // Is at a corner. + if (!*isFirstCollision && !Vector3Equals(*lastNormal, normal)) + { + player->velocity = (Vector3){0.0, 0.0, 0.0}; + return true; + } + + *isFirstCollision = false; + *lastNormal = normal; + } + + return false; +} + // TODO: Make this fucker speedy quick void playerHandleCollisionWithBuilding(Player* player, Game* game, WorldUID uid) @@ -87,6 +154,9 @@ void playerHandleCollisionWithBuilding(Player* player, Game* game, ENTITY_BUILDING_CUBE_SIZE.z / 2.0} }; + bool isFirstCollision = true; + Vector3 lastNormal = (Vector3){0.0, 0.0, 0.0}; + for (int y = 0; y < building->height; ++y) { for (int x = 0; x < building->width; ++x) @@ -105,8 +175,20 @@ void playerHandleCollisionWithBuilding(Player* player, Game* game, }; BoundingBox box = wallBox; - box.min = Vector3Add(box.min, place->position); - box.max = Vector3Add(box.max, place->position); + box.min = Vector3Add(box.min, wallPosition); + box.max = Vector3Add(box.max, wallPosition); + + if (CheckCollisionBoxes(player->box, box)) + { + DrawBoundingBox(box, PURPLE); + if (playerHandleCollisionWithBuildingBlock(player, building, box, + wallPosition, x, y, + &isFirstCollision, + &lastNormal)) + { + return; + } + } } } } @@ -147,8 +229,15 @@ void updatePlayerMovement(Player* player, Game* game) } player->velocity = Vector3Scale(player->velocity, PLAYER_SPEED); + player->speed = Vector3Length(player->velocity); - printf("%d\n", playerCheckCollisionWithBuildings(player, game)); + // Check collision with buildings. + WorldUID buildingUID = playerCheckCollisionWithBuildings(player, game); + + if (buildingUID != ENTITY_NONE) + { + playerHandleCollisionWithBuilding(player, game, buildingUID); + } // Apply velocity. player->position = Vector3Add( diff --git a/src/player.h b/src/player.h index 7755ef9..3dac500 100644 --- a/src/player.h +++ b/src/player.h @@ -12,7 +12,9 @@ typedef struct { Vector3 position; Vector3 direction; + Vector3 velocity; + float speed; BoundingBox relativeBox; BoundingBox box; |
