From 8781cab2aa2c884624cf5aa3ea7afaecc7e1e126 Mon Sep 17 00:00:00 2001 From: Chris Bell Date: Mon, 18 Nov 2024 17:42:48 -0600 Subject: [PATCH] Seperating out components --- Tiles/CameraController.cs | 37 +++++ Tiles/DebugUI.cs | 31 ++++ Tiles/Game.cs | 311 +++++++++----------------------------- Tiles/Player.cs | 102 +++++++++++++ Tiles/TileManager.cs | 67 ++++++++ Tiles/World.cs | 112 ++++++++++++++ 6 files changed, 417 insertions(+), 243 deletions(-) create mode 100644 Tiles/CameraController.cs create mode 100644 Tiles/DebugUI.cs create mode 100644 Tiles/Player.cs create mode 100644 Tiles/TileManager.cs create mode 100644 Tiles/World.cs diff --git a/Tiles/CameraController.cs b/Tiles/CameraController.cs new file mode 100644 index 0000000..15e168e --- /dev/null +++ b/Tiles/CameraController.cs @@ -0,0 +1,37 @@ +using System.Numerics; +using Raylib_cs; + +namespace Tiles; + +public class CameraController +{ + private Camera2D _camera2D; + public Camera2D Camera => _camera2D; + + + public CameraController() + { + _camera2D = new Camera2D(); + } + + public void SetCameraTarget(Vector2 target) + { + _camera2D.Target = target; + } + + public void SetCameraOffset(Vector2 offset) + { + _camera2D.Offset = offset; + } + + public void SetCameraZoom(float zoom) + { + _camera2D.Zoom = zoom; + } + + public void SetCameraRotation(float rotation) + { + _camera2D.Rotation = rotation; + } + +} \ No newline at end of file diff --git a/Tiles/DebugUI.cs b/Tiles/DebugUI.cs new file mode 100644 index 0000000..21e4df8 --- /dev/null +++ b/Tiles/DebugUI.cs @@ -0,0 +1,31 @@ +using Raylib_cs; + +namespace Tiles; + +public class DebugUI +{ + public void Draw() + { + int textSize = 10; + + int textPositionX = (int)(Game.Instance.CameraController.Camera.Target.X - Game.Instance.ScreenWidth / 2 / Game.Instance.CameraController.Camera.Zoom) + 10; + int textPositionY = (int)(Game.Instance.CameraController.Camera.Target.Y - Game.Instance.ScreenHeight / 2 / Game.Instance.CameraController.Camera.Zoom) + 10; + + string lookingAt = ""; + if (Game.Instance.World.GetTile((int)Game.Instance.Player.PointerPosition.X, (int)Game.Instance.Player.PointerPosition.Y) != 0) + { + lookingAt = Game.Instance.TileManager.GetTileFromId(Game.Instance.World.GetTile((int)Game.Instance.Player.PointerPosition.X, (int)Game.Instance.Player.PointerPosition.Y)).Name; + } + else + { + lookingAt = "air"; + } + + Raylib.DrawText("FPS: " + Raylib.GetFPS(), textPositionX, textPositionY, textSize, Color.White); + Raylib.DrawText(Game.Instance.TileManager.GetTileFromId(Game.Instance.Player.CurrentSelectedTileId).Name, textPositionX, textPositionY + (textSize*2), textSize, Color.White); + Raylib.DrawText("Coords: " + Game.Instance.World.GetGridPositionFromGlobalPosition((int)Game.Instance.Player.Position.X, (int)Game.Instance.Player.Position.Y).ToString().ToUpper(), + textPositionX, textPositionY + (textSize * 3), textSize, Color.White); + Raylib.DrawText("Speed: " + Game.Instance.Player.Speed, textPositionX, textPositionY + (textSize*4), textSize, Color.White); + Raylib.DrawText("Pointer: " + Game.Instance.Player.PointerPosition + " " + lookingAt, textPositionX, textPositionY + (textSize*5), textSize, Color.White); + } +} \ No newline at end of file diff --git a/Tiles/Game.cs b/Tiles/Game.cs index 38f00d4..a368e60 100644 --- a/Tiles/Game.cs +++ b/Tiles/Game.cs @@ -5,265 +5,90 @@ namespace Tiles; public class Game { - const int _tileSize = 8; - const int _worldWidth = 2000; - const int _worldHeight = 1000; + public static Game Instance { get; private set; } - private int _screenWidth; - private int _screenHeight; + public TileManager TileManager { get; private set; } + public Player Player { get; private set; } + public CameraController CameraController { get; private set; } + public World World { get; private set; } + public DebugUI DebugUi { get; private set; } - - private Dictionary _tileNameToId = new(); - private Dictionary _tileIdToTile = new(); - private Dictionary<(int x, int y), int> _worldGrid = new(); - - private Vector2 _playerPosition; - private float _playerSpeed = 2f; - private Image _playerImage; - private Texture2D _playerTexture; - - private Vector2 _pointerPosition = Vector2.Zero; - - private Camera2D _camera; - - private int _currentSelectedTileId = 1; - private int _currentSelectedIndex = 0; + public int ScreenWidth { get; private set; } + public int ScreenHeight { get; private set; } public Game(int screenWidth, int screenHeight) { - _screenWidth = screenWidth; - _screenHeight = screenHeight; - Raylib.InitWindow(_screenWidth, _screenHeight, "Tiles"); - Raylib.SetTargetFPS(60); + ScreenWidth = screenWidth; + ScreenHeight = screenHeight; - _playerTexture = Raylib.LoadTexture("data/core/player/dude.png"); - - _playerPosition = GetGlobalPositionFromGrid(500, 500); - - _camera = new Camera2D() - { - Target = _playerPosition, - Offset = new Vector2(_screenWidth / 2, _screenHeight / 2), - Rotation = 0f, - Zoom = 4f - }; - - SetupTiles(); - - GenerateWorld(); + Instance = this; + InitializeRaylib(); + Init(); while (!Raylib.WindowShouldClose()) { - HandleInput(); - _camera.Target = _playerPosition; - - Raylib.BeginDrawing(); - Raylib.ClearBackground(new Color(20, 70, 100, 255)); - Raylib.BeginMode2D(_camera); - - DrawWorld(); - DrawPlayer(); - DrawPointer(); - DrawDebug(); + Draw(); + Update(); + } + } + + private void InitializeRaylib() + { + Raylib.InitWindow(ScreenWidth, ScreenHeight, "Tiles"); + Raylib.SetTargetFPS(60); + } + + private void Init() + { + TileManager = new TileManager(); + + World = new World(); + + Player = new Player("Player") + { + Position = World.GetGlobalPositionFromGrid(500, 500) + }; + + CameraController = new CameraController(); + CameraController.SetCameraTarget(Player.Position); + CameraController.SetCameraOffset(new Vector2(ScreenWidth / 2, ScreenHeight / 2)); + CameraController.SetCameraRotation(0f); + CameraController.SetCameraZoom(4f); + + DebugUi = new DebugUI(); + + World.GenerateWorld(); + } + + private void Update() + { + CameraController.SetCameraTarget(Player.Position); + Player.Update(); + } + + private void Draw() + { + Raylib.BeginDrawing(); + Raylib.ClearBackground(new Color(20, 30, 100, 255)); + Raylib.BeginMode2D(CameraController.Camera); + + World.Draw(); + Player.Draw(); + DebugUi.Draw(); - Raylib.EndMode2D(); - Raylib.EndDrawing(); - } + Raylib.EndMode2D(); + Raylib.EndDrawing(); } - private void HandleInput() - { - if (Raylib.IsKeyDown(KeyboardKey.W)) _playerPosition += new Vector2(0, -1) * _playerSpeed; - if (Raylib.IsKeyDown(KeyboardKey.A)) _playerPosition += new Vector2(-1, 0) * _playerSpeed; - if (Raylib.IsKeyDown(KeyboardKey.S)) _playerPosition += new Vector2(0, 1) * _playerSpeed; - if (Raylib.IsKeyDown(KeyboardKey.D)) _playerPosition += new Vector2(1, 0) * _playerSpeed; - if (Raylib.IsKeyReleased(KeyboardKey.Right)) - { - _currentSelectedIndex = (_currentSelectedIndex + 1) % _tileNameToId.Count; - if (_currentSelectedIndex == 0) - { - _currentSelectedIndex = 1; - } - _currentSelectedTileId = _currentSelectedIndex; - } - else if (Raylib.IsKeyReleased(KeyboardKey.Left)) - { - _currentSelectedIndex = (_currentSelectedIndex - 1 + _tileNameToId.Count) % _tileNameToId.Count; - if (_currentSelectedIndex == 0) - { - _currentSelectedIndex = _tileNameToId.Count - 1; - } - _currentSelectedTileId = _currentSelectedIndex; - } - - - if (Raylib.IsMouseButtonDown(MouseButton.Left)) - { - SetTile((int)_pointerPosition.X, (int)_pointerPosition.Y, _currentSelectedTileId); - } - if (Raylib.IsMouseButtonDown(MouseButton.Right)) - { - SetTile((int)_pointerPosition.X, (int)_pointerPosition.Y, 0); - } - - if (Raylib.IsKeyReleased(KeyboardKey.Up)) _playerSpeed += 1f; - if (Raylib.IsKeyReleased(KeyboardKey.Down)) _playerSpeed -= 1f; - } - - private void SetupTiles() - { - _tileNameToId.Add("air", 0); - - int index = 1; - - foreach (var path in Directory.GetFiles("data/core/tiles/", "*.json")) - { - Tile tile; - - try - { - tile = Tile.GenerateTileFromJson(path); - - if (tile == null) throw new Exception($"Couldn't load tile {path}"); - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } - Console.WriteLine($"Tile {tile.Name} loaded"); - _tileIdToTile.Add(index, tile); - _tileNameToId.Add(tile.Name, index); - index++; - } - } - private void DrawWorld() - { - // Calculate the boundaries of the visible region in grid coordinates - int startX = Math.Max((int)(_camera.Target.X - (_screenWidth / 2 / _camera.Zoom)) / _tileSize, 0); - int startY = Math.Max((int)(_camera.Target.Y - (_screenHeight / 2 / _camera.Zoom)) / _tileSize, 0); - int endX = Math.Min((int)(_camera.Target.X + (_screenWidth / 2 / _camera.Zoom)) / _tileSize, _worldWidth - 1); - int endY = Math.Min((int)(_camera.Target.Y + (_screenHeight / 2 / _camera.Zoom)) / _tileSize, _worldHeight - 1); - - // Loop only through the visible tiles - for (int x = startX; x <= endX; x++) - { - for (int y = startY; y <= endY; y++) - { - (int x, int y) position = new(x, y); - if (_worldGrid.TryGetValue(position, out var tileType) && tileType != 0) - { - Raylib.DrawTexture(_tileIdToTile[tileType].Texture, x * _tileSize, y * _tileSize, Color.White); - } - } - } - } - - - private void DrawPlayer() - { - //Raylib.DrawRectangle((int)_playerPosition.X, (int)_playerPosition.Y, 16, 32, new(0,0,100,255)); - Raylib.DrawTexture(_playerTexture, (int)_playerPosition.X, (int)_playerPosition.Y, Color.White); - } - - private void DrawPointer() - { - Vector2 mousePosition = Raylib.GetMousePosition(); - Vector2 worldPosition = Raylib.GetScreenToWorld2D(mousePosition, _camera); - Vector2 gridPosition = new Vector2((int)(worldPosition.X / _tileSize), (int)(worldPosition.Y / _tileSize)); - _pointerPosition = new Vector2(gridPosition.X, gridPosition.Y); - - Raylib.DrawRectangle((int)_pointerPosition.X*_tileSize, (int)_pointerPosition.Y*_tileSize, _tileSize, _tileSize, new Color(255, 255, 0, 80)); - } - private void DrawDebug() - { - int textSize = 10; - - int textPositionX = (int)(_camera.Target.X - _screenWidth / 2 / _camera.Zoom) + 10; - int textPositionY = (int)(_camera.Target.Y - _screenHeight / 2 / _camera.Zoom) + 10; - - string lookingAt = ""; - if (GetTile((int)_pointerPosition.X, (int)_pointerPosition.Y) != 0) - { - lookingAt = _tileIdToTile[GetTile((int)_pointerPosition.X, (int)_pointerPosition.Y)].Name; - } - else - { - lookingAt = "air"; - } - - Raylib.DrawText("FPS: " + Raylib.GetFPS(), textPositionX, textPositionY, textSize, Color.White); - Raylib.DrawText(_tileIdToTile[_currentSelectedTileId].Name, textPositionX, textPositionY + (textSize*2), textSize, Color.White); - Raylib.DrawText("Coords: " + GetGridPositionFromGlobalPosition((int)_playerPosition.X, (int)_playerPosition.Y).ToString().ToUpper(), - textPositionX, textPositionY + (textSize * 3), textSize, Color.White); - Raylib.DrawText("Speed: " + _playerSpeed, textPositionX, textPositionY + (textSize*4), textSize, Color.White); - Raylib.DrawText("Pointer: " + _pointerPosition + " " + lookingAt, textPositionX, textPositionY + (textSize*5), textSize, Color.White); - } - private void GenerateWorld() - { - int totalHeight = _worldHeight; - int grassHeight = (int)(totalHeight * 0.01); - int dirtHeight = (int)(totalHeight * 0.10); - int airHeight = (int)(totalHeight * 0.50); - int rockHeight = totalHeight - (airHeight + grassHeight + dirtHeight); - - for (int x = 0; x < _worldWidth; x++) - { - for (int y = 0; y < totalHeight; y++) - { - string tileType; - - if (y >= airHeight && y < airHeight + grassHeight) - { - tileType = "grass"; - SetTile(x, y, _tileNameToId[tileType]); - } - else if (y >= airHeight + grassHeight && y < airHeight + grassHeight + dirtHeight) - { - tileType = "dirt"; - SetTile(x, y, _tileNameToId[tileType]); - } - else if (y >= airHeight + grassHeight + dirtHeight) - { - tileType = "rock"; - SetTile(x, y, _tileNameToId[tileType]); - } - } - } - } - - private Vector2 GetGridPositionFromGlobalPosition(int x, int y) - { - int gridX = x / _tileSize; - int gridY = y / _tileSize; - - if (gridX >= 0 && gridX < _worldWidth && gridY >= 0 && gridY < _worldHeight) - { - return new Vector2(gridX, gridY); - } - - return new Vector2(0, 0); - } - - private void SetTile(int x, int y, int id) - { - _worldGrid[(x, y)] = id; - } - - private int GetTile(int x, int y) - { - if (_worldGrid.ContainsKey((x,y))) return _worldGrid[(x,y)]; - return 0; - } - - private Vector2 GetGlobalPositionFromGrid(int x, int y) - { - return new(x * _tileSize, y * _tileSize); - } + + + + + } \ No newline at end of file diff --git a/Tiles/Player.cs b/Tiles/Player.cs new file mode 100644 index 0000000..276e455 --- /dev/null +++ b/Tiles/Player.cs @@ -0,0 +1,102 @@ +using System.Numerics; +using Raylib_cs; + +namespace Tiles; + +public class Player +{ + public int Id { get; private set; } + public string Name { get; private set; } + public Vector2 Position { get; set; } + public float Speed { get; set; } = 2f; + public Texture2D Texture { get; private set; } + + public Vector2 PointerPosition { get; private set; } + + private readonly string _imagePath; + + public int CurrentSelectedTileId = 1; + private int _currentSelectedIndex = 0; + + public Player(string name, int id = 0, string imagePath = "data/core/player/dude.png") + { + Name = name; + Id = id; + _imagePath = imagePath; + + InitTexture(); + } + + public void Update() + { + HandleInput(); + HandleMouse(); + } + + public void Draw() + { + Raylib.DrawTexture(Texture, (int)Position.X, (int)Position.Y, Color.White); + DrawPointer(); + } + + private void InitTexture() + { + Texture = Raylib.LoadTexture(_imagePath); + } + + private void HandleInput() + { + // WASD + if (Raylib.IsKeyDown(KeyboardKey.W)) Position += new Vector2(0, -1) * Speed; + if (Raylib.IsKeyDown(KeyboardKey.A)) Position += new Vector2(-1, 0) * Speed; + if (Raylib.IsKeyDown(KeyboardKey.S)) Position += new Vector2(0, 1) * Speed; + if (Raylib.IsKeyDown(KeyboardKey.D)) Position += new Vector2(1, 0) * Speed; + + // Speed control + if (Raylib.IsKeyReleased(KeyboardKey.Up)) Speed += 1f; + if (Raylib.IsKeyReleased(KeyboardKey.Down)) Speed -= 1f; + + // Select tiles + if (Raylib.IsKeyReleased(KeyboardKey.Right)) + { + _currentSelectedIndex = (_currentSelectedIndex + 1) % Game.Instance.TileManager.TileNameToIdList.Count; + if (_currentSelectedIndex == 0) + { + _currentSelectedIndex = 1; + } + CurrentSelectedTileId = _currentSelectedIndex; + } + else if (Raylib.IsKeyReleased(KeyboardKey.Left)) + { + _currentSelectedIndex = (_currentSelectedIndex - 1 + Game.Instance.TileManager.TileNameToIdList.Count) % Game.Instance.TileManager.TileNameToIdList.Count; + if (_currentSelectedIndex == 0) + { + _currentSelectedIndex = Game.Instance.TileManager.TileNameToIdList.Count - 1; + } + CurrentSelectedTileId = _currentSelectedIndex; + } + } + + private void HandleMouse() + { + //Mouse clicks + if (Raylib.IsMouseButtonDown(MouseButton.Left)) + { + Game.Instance.World.SetTile((int)PointerPosition.X, (int)PointerPosition.Y, CurrentSelectedTileId); + } + if (Raylib.IsMouseButtonDown(MouseButton.Right)) + { + Game.Instance.World.SetTile((int)PointerPosition.X, (int)PointerPosition.Y, 0); + } + } + + private void DrawPointer() + { + Vector2 mousePosition = Raylib.GetMousePosition(); + Vector2 worldPosition = Raylib.GetScreenToWorld2D(mousePosition, Game.Instance.CameraController.Camera); + Vector2 gridPosition = new Vector2((int)(worldPosition.X / Game.Instance.World.TileSize), (int)(worldPosition.Y / Game.Instance.World.TileSize)); + PointerPosition = new Vector2(gridPosition.X, gridPosition.Y); + + Raylib.DrawRectangle((int)PointerPosition.X*Game.Instance.World.TileSize, (int)PointerPosition.Y*Game.Instance.World.TileSize, Game.Instance.World.TileSize, Game.Instance.World.TileSize, new Color(255, 255, 0, 80)); + } +} \ No newline at end of file diff --git a/Tiles/TileManager.cs b/Tiles/TileManager.cs new file mode 100644 index 0000000..8de9f93 --- /dev/null +++ b/Tiles/TileManager.cs @@ -0,0 +1,67 @@ +namespace Tiles; + +public class TileManager +{ + + private Dictionary _tileNameToId; + private Dictionary _tileIdToTile; + + public Dictionary TileNameToIdList => _tileNameToId; + + public TileManager() + { + _tileNameToId = new Dictionary(); + _tileIdToTile = new Dictionary(); + + SetupTiles(); + } + + public void SetupTiles() + { + _tileNameToId.Add("air", 0); + + int index = 1; + + foreach (var path in Directory.GetFiles("data/core/tiles/", "*.json")) + { + Tile tile; + + try + { + tile = Tile.GenerateTileFromJson(path); + + if (tile == null) throw new Exception($"Couldn't load tile {path}"); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + + Console.WriteLine($"Tile {tile.Name} loaded"); + _tileIdToTile.Add(index, tile); + _tileNameToId.Add(tile.Name, index); + index++; + } + } + + public Tile GetTileFromId(int id) + { + if (!_tileIdToTile.ContainsKey(id)) + { + throw new Exception($"Tile {id} not found"); + } + + return _tileIdToTile[id]; + } + + public int GetTileIdFromName(string name) + { + if (!_tileNameToId.ContainsKey(name)) + { + throw new Exception($"Tile {name} not found"); + } + + return _tileNameToId[name]; + } +} \ No newline at end of file diff --git a/Tiles/World.cs b/Tiles/World.cs new file mode 100644 index 0000000..41dc938 --- /dev/null +++ b/Tiles/World.cs @@ -0,0 +1,112 @@ +using System.Numerics; +using Raylib_cs; + +namespace Tiles; + +public class World +{ + public int TileSize { get; } + public int WorldWidth { get; } + public int WorldHeight { get; } + + private Dictionary<(int x, int y), int> _worldGrid; + + public World(int worldWidth = 2000, int worldHeight = 1000, int tileSize = 8) + { + WorldWidth = worldWidth; + WorldHeight = worldHeight; + TileSize = tileSize; + + _worldGrid = new Dictionary<(int x, int y), int>(); + } + + public void Update() + { + + } + + public void Draw() + { + // Calculate the boundaries of the visible region in grid coordinates + int startX = Math.Max((int)(Game.Instance.CameraController.Camera.Target.X - (Game.Instance.ScreenWidth / 2 / Game.Instance.CameraController.Camera.Zoom)) / TileSize, 0); + int startY = Math.Max((int)(Game.Instance.CameraController.Camera.Target.Y - (Game.Instance.ScreenHeight / 2 / Game.Instance.CameraController.Camera.Zoom)) / TileSize, 0); + int endX = Math.Min((int)(Game.Instance.CameraController.Camera.Target.X + (Game.Instance.ScreenWidth / 2 / Game.Instance.CameraController.Camera.Zoom)) / TileSize, WorldWidth - 1); + int endY = Math.Min((int)(Game.Instance.CameraController.Camera.Target.Y + (Game.Instance.ScreenHeight / 2 / Game.Instance.CameraController.Camera.Zoom)) / TileSize, WorldHeight - 1); + + // Loop only through the visible tiles + for (int x = startX; x <= endX; x++) + { + for (int y = startY; y <= endY; y++) + { + (int x, int y) position = new(x, y); + if (_worldGrid.TryGetValue(position, out var tileType) && tileType != 0) + { + Raylib.DrawTexture(Game.Instance.TileManager.GetTileFromId(tileType).Texture, x * TileSize, y * TileSize, Color.White); + } + } + } + } + + public void GenerateWorld() + { + int totalHeight = WorldHeight; + + int grassHeight = (int)(totalHeight * 0.01); + int dirtHeight = (int)(totalHeight * 0.10); + int airHeight = (int)(totalHeight * 0.50); + int rockHeight = totalHeight - (airHeight + grassHeight + dirtHeight); + + for (int x = 0; x < WorldWidth; x++) + { + for (int y = 0; y < totalHeight; y++) + { + string tileType; + + if (y >= airHeight && y < airHeight + grassHeight) + { + tileType = "grass"; + SetTile(x, y, Game.Instance.TileManager.GetTileIdFromName(tileType)); + } + else if (y >= airHeight + grassHeight && y < airHeight + grassHeight + dirtHeight) + { + tileType = "dirt"; + SetTile(x, y, Game.Instance.TileManager.GetTileIdFromName(tileType)); + } + else if (y >= airHeight + grassHeight + dirtHeight) + { + tileType = "rock"; + SetTile(x, y, Game.Instance.TileManager.GetTileIdFromName(tileType)); + } + } + } + } + + public Vector2 GetGridPositionFromGlobalPosition(int x, int y) + { + int gridX = x / TileSize; + int gridY = y / TileSize; + + if (gridX >= 0 && gridX < WorldWidth && gridY >= 0 && gridY < WorldHeight) + { + return new Vector2(gridX, gridY); + } + + return new Vector2(0, 0); + } + + public void SetTile(int x, int y, int id) + { + _worldGrid[(x, y)] = id; + } + + public int GetTile(int x, int y) + { + if (_worldGrid.ContainsKey((x,y))) return _worldGrid[(x,y)]; + return 0; + } + + public Vector2 GetGlobalPositionFromGrid(int x, int y) + { + return new(x * TileSize, y * TileSize); + } +} \ No newline at end of file