player added

This commit is contained in:
maxwes08
2025-09-30 10:58:12 +02:00
parent 38dccf0a84
commit 11f76ca429
11 changed files with 259 additions and 48 deletions

41
AABB.cs Normal file
View File

@@ -0,0 +1,41 @@
using OpenTK.Mathematics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Voxel
{
public struct AABB
{
public Vector3 Min;
public Vector3 Max;
public AABB(Vector3 min, Vector3 max)
{
Min = min;
Max = max;
}
public static AABB FromCenter(Vector3 center, float width, float height, float depth)
{
Vector3 half = new Vector3(width / 2f, 0, depth / 2f);
return new AABB(center - half, center + new Vector3(half.X, height, half.Z));
}
public bool Intersects(AABB other)
{
return (Min.X <= other.Max.X && Max.X >= other.Min.X) &&
(Min.Y <= other.Max.Y && Max.Y >= other.Min.Y) &&
(Min.Z <= other.Max.Z && Max.Z >= other.Min.Z);
}
public bool Contains(Vector3 point)
{
return (point.X >= Min.X && point.X <= Max.X) &&
(point.Y >= Min.Y && point.Y <= Max.Y) &&
(point.Z >= Min.Z && point.Z <= Max.Z);
}
}
}

View File

@@ -21,39 +21,15 @@ namespace Voxel
{ {
get get
{ {
float yawOffset = Yaw - 90f;
Vector3 front; Vector3 front;
front.X = MathF.Cos(MathHelper.DegreesToRadians(Yaw)) * MathF.Cos(MathHelper.DegreesToRadians(Pitch)); front.X = MathF.Cos(MathHelper.DegreesToRadians(yawOffset)) * MathF.Cos(MathHelper.DegreesToRadians(Pitch));
front.Y = MathF.Sin(MathHelper.DegreesToRadians(Pitch)); front.Y = MathF.Sin(MathHelper.DegreesToRadians(Pitch));
front.Z = MathF.Sin(MathHelper.DegreesToRadians(Yaw)) * MathF.Cos(MathHelper.DegreesToRadians(Pitch)); front.Z = MathF.Sin(MathHelper.DegreesToRadians(yawOffset)) * MathF.Cos(MathHelper.DegreesToRadians(Pitch));
return front.Normalized(); return front.Normalized();
} }
} }
public static void Update(float time)
{
float moveSpeed = Speed * time;
if (Input.GetKey(OpenTK.Windowing.GraphicsLibraryFramework.Keys.LeftShift))
{
moveSpeed = ShiftSpeed * time;
}
if (Input.GetKey(OpenTK.Windowing.GraphicsLibraryFramework.Keys.W))
{
Position += Front * moveSpeed;
}
if (Input.GetKey(OpenTK.Windowing.GraphicsLibraryFramework.Keys.S))
{
Position += Front * -moveSpeed;
}
if (Input.GetKey(OpenTK.Windowing.GraphicsLibraryFramework.Keys.A))
{
Position += Vector3.Cross(Front, Vector3.UnitY).Normalized() * -moveSpeed;
}
if (Input.GetKey(OpenTK.Windowing.GraphicsLibraryFramework.Keys.D))
{
Position += Vector3.Cross(Front, Vector3.UnitY).Normalized() * moveSpeed;
}
}
public static void UpdateMouse(Vector2 delta) public static void UpdateMouse(Vector2 delta)
{ {
float sensitivity = 0.1f; float sensitivity = 0.1f;

129
Entity.cs Normal file
View File

@@ -0,0 +1,129 @@
using OpenTK.Mathematics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Voxel
{
public class Entity
{
public Vector3 Position;
public Vector3 Velocity;
public bool OnGround;
public float Rotation;
public float Width;
public float Height;
private float _airDrag = 2f;
private float _groundDrag = 8f;
private World _world;
public Entity(Vector3 position, float width, float height, World world)
{
Position = position;
Width = width;
Height = height;
_world = world;
}
public void Tick(float deltaTime)
{
Console.WriteLine(OnGround);
if (!OnGround)
{
Console.WriteLine("Velocity: " + Velocity.Y.ToString());
Velocity -= new Vector3(
Velocity.X * _airDrag * deltaTime,
1.6f * deltaTime,
Velocity.Z * _airDrag * deltaTime);
}
else
{
Velocity = new Vector3(Velocity.X, 0, Velocity.Z);
Velocity -= new Vector3(
Velocity.X * _groundDrag * deltaTime,
0,
Velocity.Z * _groundDrag * deltaTime);
}
UpdateOnGround();
Position += Velocity;
Console.WriteLine("Position: " + Position.Y.ToString());
}
public AABB GetBoundingBox()
{
float halfWidth = Width / 2;
Vector3 min = new Vector3(
Position.X - halfWidth,
Position.Y - Height,
Position.Z - halfWidth
);
Vector3 max = new Vector3(
Position.X + halfWidth,
Position.Y + Height,
Position.Z + halfWidth
);
return new AABB(min, max);
}
private bool IsCollidingSide(Vector3 direction)
{
AABB box = GetBoundingBox();
// Determine which axis were checking
int checkX = direction.X > 0 ? (int)MathF.Floor(box.Max.X) : (int)MathF.Floor(box.Min.X);
int checkZ = direction.Z > 0 ? (int)MathF.Floor(box.Max.Z) : (int)MathF.Floor(box.Min.Z);
int minY = (int)MathF.Floor(box.Min.Y);
int maxY = (int)MathF.Floor(box.Max.Y);
// Sweep along vertical range
for (int y = minY; y <= maxY; y++)
{
if (_world.GetBlock(checkX, y, checkZ) != Blocks.Air)
return true;
}
return false;
}
public void UpdateOnGround()
{
AABB box = GetBoundingBox();
float yCheck = box.Min.Y - 0.05f;
int minX = (int)MathF.Floor(box.Min.X);
int maxX = (int)MathF.Floor(box.Max.X);
int minZ = (int)MathF.Floor(box.Min.Z);
int maxZ = (int)MathF.Floor(box.Max.Z);
OnGround = false;
for (int x = minX; x <= maxX; x++)
{
for (int z = minZ; z <= maxZ; z++)
{
Blocks block = _world.GetBlock(x, (int)MathF.Floor(yCheck), z);
if (block != Blocks.Air)
{
OnGround = true;
return;
}
}
}
}
}
}

13
Game.cs Normal file
View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Voxel
{
public static class Game
{
}
}

View File

@@ -3,24 +3,23 @@ using OpenTK.Windowing.GraphicsLibraryFramework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Voxel namespace Voxel
{ {
public class Player public class Player : Entity
{ {
public Vector3 Position;
private World _world; private World _world;
public double lastClick = 0; public double lastClick = 0;
public readonly float mouseCooldown = 0.2f; public readonly float mouseCooldown = 0.2f;
private int _blockIndex = 0; private int _blockIndex = 0;
private Blocks _selectedBlock = Blocks.Dirt; private Blocks _selectedBlock = Blocks.Dirt;
public Player(World world, Vector3 startPos) public Player(Vector3 startPos, World world) : base(startPos, 0.5f, 1.8f, world)
{ {
_world = world;
} }
public void PlaceBlock() public void PlaceBlock()
@@ -45,7 +44,8 @@ namespace Voxel
public void Update(float deltaTime) public void Update(float deltaTime)
{ {
Camera.Update(deltaTime); Camera.Position = Position + Vector3.UnitY * 0.5f;
Rotation = Camera.Yaw;
if (lastClick > 0) if (lastClick > 0)
{ {
@@ -71,6 +71,33 @@ namespace Voxel
BreakBlock(); BreakBlock();
} }
if (Input.GetKey(Keys.W))
ApplyLocalVelocity(0, -5 * deltaTime);
if (Input.GetKey(Keys.Space) && OnGround)
{
Velocity = new Vector3(Velocity.X, 0.5f, Velocity.Z);
OnGround = false;
Console.WriteLine("Jump");
}
}
public void ApplyLocalVelocity(float x, float z)
{
Vector3 localVelocity = new Vector3(x, 0, z);
float yaw = MathHelper.DegreesToRadians(Rotation);
float cos = MathF.Cos(yaw); // yaw in radians
float sin = MathF.Sin(yaw);
Vector3 worldVelocity = new Vector3(
localVelocity.X * cos - localVelocity.Z * sin,
Velocity.Y,
localVelocity.X * sin + localVelocity.Z * cos
);
Velocity = worldVelocity;
} }
public void SwitchBlock(bool inverted) public void SwitchBlock(bool inverted)

View File

@@ -11,14 +11,11 @@ internal class Program
World world = new World(); 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;
Console.WriteLine("Generating map..."); Console.WriteLine("Generating map...");
int worldSizeX = 32; int worldSizeX = 8;
int worldSizeY = 32; int worldSizeY = 8;
float maxI = worldSizeX * worldSizeY; float maxI = worldSizeX * worldSizeY;
int i = 0; int i = 0;
@@ -45,6 +42,12 @@ internal class Program
Renderer.SetWorld(world); Renderer.SetWorld(world);
Vector3 startPos = new Vector3(15, 64, 15);
Player player = new Player(startPos, world);
window.Update += player.Tick;
window.Update += player.Update;
window.Run(); window.Run();
} }
} }

View File

@@ -43,6 +43,7 @@ namespace Voxel
_shader.Use(); _shader.Use();
_shader.SetMatrix4("view", Camera.view); _shader.SetMatrix4("view", Camera.view);
_shader.SetVector3("cameraPosition", Camera.Position);
_shader.SetMatrix4("projection", Camera.projection); _shader.SetMatrix4("projection", Camera.projection);
if (_buffersDirty) if (_buffersDirty)

View File

@@ -67,6 +67,17 @@ namespace Voxel
GL.UniformMatrix4(location, false, ref matrix); GL.UniformMatrix4(location, false, ref matrix);
} }
public void SetVector3(string name, Vector3 vector3)
{
int location = GL.GetUniformLocation(_handle, name);
if (location == -1)
{
Console.WriteLine($"Uniform '{name}' not found in shader.");
return;
}
GL.Uniform3(location, ref vector3);
}
public void SetInt(string name, int value) public void SetInt(string name, int value)
{ {
int location = GL.GetUniformLocation(_handle, name); int location = GL.GetUniformLocation(_handle, name);

View File

@@ -2,12 +2,24 @@
out vec4 FragColor; out vec4 FragColor;
in vec2 fragUV; in vec2 fragUV;
in vec3 fragPos;
in float lighting; in float lighting;
uniform sampler2D uTexture; uniform sampler2D uTexture;
uniform vec3 cameraPosition;
void main() void main()
{ {
vec4 texColor = texture(uTexture, fragUV); float fogEnd = 512;
FragColor = vec4(texColor.rgb * lighting, texColor.a); float fogStart = 32;
float dist = length(cameraPosition - fragPos);
float fogFactor = (fogEnd - dist) / (fogEnd - fogStart);
fogFactor = clamp(fogFactor, 0, 1);
vec4 fogColor = vec4(0.8,0.8,0.8,1);
vec4 texColor = texture(uTexture, fragUV) * lighting;
vec4 color = mix(fogColor, texColor, fogFactor);
FragColor = vec4(color.rgb, texColor.a);
} }

View File

@@ -20,6 +20,7 @@ uniform int chunkY;
out vec2 fragUV; out vec2 fragUV;
out float lighting; out float lighting;
out vec3 fragPos;
const float lightMult[6] = float[6](0.6, 0.6, 1.0, 0.5, 0.8, 0.8); const float lightMult[6] = float[6](0.6, 0.6, 1.0, 0.5, 0.8, 0.8);
@@ -111,5 +112,6 @@ void main()
fragUV = uv; fragUV = uv;
lighting = lightMult[facing]; lighting = lightMult[facing];
fragPos = vec3(worldPos.x, worldPos.y, worldPos.z);
gl_Position = projection * view * worldPos; gl_Position = projection * view * worldPos;
} }

View File

@@ -10,14 +10,16 @@ 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;
public event Action<float> Update;
protected override void OnUpdateFrame(FrameEventArgs e) protected override void OnUpdateFrame(FrameEventArgs e)
{ {
base.OnUpdateFrame(e); base.OnUpdateFrame(e);
float deltaTime = (float)e.Time;
if (Input.GetKey(Keys.Escape)) if (Input.GetKey(Keys.Escape))
{ {
Close(); Close();
@@ -31,10 +33,7 @@ namespace Voxel
WindowState = WindowState.Normal; WindowState = WindowState.Normal;
} }
if (Player != null) Update.Invoke(deltaTime);
{
Player.Update((float)e.Time);
}
} }
protected override void OnRenderFrame(FrameEventArgs e) protected override void OnRenderFrame(FrameEventArgs e)
@@ -52,7 +51,6 @@ namespace Voxel
frames = 0; frames = 0;
} }
Camera.Update((float)e.Time);
Renderer.Render(); Renderer.Render();
SwapBuffers(); SwapBuffers();
@@ -123,8 +121,6 @@ namespace Voxel
if (e.OffsetY < 0) if (e.OffsetY < 0)
inverted = true; inverted = true;
Player.SwitchBlock(inverted);
} }
} }
} }