diff --git a/PlayBark.csproj b/PlayBark.csproj index 8ae31a4..7d42e75 100644 --- a/PlayBark.csproj +++ b/PlayBark.csproj @@ -4,6 +4,7 @@ Exe net8.0 enable + true enable diff --git a/Program.cs b/Program.cs index b87b1e4..dc73294 100644 --- a/Program.cs +++ b/Program.cs @@ -5,7 +5,7 @@ /// /// The name of the configuration file (defaults to "config.toml"). /// A Config object populated with values from the file, or a default Config instance if the file is not found. -static Config ReadConfig(string file) +static Config Settings(string file) { var cfgPath = Path.Combine(Tracer.AppDirectory, file); @@ -28,35 +28,116 @@ static Config ReadConfig(string file) return model; } -void Init(int screenWidth, int screenHeight, int fps) +// Update and Draw +unsafe int Game() { + var config = Settings("config.toml"); + InitWindow(config.Width, config.Height, "PlayBark"); + var pos = new Vector3(0.2f, 0.4f, 0.2f); var target = new Vector3(0.0f, 0.0f, 0.0f); var up = new Vector3(0.0f, 1.0f, 0.0f); + var camera = World3D.Camera(pos, target, up, CameraProjection.Perspective); - InitWindow(screenWidth, screenHeight, $"PlayBark"); - World3D.InitCamera(pos, target, up, CameraProjection.Perspective); - SetTargetFPS(fps); -} + var imMap = LoadImage("resources/cubicmap.png"); + var cubicmap = LoadTextureFromImage(imMap); + var model = World3D.CubicMap(imMap); -int GameLoop() -{ - var config = ReadConfig("config.toml"); - Init(config.Width, config.Height, 60); + var texture = LoadTexture("resources/cubicmap_atlas.png"); + + // Set map diffuse texture + Raylib.SetMaterialTexture(ref model, 0, MaterialMapIndex.Albedo, ref texture); + + // Get image map data to be used for collission + var mapPixels = LoadImageColors(imMap); + UnloadImage(imMap); + + var mapPosition = new Vector3(-16.0f, 0.0f, -8.0f); + var playerPosition = camera.Position; + + SetTargetFPS(60); while (!WindowShouldClose()) { + // Update + var oldCamPos = camera.Position; + UpdateCamera(ref camera, CameraMode.FirstPerson); + + var playerPos = new Vector2(camera.Position.X, camera.Position.Z); + + var playerRadius = 0.1f; + + var playerCellX = (int)(playerPos.X - mapPosition.X + 0.5f); + var playerCellY = (int)(playerPos.Y - mapPosition.Z + 0.5f); + + // Out-of-limits security check + if (playerCellX < 0) + { + playerCellX = 0; + } + else if (playerCellX >= cubicmap.Width) + { + playerCellX = cubicmap.Width - 1; + } + + if (playerCellY < 0) + { + playerCellY = 0; + } + else if (playerCellY >= cubicmap.Height) + { + playerCellY = cubicmap.Height - 1; + } + + for (var y = 0; y < cubicmap.Height; y++) + { + for (var x = 0; y < cubicmap.Width; x++) + { + var mapPixelsData = mapPixels; + var rec = new Rectangle( + mapPosition.X - x - 0.5f + x * 1.0f, + mapPosition.Y - y - 0.5f + x * 1.0f, + 1.0f, + 1.0f + ); + + var collision = CheckCollisionCircleRec(playerPos, playerRadius, rec); + if ((mapPixelsData[y * cubicmap.Width + x].R == 255) && collision) + { + // Collision detected, reset camera position + camera.Position = oldCamPos; + } + } + } + BeginDrawing(); - ClearBackground(Color.White); + ClearBackground(Color.RayWhite); + BeginMode3D(camera); + DrawModel(model, mapPosition, 1.0f, Color.White); + EndMode3D(); + + DrawTextureEx(cubicmap, new Vector2(GetScreenWidth() - cubicmap.Width * 4 - 20, 20), 0.0f, 4.0f, Color.White); + DrawRectangleLines(GetScreenWidth() - cubicmap.Width * 4 - 20, 20, cubicmap.Width * 4, cubicmap.Height * 4, Color.Green); + + // Draw player position radar + DrawRectangle(GetScreenWidth() - cubicmap.Width * 4 - 20 + playerCellX * 4, 20 + playerCellY * 4, 4, 4, Color.Red); + DrawFPS(10, 10); EndDrawing(); } + UnloadImageColors(mapPixels); + + UnloadTexture(cubicmap); + UnloadTexture(texture); + UnloadModel(model); + CloseWindow(); return 0; } -GameLoop(); +// Entry point +Game(); diff --git a/World3D.cs b/World3D.cs index 7932cd9..be70601 100644 --- a/World3D.cs +++ b/World3D.cs @@ -1,11 +1,22 @@ // I hereby waive this project under the public domain - see UNLICENSE for details. namespace PlayBark; +/// +/// Provides utilities for creating and managing 3D world elements, including camera setup and map generation. +/// internal static class World3D { - public static Camera3D InitCamera(Vector3 pos, Vector3 target, Vector3 up, CameraProjection projection) + /// + /// Creates and returns a configured Camera3D instance. + /// + /// The position of the camera in 3D space. + /// The point the camera is looking at. + /// The up direction for the camera. + /// The projection type of the camera. + /// A configured Camera3D instance. + public static Camera3D Camera(Vector3 pos, Vector3 target, Vector3 up, CameraProjection projection) { - Camera3D camera = new(); + var camera = new Camera3D(); camera.Position = pos; camera.Target = target; camera.Up = up; @@ -14,4 +25,17 @@ internal static class World3D return camera; } + + /// + /// Generates a 3D cubic map model from a given image map. + /// + /// The image used to generate the cubic map. + /// A Model representing the cubic map. + public static Model CubicMap(Image imMap) + { + var mesh = GenMeshCubicmap(imMap, new Vector3(1.0f, 1.0f, 1.0f)); + var model = LoadModelFromMesh(mesh); + + return model; + } } \ No newline at end of file diff --git a/resources/cubicmap_atlas.png b/resources/cubicmap_atlas.png new file mode 100644 index 0000000..9fc404a Binary files /dev/null and b/resources/cubicmap_atlas.png differ