diff --git a/assets/breaking.ase b/assets/breaking.ase new file mode 100644 index 0000000..03365c9 Binary files /dev/null and b/assets/breaking.ase differ diff --git a/assets/breaking.png b/assets/breaking.png new file mode 100644 index 0000000..16cc900 Binary files /dev/null and b/assets/breaking.png differ diff --git a/src/backend/interactor/Breaking.cs b/src/backend/interactor/Breaking.cs new file mode 100644 index 0000000..f9f4b73 --- /dev/null +++ b/src/backend/interactor/Breaking.cs @@ -0,0 +1,25 @@ +[Interactor] +class Breaking +{ + [Interaction(InteractorKind.Hybrid, "tick")] + public static void TickHybrid(TickPacket packet) + { + var ctx = Context.Get(); + ctx.GameState.Players.ForEach(player => + { + Math.Max(0, player.MiningCooldown -= 1); + if (player.Mining != null && player.MiningCooldown == 0) + { + var chunk = ctx.GameState.World.GetChunkAt(player.Mining); + // chunk.SetTileAt(player.Mining, tile with { Hits = tile.Hits + 1 }); + // var tile = chunk.GetTileAt(amp); + // if (tile.Hits >= hardness) + // { + // chunk.SetTileAt(amp, STile.From(0)); + // } + + } + } + ); + } +} diff --git a/src/core/Bootstrapper.cs b/src/core/Bootstrapper.cs index 24023ed..27ea3f1 100644 --- a/src/core/Bootstrapper.cs +++ b/src/core/Bootstrapper.cs @@ -4,9 +4,8 @@ class Bootstrapper { var ctx = Context.Get(); ctx.GameState.World = new World(); - ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(0, 1, Tiles.stone)); - ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(-1, 1, Tiles.stone)); - ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(1, 1, Tiles.stone)); - ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(1, 0, Tiles.stone)); + ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(0, 1, STile.From(Tiles.stone))); + ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(1, 1, STile.From(Tiles.stone))); + ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(1, 0, STile.From(Tiles.stone))); } } diff --git a/src/core/Camera.cs b/src/core/Camera.cs index 70be9e5..624771c 100644 --- a/src/core/Camera.cs +++ b/src/core/Camera.cs @@ -9,7 +9,6 @@ class Camera public void CenterOn(Vector2 target) { - Console.WriteLine("Centering camera on " + target); var ctx = Context.Get(); var scale = ctx.FrontendGameState.Settings.GameScale; var windowWidth = ctx.FrontendGameState.WindowWidth; diff --git a/src/core/PlayerEntity.cs b/src/core/PlayerEntity.cs index 097a59e..b7808a8 100644 --- a/src/core/PlayerEntity.cs +++ b/src/core/PlayerEntity.cs @@ -53,17 +53,24 @@ class PlayerEntity hasCollision = world.HasChunkAt(pL) && world.GetChunkAt(pL).hasTileAt(pL) || world.HasChunkAt(pR) && world.GetChunkAt(pR).hasTileAt(pR); - Console.WriteLine(World.ToChunkPos(p.Position)); - if (world.HasChunkAt(p.Position)) - { - var chunk = world.GetChunkAt(p.Position); - Console.WriteLine($"Chunk: {chunk.X}, {chunk.Y}"); - } if (hasCollision) { p.Movement = p.Movement with { Y = 0 }; p.Position += new Vector2(0, -0.1f); } } while (hasCollision); + do + { + var pL = p.Position + new Vector2(0, -32); + var pR = p.Position + new Vector2(16, -32); + hasCollision = + world.HasChunkAt(pL) && world.GetChunkAt(pL).hasTileAt(pL) + || world.HasChunkAt(pR) && world.GetChunkAt(pR).hasTileAt(pR); + if (hasCollision) + { + p.Movement = p.Movement with { Y = 0 }; + p.Position += new Vector2(0, 0.1f); + } + } while (hasCollision); } } diff --git a/src/core/data/Chunk.cs b/src/core/data/Chunk.cs index 65d5722..d223c63 100644 --- a/src/core/data/Chunk.cs +++ b/src/core/data/Chunk.cs @@ -1,6 +1,6 @@ class Chunk { - public int[,] Tiles { get; set; } = new int[Constants.ChunkSize, Constants.ChunkSize]; + public STile[,] Tiles { get; set; } = new STile[Constants.ChunkSize, Constants.ChunkSize]; public int X { get; set; } public int Y { get; set; } @@ -10,12 +10,12 @@ class Chunk this.Y = y; } - public void SetTile(int x, int y, int tile) + public void SetTile(int x, int y, STile tile) { this.Tiles[x, y] = tile; } - public int GetTile(int x, int y) + public STile GetTile(int x, int y) { return this.Tiles[x, y]; } @@ -33,21 +33,35 @@ class Chunk return this.hasTile(tileX, tileY); } - public int GetTileAt(Vector2 pos) + public STile GetTileAt(Vector2 pos) { return this.GetTileAt((int)pos.X, (int)pos.Y); } - public int GetTileAt(int x, int y) + public STile GetTileAt(int x, int y) { - var tileX = (int)Math.Floor(x / (float)Constants.TileSize); - var tileY = (int)Math.Floor(y / (float)Constants.TileSize); + var posInChunk = this.GetPositionInChunk(new Vector2(x, y)); + var tileX = (int)Math.Floor(posInChunk.X / Constants.TileSize); + var tileY = (int)Math.Floor(posInChunk.Y / Constants.TileSize); return this.GetTile(tileX, tileY); } + public void SetTileAt(Vector2 pos, STile tile) + { + this.SetTileAt((int)pos.X, (int)pos.Y, tile); + } + + public void SetTileAt(int x, int y, STile tile) + { + var posInChunk = this.GetPositionInChunk(new Vector2(x, y)); + var tileX = (int)Math.Floor(posInChunk.X / Constants.TileSize); + var tileY = (int)Math.Floor(posInChunk.Y / Constants.TileSize); + this.SetTile(tileX, tileY, tile); + } + public bool hasTile(int x, int y) { - return x >= 0 && x < this.Tiles.Length && y >= 0 && y < this.Tiles.Length; + return x >= 0 && x < this.Tiles.Length && y >= 0 && y < this.Tiles.Length && this.Tiles[x, y].Id != 0; } public bool hasTile(Vector2 pos) diff --git a/src/core/data/STile.cs b/src/core/data/STile.cs new file mode 100644 index 0000000..b1bc0cb --- /dev/null +++ b/src/core/data/STile.cs @@ -0,0 +1,18 @@ +struct STile +{ + public int Id { get; set; } + public int Hits { get; set; } + + public static STile From(int id) + { + return new STile() + { + Id = id + }; + } + + public static STile From(Tiles id) + { + return From((int)id); + } +} diff --git a/src/core/data/World.cs b/src/core/data/World.cs index 71d02e1..c32a20e 100644 --- a/src/core/data/World.cs +++ b/src/core/data/World.cs @@ -63,11 +63,16 @@ class World return new Vector2((float)chunkX, (float)chunkY); } - public int GetTileAt(int x, int y) + public STile GetTileAt(int x, int y) { return this.GetChunkAt(x, y).GetTileAt(x, y); } + public void SetTileAt(int x, int y, STile tile) + { + this.GetChunkAt(x, y).SetTileAt(x, y, tile); + } + public bool HasTileAt(int x, int y) { return this.HasChunkAt(x, y) && this.GetChunkAt(x, y).hasTileAt(new Vector2(x, y)); diff --git a/src/core/tiles/TextureCache.cs b/src/core/tiles/TextureCache.cs new file mode 100644 index 0000000..e69de29 diff --git a/src/core/tiles/Tile.cs b/src/core/tiles/Tile.cs index d49ef76..fafe49c 100644 --- a/src/core/tiles/Tile.cs +++ b/src/core/tiles/Tile.cs @@ -1,37 +1,68 @@ class Tile { public string Name { get; set; } - public IntPtr Texture { get; set; } + public int Hardness { get; set; } + private readonly IntPtr texture; + private static IntPtr breakingTexture; - public Tile(string name, string textureName) + public Tile(string name, string textureName, int hardness) { this.Name = name; + this.Hardness = hardness; var rl = Context.Get().ResourceLoader; var (ptr, size) = rl.LoadToIntPtr("assets." + textureName + ".png"); var sdlBuffer = SDL_RWFromMem(ptr, size); var surface = IMG_Load_RW(sdlBuffer, 1); var texture = Context.Get().Renderer.CreateTextureFromSurface(surface); - this.Texture = texture; + this.texture = texture; + if (breakingTexture == IntPtr.Zero) + { + loadBreakingTexture(); + } SDL_FreeSurface(surface); } ~Tile() { - SDL_DestroyTexture(this.Texture); + SDL_DestroyTexture(this.texture); } - public void Render(int x, int y) + public void Render(int x, int y, STile tile) { var renderer = Context.Get().Renderer; var scale = Context.Get().FrontendGameState.Settings.GameScale; var camera = Context.Get().FrontendGameState.Camera; renderer.DrawTexture( - this.Texture, + this.texture, (x - (int)camera.position.X) * scale, (y - (int)camera.position.Y) * scale, Constants.TileSize * scale, Constants.TileSize * scale ); + if (tile.Hits > 0) + { + var breakingOffset = (int)((double)tile.Hits / this.Hardness * 4); + renderer.DrawTexture( + breakingTexture, + (x - (int)camera.position.X) * scale, + (y - (int)camera.position.Y) * scale, + Constants.TileSize * scale, + Constants.TileSize * scale, + breakingOffset, + 16, + 16 + ); + } + } + + private static void loadBreakingTexture() + { + var rl = Context.Get().ResourceLoader; + var (ptr, size) = rl.LoadToIntPtr("assets.breaking.png"); + var sdlBuffer = SDL_RWFromMem(ptr, size); + var surface = IMG_Load_RW(sdlBuffer, 1); + breakingTexture = Context.Get().Renderer.CreateTextureFromSurface(surface); + SDL_FreeSurface(surface); } } diff --git a/src/core/tiles/TileRegistry.cs b/src/core/tiles/TileRegistry.cs index 4eb67f1..0e77e7a 100644 --- a/src/core/tiles/TileRegistry.cs +++ b/src/core/tiles/TileRegistry.cs @@ -9,7 +9,7 @@ class TileRegistry public void RegisterTile() { - this.Tiles.Add(1, new Tile("stone", "stone")); + this.Tiles.Add(1, new Tile("stone", "stone", 5)); } public Tile GetTile(int id) diff --git a/src/core/world/ChunkGenerator.cs b/src/core/world/ChunkGenerator.cs index 193253e..eae02c4 100644 --- a/src/core/world/ChunkGenerator.cs +++ b/src/core/world/ChunkGenerator.cs @@ -1,6 +1,6 @@ class ChunkGenerator { - public static Chunk CreateFilledChunk(int x, int y, int fill) + public static Chunk CreateFilledChunk(int x, int y, STile fill) { var chunk = new Chunk(x, y); for (var i = 0; i < Constants.ChunkSize; i++) @@ -12,9 +12,4 @@ class ChunkGenerator } return chunk; } - - public static Chunk CreateFilledChunk(int x, int y, Tiles fill) - { - return CreateFilledChunk(x, y, (int)fill); - } } diff --git a/src/engine/Renderer.cs b/src/engine/Renderer.cs index 65c99b0..85b6aa4 100644 --- a/src/engine/Renderer.cs +++ b/src/engine/Renderer.cs @@ -128,6 +128,25 @@ class Renderer w = w, h = h }; - SDL_RenderCopy(renderer, texture, IntPtr.Zero, ref rect); + _ = SDL_RenderCopy(this.renderer, texture, IntPtr.Zero, ref rect); + } + + public void DrawTexture(IntPtr texture, int x, int y, int w, int h, int offsetIndex, int srcWidth, int srcHeight) + { + SDL_Rect rect = new() + { + x = x, + y = y, + w = w, + h = h + }; + SDL_Rect srcRect = new() + { + x = srcWidth * offsetIndex, + y = 0, + w = srcWidth, + h = srcHeight, + }; + _ = SDL_RenderCopy(this.renderer, texture, ref srcRect, ref rect); } } diff --git a/src/frontend/Frontend.cs b/src/frontend/Frontend.cs index 493b615..43a33dc 100644 --- a/src/frontend/Frontend.cs +++ b/src/frontend/Frontend.cs @@ -42,6 +42,26 @@ class Frontend : IFrontend Console.WriteLine($"Mouse moved to {mousePos}"); ctx.FrontendGameState.MousePosition = mousePos; } + if (e.type == SDL_EventType.SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT) + { + var amp = ctx.FrontendGameState.MousePosition / ctx.FrontendGameState.Settings.GameScale + ctx.FrontendGameState.Camera.position; + if (ctx.GameState.World.HasChunkAt(amp)) + { + var chunk = ctx.GameState.World.GetChunkAt(amp); + var tile = chunk.GetTileAt(amp); + var tileId = tile.Id; + if (tile.Id != 0) + { + var tileRegistry = ctx.TileRegistry; + var hardness = tileRegistry.GetTile(tileId).Hardness; + chunk.SetTileAt(amp, tile with { Hits = tile.Hits + 1 }); + if (tile.Hits >= hardness) + { + chunk.SetTileAt(amp, STile.From(0)); + } + } + } + } if (e.type == SDL_EventType.SDL_KEYDOWN && e.key.repeat == 0) { var movementInput = ctx.FrontendGameState.MovementInput; diff --git a/src/frontend/renderer/WorldRenderer.cs b/src/frontend/renderer/WorldRenderer.cs index f80c9d8..28267a1 100644 --- a/src/frontend/renderer/WorldRenderer.cs +++ b/src/frontend/renderer/WorldRenderer.cs @@ -4,19 +4,23 @@ class WorldRenderer : IRenderer { var ctx = Context.Get(); var world = ctx.GameState.World; - var renderer = ctx.Renderer; var tileRegistry = ctx.TileRegistry; foreach (var (_, chunk) in world.Chunks) { - for (int y = 0; y < Constants.ChunkSize; y++) + for (var y = 0; y < Constants.ChunkSize; y++) { - for (int x = 0; x < Constants.ChunkSize; x++) + for (var x = 0; x < Constants.ChunkSize; x++) { - var tileId = chunk.GetTile(x, y); - var tile = tileRegistry.GetTile(tileId); + var stile = chunk.GetTile(x, y); + if (stile.Id == 0) + { + continue; + } + + var tile = tileRegistry.GetTile(stile.Id); var chunkOffsetX = chunk.X * Constants.TileSize * Constants.ChunkSize; var chunkOffsetY = chunk.Y * Constants.TileSize * Constants.ChunkSize; - tile.Render(x * 16 + chunkOffsetX, y * 16 + chunkOffsetY); + tile.Render(x * 16 + chunkOffsetX, y * 16 + chunkOffsetY, stile); } } }