player added
This commit is contained in:
41
AABB.cs
Normal file
41
AABB.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Camera.cs
30
Camera.cs
@@ -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
129
Entity.cs
Normal 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 we’re 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
13
Game.cs
Normal 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
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Player.cs
39
Player.cs
@@ -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)
|
||||||
|
|||||||
13
Program.cs
13
Program.cs
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
11
Shader.cs
11
Shader.cs
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
12
Window.cs
12
Window.cs
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user