diff --git a/.gitignore b/.gitignore index fea8d3f..fa6f4c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .config/ .vscode/ -src/bin -src/**/obj \ No newline at end of file +**/bin/ +**/obj/ \ No newline at end of file diff --git a/src/Content/Content.mgcb b/Content/Content.mgcb similarity index 50% rename from src/Content/Content.mgcb rename to Content/Content.mgcb index ddc4c36..e1a4b9c 100644 --- a/src/Content/Content.mgcb +++ b/Content/Content.mgcb @@ -13,3 +13,15 @@ #---------------------------------- Content ---------------------------------# +#begin Tilemap.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Tilemap.png + diff --git a/Content/Tilemap.kra b/Content/Tilemap.kra new file mode 100644 index 0000000..11da0a8 Binary files /dev/null and b/Content/Tilemap.kra differ diff --git a/Content/Tilemap.kra~ b/Content/Tilemap.kra~ new file mode 100644 index 0000000..e1e7c66 Binary files /dev/null and b/Content/Tilemap.kra~ differ diff --git a/Content/Tilemap.png b/Content/Tilemap.png new file mode 100644 index 0000000..c1695d5 Binary files /dev/null and b/Content/Tilemap.png differ diff --git a/src/Game1.cs b/Game1.cs similarity index 69% rename from src/Game1.cs rename to Game1.cs index 00f6c75..ca94b74 100644 --- a/src/Game1.cs +++ b/Game1.cs @@ -2,14 +2,18 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; -using World; +using static tunnet.World.World; + namespace tunnet; public class Game1 : Game { private GraphicsDeviceManager _graphics; private SpriteBatch _spriteBatch; - private Dictionary _chunks; + // + private Map _world; + // private Texture2D _defaultTile; + // private const int TileSize = 32; public Game1() { @@ -21,7 +25,9 @@ public class Game1 : Game protected override void Initialize() { // TODO: Add your initialization logic here - _chunks = new Dictionary(); + _world = new Map(mapId: 0); + _world.LoadMap(); + // base.Initialize(); } @@ -29,8 +35,11 @@ public class Game1 : Game protected override void LoadContent() { _spriteBatch = new SpriteBatch(GraphicsDevice); + // _world.setContent(Content); // TODO: use this.Content to load your game content here + // _world._defaultTile = Texture2D.FromFile(GraphicsDevice, "src/Content/Tilemap.png"); + _world._defaultTile = Content.Load("Tilemap.png"); } protected override void Update(GameTime gameTime) @@ -48,7 +57,12 @@ public class Game1 : Game GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here + _spriteBatch.Begin(); + _world.Draw(ref _spriteBatch); + + _spriteBatch.End(); + // base.Draw(gameTime); } } diff --git a/src/Icon.bmp b/Icon.bmp similarity index 100% rename from src/Icon.bmp rename to Icon.bmp diff --git a/src/Icon.ico b/Icon.ico similarity index 100% rename from src/Icon.ico rename to Icon.ico diff --git a/src/Program.cs b/Program.cs similarity index 100% rename from src/Program.cs rename to Program.cs diff --git a/World/World.cs b/World/World.cs new file mode 100644 index 0000000..4beb3fe --- /dev/null +++ b/World/World.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace tunnet.World; +struct World +{ + private class Tile // TODO: sprite, buildings[] + { + public int Id { get; } + public Tile(int id) => Id = id; + public static Tile FromId(int id) + { + return new Tile(id); + } + } + private class Chunk + { + public const int Width = 16; + public const int Height = 16; + internal Tile[,] Tiles { get; private set; } + + public Chunk() + { + Tiles = new Tile[Width, Height]; + } + } + private static class ChunkStorage + { + /// + /// Saves the given chunk to disk in a compact binary format: + /// Width×Height consecutive Int32 tile IDs. + /// + public static void Save(string filePath, Chunk chunk) + { + if (chunk == null) + throw new System.ArgumentNullException(nameof(chunk)); + + Directory.CreateDirectory(Path.GetDirectoryName(filePath) ?? "."); + using var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write); + using var writer = new BinaryWriter(fs); + + for (int x = 0; x < Chunk.Width; x++) + { + for (int y = 0; y < Chunk.Height; y++) + { + // write each tile’s ID + writer.Write(chunk.Tiles[x, y]?.Id ?? 0); + } + } + } + public static void Save(int chunkX, int chunkY, Chunk chunk) + { + Save($"{chunkX}_{chunkY}.chunk", chunk); + } + + /// + /// Loads a chunk from the binary file format produced by Save(). + /// + public static Chunk Load(string filePath) + { + if (!File.Exists(filePath)) + throw new FileNotFoundException("Chunk file not found", filePath); + //TODO generate chunk instead + + var chunk = new Chunk(); + using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); + using var reader = new BinaryReader(fs); + + for (int x = 0; x < Chunk.Width; x++) + for (int y = 0; y < Chunk.Height; y++) + { + int id = reader.ReadInt32(); + chunk.Tiles[x, y] = Tile.FromId(id); + } + + return chunk; + } + public static Chunk Load(Point location) + { + var filePath = $"{location.X}_{location.Y}.chunk"; + if (File.Exists(filePath)) + return Load(filePath); + return null; + } + } + public class Map : Game + { + private readonly Dictionary _loadedChunks = new Dictionary(); + private IReadOnlyDictionary Chunks => _loadedChunks; + private readonly int id; + private readonly int TileSize; + public Texture2D _defaultTile; + + public Map(int mapId) + { + id = mapId; + TileSize = 32; + // Console.WriteLine(Content.Load("Tilemap.png").Width); + // _defaultTile = Texture2D.FromFile(GraphicsDevice, "Tilemap.png"); + // _defaultTile = Content.Load("Tilemap.png"); + } + + // Load the map by ID + public void LoadMap() + { + //TODO: Load map by ID + } + + // Generate a new map + private void GenerateMap() + { + //TODO: Implement map generation + } + + // Get a chunk (load if not in memory) + private Chunk GetChunk(Point location) + { + // var key = new Point(chunkX, chunkY); + if (!_loadedChunks.TryGetValue(location, out Chunk chunk)) + { + chunk = ChunkStorage.Load(location);// LoadChunkFromDisk(chunkX, chunkY); // Or generate + _loadedChunks[location] = chunk; + } + return chunk; + } + + // Access a specific tile + private Tile GetTile(int worldX, int worldY) + { + int chunkX = worldX / Chunk.Width; + int chunkY = worldY / Chunk.Height; + int tileX = worldX % Chunk.Width; + int tileY = worldY % Chunk.Height; + + // Handle negative coordinates + if (tileX < 0) tileX += Chunk.Width; + if (tileY < 0) tileY += Chunk.Height; + + return GetChunk(new Point(chunkX, chunkY)).Tiles[tileX, tileY]; + } + + // Unload distant chunks (memory management) + public void UnloadChunks(Point currentChunk, int keepRadius) + { + var keysToRemove = new List(); + foreach (var key in _loadedChunks.Keys) + { + if (System.Math.Abs(key.X - currentChunk.X) > keepRadius || + System.Math.Abs(key.Y - currentChunk.Y) > keepRadius) + { + ChunkStorage.Save(key.X, key.Y, _loadedChunks[key]); // Persist if needed + keysToRemove.Add(key); + } + } + keysToRemove.ForEach(k => _loadedChunks.Remove(k)); + } + + public void Draw(ref SpriteBatch spriteBatch) + { + foreach (var kvp in _loadedChunks) + { + Point chunkCoord = kvp.Key; + // var chunk = kvp.Value; + + for (int cx = 0; cx < Chunk.Width; cx++) + { + for (int cy = 0; cy < Chunk.Height; cy++) + { + // world‐space position in pixels + Vector2 pos = new Vector2( + (chunkCoord.X * Chunk.Width + cx) * TileSize, + (chunkCoord.Y * Chunk.Height + cy) * TileSize + ); + + // draw the default tile for now + spriteBatch.Draw(_defaultTile, pos, Color.White); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/app.manifest b/app.manifest similarity index 100% rename from src/app.manifest rename to app.manifest diff --git a/run.sh b/run.sh index ef64ddd..47c536a 100755 --- a/run.sh +++ b/run.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash echo "Running..." -exec dotnet run --no-build --project src/ +exec dotnet run --no-build diff --git a/src/src/World.cs b/src/src/World.cs deleted file mode 100644 index 65ea2ed..0000000 --- a/src/src/World.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using Microsoft.Xna.Framework; -// -namespace World; - -public class Tile -{ - public int Id { get; } - public Tile(int id) => Id = id; - public static Tile FromId(int id) => new Tile(id); -} -public class Chunk -{ - public const int Width = 16; - public const int Height = 16; - public Tile[,] Tiles { get; private set; } - - public Chunk() - { - Tiles = new Tile[Width, Height]; - } -} - -public static class ChunkStorage -{ - /// - /// Saves the given chunk to disk in a compact binary format: - /// Width×Height consecutive Int32 tile IDs. - /// - public static void Save(string filePath, Chunk chunk) - { - if (chunk == null) - throw new System.ArgumentNullException(nameof(chunk)); - - Directory.CreateDirectory(Path.GetDirectoryName(filePath) ?? "."); - using var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write); - using var writer = new BinaryWriter(fs); - - for (int x = 0; x < Chunk.Width; x++) - { - for (int y = 0; y < Chunk.Height; y++) - { - // write each tile’s ID - writer.Write(chunk.Tiles[x, y]?.Id ?? 0); - } - } - } - public static void Save(int chunkX, int chunkY, Chunk chunk) - { - Save($"{chunkX}_{chunkY}.chunk", chunk); - } - - /// - /// Loads a chunk from the binary file format produced by Save(). - /// - public static Chunk Load(string filePath) - { - if (!File.Exists(filePath)) - throw new FileNotFoundException("Chunk file not found", filePath); - - var chunk = new Chunk(); - using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); - using var reader = new BinaryReader(fs); - - for (int x = 0; x < Chunk.Width; x++) - for (int y = 0; y < Chunk.Height; y++) - { - int id = reader.ReadInt32(); - chunk.Tiles[x, y] = Tile.FromId(id); - } - - return chunk; - } - public static Chunk Load(int chunkX, int chunkY) - { - var filePath = $"{chunkX}_{chunkY}.chunk"; - if (File.Exists(filePath)) - return Load(filePath); - return null; - } -} -public class WorldMap -{ - private readonly Dictionary _loadedChunks = new Dictionary(); - - // Get a chunk (load if not in memory) - public Chunk GetChunk(int chunkX, int chunkY) - { - var key = new Point(chunkX, chunkY); - if (!_loadedChunks.TryGetValue(key, out Chunk chunk)) - { - chunk = ChunkStorage.Load(chunkX, chunkY);// LoadChunkFromDisk(chunkX, chunkY); // Or generate - _loadedChunks[key] = chunk; - } - return chunk; - } - - // Access a specific tile - public Tile GetTile(int worldX, int worldY) - { - int chunkX = worldX / Chunk.Width; - int chunkY = worldY / Chunk.Height; - int tileX = worldX % Chunk.Width; - int tileY = worldY % Chunk.Height; - - // Handle negative coordinates - if (tileX < 0) tileX += Chunk.Width; - if (tileY < 0) tileY += Chunk.Height; - - return GetChunk(chunkX, chunkY).Tiles[tileX, tileY]; - } - - // Unload distant chunks (memory management) - public void UnloadChunks(Point currentChunk, int keepRadius) - { - var keysToRemove = new List(); - foreach (var key in _loadedChunks.Keys) - { - if (System.Math.Abs(key.X - currentChunk.X) > keepRadius || - System.Math.Abs(key.Y - currentChunk.Y) > keepRadius) - { - ChunkStorage.Save(key.X, key.Y, _loadedChunks[key]); // Persist if needed - keysToRemove.Add(key); - } - } - keysToRemove.ForEach(k => _loadedChunks.Remove(k)); - } -} \ No newline at end of file diff --git a/src/tunnet.csproj b/tunnet.csproj similarity index 100% rename from src/tunnet.csproj rename to tunnet.csproj diff --git a/tunnet.sln b/tunnet.sln index aa36c25..e3c59bc 100644 --- a/tunnet.sln +++ b/tunnet.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tunnet", "src/tunnet.csproj", "{728D0B55-232F-4C2B-A31F-04EA4BFF4209}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tunnet", "tunnet.csproj", "{728D0B55-232F-4C2B-A31F-04EA4BFF4209}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution