From a8d803916883e49790981beed6438726406e0995 Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 5 Jan 2026 02:30:25 -0700 Subject: Collision with buildings working --- src/player.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 3 deletions(-) (limited to 'src/player.c') 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( -- cgit v1.2.3