added block breaking
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
16
Chunk.cs
16
Chunk.cs
@@ -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
40
Player.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Program.cs
11
Program.cs
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
32
Window.cs
32
Window.cs
@@ -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
104
World.cs
Normal 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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user