diff options
author | nathan <nathansmith@disroot.org> | 2025-07-06 21:38:08 +0000 |
---|---|---|
committer | nathan <nathansmith@disroot.org> | 2025-07-06 21:38:08 +0000 |
commit | 811d5bf064ce992bc742f55c112a777801126861 (patch) | |
tree | 5842fa0f76b2b0dbd4a04ac7a237b4d5753fdd1d | |
parent | 1abde5cdf85269597b180d5e88e9d62798fc893c (diff) | |
download | FindThings-811d5bf064ce992bc742f55c112a777801126861.tar.gz FindThings-811d5bf064ce992bc742f55c112a777801126861.tar.bz2 FindThings-811d5bf064ce992bc742f55c112a777801126861.zip |
Finally smooth walking
-rw-r--r-- | src/player.c | 15 | ||||
-rw-r--r-- | src/utils.h | 1 | ||||
-rw-r--r-- | src/world.c | 75 | ||||
-rw-r--r-- | src/world.h | 1 |
4 files changed, 68 insertions, 24 deletions
diff --git a/src/player.c b/src/player.c index 0342040..9c66627 100644 --- a/src/player.c +++ b/src/player.c @@ -18,6 +18,14 @@ Player createPlayer() }; } +// Fake physics, distance from ground. +void updatePlayerHeight(Player* player, Game* game) +{ + float height = getWorldHeightAtLocation( + game->world, player->position.x, player->position.z) + PLAYER_HEIGHT; + player->position.y = height; +} + // TODO: move magic numbers to settings void updatePlayer(Player* player, Game* game) { @@ -65,14 +73,13 @@ void updatePlayer(Player* player, Game* game) player->velocity = Vector3Scale(player->velocity, 10.0); - // Apply velocity + // Apply velocity. player->position = Vector3Add( player->position, Vector3Scale(player->velocity, GetFrameTime())); + + updatePlayerHeight(player, game); // Apply camera. camera->position = player->position; camera->target = Vector3Add(player->position, player->direction); - - player->position.y = getWorldHeightAtLocation( - game->world, player->position.x, player->position.z) + PLAYER_HEIGHT; } diff --git a/src/utils.h b/src/utils.h index c165e2c..e4cefee 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,6 +2,7 @@ #include <stdlib.h> #include <stdint.h> #include <math.h> +#include <float.h> #include <raylib.h> #include <raymath.h> diff --git a/src/world.c b/src/world.c index 1fdb1ce..b444ff1 100644 --- a/src/world.c +++ b/src/world.c @@ -7,7 +7,7 @@ World createWorld(const Assets* assets) world.size = (Vector3){1000.0, 100.0, 1000.0}; // Heightmap image. - Image image = GenImagePerlinNoise(1024, 1024, 0, 0, 2.0); + Image image = GenImagePerlinNoise(100, 100, 0, 0, 5.0); // Heightmap. Mesh mesh = GenMeshHeightmap(image, world.size); @@ -27,7 +27,6 @@ World createWorld(const Assets* assets) Entity entity = createEntity(seed % ENTITY_COUNT, Vector3Zero()); FT_RANDOM16(seed); - // It be funky and give negative numbers. entity.position.x = seed % (int)world.size.x; FT_RANDOM16(seed); entity.position.z = seed % (int)world.size.z; @@ -55,29 +54,67 @@ void freeWorld(World world) UnloadModel(world.heightmap); } -float getWorldPixelHeight(World world, int x, int y) +float getWorldHeightAtLocation(World world, float x, float y) { - int verticeStart = (y * (world.texture.width - 1) + x) * 18; - float height = 0.0; - int count = 0; + float toMapX = (float)world.texture.width / world.size.x; + float toMapY = (float)world.texture.height / world.size.z; + int pixelX = x * toMapX; + int pixelY = y * toMapY; + + int verticeStart = (pixelY * (world.texture.width - 1) + pixelX) * 18; + float* vertices = &world.heightmap.meshes[0].vertices[verticeStart]; + + // Clamp x and y to prevent ray being out of bounds. + Vector2 min = (Vector2){vertices[0], vertices[2]}; + Vector2 max = (Vector2){vertices[0], vertices[2]}; - for (int index = 1; index < 18; index += 3) + for (int index = 0; index < 18; index += 3) { - height += world.heightmap.meshes[0].vertices[verticeStart + index]; - ++count; + Vector2 vertex = (Vector2){vertices[index], vertices[index + 2]}; + min = Vector2Min(min, vertex); + max = Vector2Max(max, vertex); } - return (float)height / count; -} - -float getWorldHeightAtLocation(World world, float x, float y) -{ - float toMapX = (float)world.texture.width / world.size.x; - float toMapY = (float)world.texture.height / world.size.z; - int pixelX = roundf((float)x * toMapX); - int pixelY = roundf((float)y * toMapY); + // Cast to triangles at pixel. Really hacky indeed. + Ray ray = (Ray){ + .position = (Vector3){ + Clamp(x, min.x, max.x), + FLT_MAX_EXP, + Clamp(y, min.y, max.y)}, + .direction = (Vector3){0.0, -1.0, 0.0} + }; + + RayCollision result = GetRayCollisionTriangle( + ray, + (Vector3){vertices[0], vertices[1], vertices[2]}, + (Vector3){vertices[3], vertices[4], vertices[5]}, + (Vector3){vertices[6], vertices[7], vertices[8]}); + + // Test other triangle. + if (!result.hit) + { + result = GetRayCollisionTriangle( + ray, + (Vector3){vertices[9], vertices[10], vertices[11]}, + (Vector3){vertices[12], vertices[13], vertices[14]}, + (Vector3){vertices[15], vertices[16], vertices[17]}); + } - return getWorldPixelHeight(world, pixelX, pixelY); + if (result.hit) + { + return result.point.y; + } + else // Fall back. + { + float height = 0.0; + + for (int index = 1; index < 18; index += 3) + { + height += vertices[index]; + } + + return height / 6.0; + } } // Abortions are good. Get more abortions. diff --git a/src/world.h b/src/world.h index 980f315..e06d628 100644 --- a/src/world.h +++ b/src/world.h @@ -35,7 +35,6 @@ void updateWorld(World* world, Game* game); void freeWorld(World world); // Dam, I wanta live in a free world ): -float getWorldPixelHeight(World world, int x, int y); float getWorldHeightAtLocation(World world, float x, float y); #endif |