added block breaking

This commit is contained in:
2025-09-03 00:37:42 +02:00
parent 00713db79e
commit 94ebc4ace4
6 changed files with 171 additions and 36 deletions

View File

@@ -6,7 +6,8 @@
Stone, Stone,
Dirt, Dirt,
OakPlanks, OakPlanks,
Grass Grass,
Bedrock
} }
public enum Orientation : uint public enum Orientation : uint
@@ -60,6 +61,7 @@
{ Voxel.Blocks.Stone, new BlockDefinition(Voxel.Blocks.Stone, Voxel.Textures.Stone) }, { Voxel.Blocks.Stone, new BlockDefinition(Voxel.Blocks.Stone, Voxel.Textures.Stone) },
{ Voxel.Blocks.Dirt, new BlockDefinition(Voxel.Blocks.Dirt, Voxel.Textures.Dirt) }, { Voxel.Blocks.Dirt, new BlockDefinition(Voxel.Blocks.Dirt, Voxel.Textures.Dirt) },
{ Voxel.Blocks.OakPlanks, new BlockDefinition(Voxel.Blocks.OakPlanks, Voxel.Textures.OakPlanks) }, { Voxel.Blocks.OakPlanks, new BlockDefinition(Voxel.Blocks.OakPlanks, Voxel.Textures.OakPlanks) },
{ Voxel.Blocks.Bedrock, new BlockDefinition(Voxel.Blocks.Bedrock, Voxel.Textures.Bedrock) },
{ Voxel.Blocks.Grass, new BlockDefinition( { Voxel.Blocks.Grass, new BlockDefinition(
Voxel.Blocks.Grass, Voxel.Blocks.Grass,

View File

@@ -2,8 +2,8 @@
{ {
public class Chunk public class Chunk
{ {
public readonly int Size = 16; public static int Size = 16;
public readonly int Height = 256; public static int Height = 256;
public readonly int PositionX; public readonly int PositionX;
public readonly int PositionY; public readonly int PositionY;
@@ -45,9 +45,12 @@
private void Initialize() private void Initialize()
{ {
Random rng = new Random(); for (int i = 0; i < Size * Size; i++)
for (int i = 0; i < Size * Size * 16; i++) _blocks[i] = Blocks.Bedrock;
_blocks[i] = (Blocks)rng.Next(5); for (int i = Size * Size * 1; i < Size * Size * 15; i++)
_blocks[i] = Blocks.Stone;
for (int i = Size * Size * 15; i < Size * Size * 16; i++)
_blocks[i] = Blocks.Grass;
} }
// todo // todo
@@ -62,6 +65,9 @@
private int GetBlockIndex(int x, int y, int z) private int GetBlockIndex(int x, int y, int z)
{ {
if (x < 0 || x > 15 || y < 0 || y > 255 || z < 0 || z > 15)
return 0;
return x + z * Size + y * Size * Size; return x + z * Size + y * Size * Size;
} }

40
Player.cs Normal file
View File

@@ -0,0 +1,40 @@
using OpenTK.Mathematics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Voxel
{
public class Player
{
public Vector3 Position;
private World _world;
public Player(World world, Vector3 startPos)
{
_world = world;
}
public void BreakBlock()
{
var (hit, x, y, z) = _world.Raycast(5f); // max 5 blocks
if (hit != Blocks.Air)
{
_world.SetBlock(x, y, z, Blocks.Air);
}
}
public void Update(float deltaTime)
{
Camera.Update(deltaTime);
if (Input.GetKey(OpenTK.Windowing.GraphicsLibraryFramework.Keys.Space))
{
BreakBlock();
}
}
}
}

View File

@@ -1,4 +1,5 @@
using Voxel; using OpenTK.Mathematics;
using Voxel;
internal class Program internal class Program
{ {
@@ -8,15 +9,19 @@ internal class Program
int sizeY = 600; int sizeY = 600;
string title = "Game"; string title = "Game";
World world = new World();
Window window = new Window(sizeX, sizeY, title); Window window = new Window(sizeX, sizeY, title);
Player player = new Player(world, Vector3.Zero);
window.Player = player;
Chunk chunk = new Chunk(0, 0); Chunk chunk = new Chunk(0, 0);
world.AddChunk(chunk);
ChunkMesh chunkMesh = chunk.GetChunkMesh(); ChunkMesh chunkMesh = chunk.GetChunkMesh();
Renderer.AddFaces(chunkMesh.Faces); Renderer.AddFaces(chunkMesh.Faces);
window.Chunk = chunk;
window.Run(); window.Run();
} }
} }

View File

@@ -1,5 +1,6 @@
using OpenTK.Graphics.OpenGL4; using OpenTK.Graphics.OpenGL4;
using OpenTK.Windowing.Common; using OpenTK.Windowing.Common;
using OpenTK.Windowing.Common.Input;
using OpenTK.Windowing.Desktop; using OpenTK.Windowing.Desktop;
namespace Voxel namespace Voxel
@@ -8,14 +9,10 @@ namespace Voxel
{ {
public readonly int Width = width; public readonly int Width = width;
public readonly int Height = height; public readonly int Height = height;
public Player Player;
public uint frames = 0; public uint frames = 0;
public double timeElapsed = 0; public double timeElapsed = 0;
// testing
public Chunk Chunk;
private Dictionary<int, bool> _cache = new Dictionary<int, bool>();
private bool chunkEmpty = false;
protected override void OnUpdateFrame(FrameEventArgs e) protected override void OnUpdateFrame(FrameEventArgs e)
{ {
base.OnUpdateFrame(e); base.OnUpdateFrame(e);
@@ -25,30 +22,10 @@ namespace Voxel
Close(); Close();
} }
RemoveRandomBlocks(); if (Player != null)
}
private void RemoveRandomBlocks()
{
if (Chunk != null && !chunkEmpty)
{ {
Random rng = new Random(); Player.Update((float)e.Time);
int GetNum()
{
int max = 4096;
int num = rng.Next(max);
if (_cache.ContainsKey(num)) return GetNum();
_cache[num] = true;
if (_cache.Count == max) chunkEmpty = true;
return num;
}
Chunk.SetBlockIndex(GetNum(), Blocks.Air);
} }
Renderer.ClearFaces();
Renderer.AddFaces(Chunk.GetChunkMesh().Faces);
} }
protected override void OnRenderFrame(FrameEventArgs e) protected override void OnRenderFrame(FrameEventArgs e)
@@ -93,6 +70,7 @@ namespace Voxel
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
CursorState = CursorState.Grabbed; CursorState = CursorState.Grabbed;
Cursor = MouseCursor.Default;
VSync = VSyncMode.On; VSync = VSyncMode.On;
Camera.UpdateProjection(Width, Height); Camera.UpdateProjection(Width, Height);

104
World.cs Normal file
View File

@@ -0,0 +1,104 @@
using OpenTK.Mathematics;
using System.Collections.Generic;
namespace Voxel
{
public class World
{
private Dictionary<(int, int), Chunk> _chunks;
public World()
{
_chunks = new Dictionary<(int, int), Chunk>();
}
// Get a chunk at world coordinates, returns null if not loaded
public Chunk GetChunk(int chunkX, int chunkZ)
{
_chunks.TryGetValue((chunkX, chunkZ), out Chunk chunk);
return chunk;
}
// Add a chunk
public void AddChunk(Chunk chunk)
{
_chunks[(chunk.PositionX, chunk.PositionY)] = chunk;
}
// Remove a chunk
public void RemoveChunk(int chunkX, int chunkZ)
{
_chunks.Remove((chunkX, chunkZ));
}
// Iterate over all chunks
public IEnumerable<Chunk> GetAllChunks()
{
return _chunks.Values;
}
// Optional: get a block at world coordinates
public Blocks GetBlock(int worldX, int worldY, int worldZ)
{
int chunkX = worldX / Chunk.Size;
int chunkZ = worldZ / Chunk.Size;
Chunk chunk = GetChunk(chunkX, chunkZ);
if (chunk == null) return 0; // air if chunk not loaded
int localX = worldX % Chunk.Size;
int localZ = worldZ % Chunk.Size;
return chunk.GetBlock(localX, worldY, localZ);
}
// Optional: set a block at world coordinates
public void SetBlock(int worldX, int worldY, int worldZ, Blocks block)
{
int chunkX = worldX / Chunk.Size;
int chunkZ = worldZ / Chunk.Size;
Chunk chunk = GetChunk(chunkX, chunkZ);
if (chunk == null) return;
int localX = worldX % Chunk.Size;
int localZ = worldZ % Chunk.Size;
chunk.SetBlock(localX, worldY, localZ, block);
Renderer.ClearFaces();
ChunkMesh chunkMesh = chunk.GetChunkMesh();
Renderer.AddFaces(chunkMesh.Faces);
}
public (Blocks block, int x, int y, int z) Raycast(float length)
{
Vector3 start = Camera.Position;
Vector3 dir = Camera.Front.Normalized();
float stepSize = 0.01f;
float distanceTraveled = 0f;
while (distanceTraveled < length)
{
Vector3 point = start + dir * distanceTraveled;
int bx = (int)MathF.Floor(point.X);
int by = (int)MathF.Floor(point.Y);
int bz = (int)MathF.Floor(point.Z);
Blocks block = GetBlock(bx, by, bz);
if (block != Blocks.Air)
{
return (block, bx, by, bz);
}
distanceTraveled += stepSize;
}
return (Blocks.Air, 0, 0, 0);
}
public void Update()
{
}
}
}