diff --git a/TheRepo/TheLabs/BoxCollider.cs b/TheRepo/TheLabs/BoxCollider.cs new file mode 100644 index 0000000..a697b5f --- /dev/null +++ b/TheRepo/TheLabs/BoxCollider.cs @@ -0,0 +1,27 @@ +using OpenTK.Mathematics; +namespace TheLabs; + +public class BoxCollider +{ + public Vector3 Center; + + public Vector3 HalfSize; + + public BoxCollider(Vector3 center, Vector3 halfSize) + { + Center = center; + HalfSize = halfSize * 0.5f; + } + public Vector3 Min => Center - HalfSize; + public Vector3 Max => Center + HalfSize; + + public bool CheckCollision(BoxCollider other) + { + + bool collisionX = Max.X >= other.Min.X && Min.X <= other.Max.X; + bool collisionY = Max.Y >= other.Min.Y && Min.Y <= other.Max.Y; + bool collisionZ = Max.Z >= other.Min.Z && Min.Z <= other.Max.Z; + + return collisionX && collisionY && collisionZ; + } +} \ No newline at end of file diff --git a/TheRepo/TheLabs/LevelLoader.cs b/TheRepo/TheLabs/LevelLoader.cs new file mode 100644 index 0000000..1a15a5c --- /dev/null +++ b/TheRepo/TheLabs/LevelLoader.cs @@ -0,0 +1,64 @@ +using Assimp; +using LearnOpenTK.Common; +using OpenTK.Mathematics; + +namespace TheLabs; + +public class LevelLoader +{ + + private Shader _shader; + private Texture _texture; + private Texture _normalTexture; + private Material _material; + private Lighting _lighting; + + + public LevelLoader(Shader shader, Texture texture, Texture normalTexture, Material material, Lighting lighting) + { + _shader = shader; + _texture = texture; + _normalTexture = normalTexture; + _material = material; + _lighting = lighting; + } + + public void LoadLevel(string filepath, SceneNode rootenode, List colliders) + { + Mesh _mesh = ShapeFactory.CreateTexturedCube(); + RenderObject renderObject = new RenderObject(_mesh, _shader, _texture, _material, _lighting); + renderObject.NormalMap = _normalTexture; + renderObject.UseTexture = true; + + if (!File.Exists(filepath)) + { + throw new FileNotFoundException("The specified level file was not found.", filepath); + } + string[] lines = File.ReadAllLines(filepath); + float spacing = 1.0f; + + for (int z = 0; z < lines.Length; z++) + { + string line = lines[z]; + for (int x = 0; x < line.Length; x++) + { + char tile = line[x]; + + SceneNode floorNode = new SceneNode(renderObject); + floorNode.Position = new Vector3(x * spacing, -0.5f, z * spacing); + floorNode.Scale = new Vector3(1.0f, 0.1f, 1.0f); + rootenode.AddChild(floorNode); + + if (tile == '1') + { + BoxCollider wallCollider = new BoxCollider(new Vector3(x, 0, z), new Vector3(1, 1, 1)); + colliders.Add(wallCollider); + SceneNode wallNode = new SceneNode(renderObject); + wallNode.Position = new Vector3(x * spacing, 0.0f, z * spacing); + + rootenode.AddChild(wallNode); + } + } + } + } +} \ No newline at end of file diff --git a/TheRepo/TheLabs/Levels/level1.txt b/TheRepo/TheLabs/Levels/level1.txt new file mode 100644 index 0000000..ebe6825 --- /dev/null +++ b/TheRepo/TheLabs/Levels/level1.txt @@ -0,0 +1,7 @@ +1111111111 +1000000001 +1011101101 +1010000101 +1010110101 +1000000001 +1111111111 \ No newline at end of file diff --git a/TheRepo/TheLabs/MyExampleWindow.cs b/TheRepo/TheLabs/MyExampleWindow.cs index 7c5718d..2894295 100644 --- a/TheRepo/TheLabs/MyExampleWindow.cs +++ b/TheRepo/TheLabs/MyExampleWindow.cs @@ -38,11 +38,14 @@ namespace TheLabs private float _mouseSensitivity = 0.1f; private float _pitch = 0.0f; private float _rotation = 0.0f; + Vector3 playerSize = new Vector3(0.5f, 1.0f, 0.5f); // Materials and Lighting private Lighting _mainLight; private Material _defaultMaterial; + private List _wallColliders = new List(); + // This prevents a large camera jump when the window first gets focus private bool _firstMove = true; @@ -75,27 +78,25 @@ namespace TheLabs GL.Enable(EnableCap.DepthTest); // --- Set up Camera --- - _camera = new Camera(_cameraPosition, _cameraFront, _cameraUp); // -- Load Shaders, Textures, and Create Scene Objects --- _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); _texture = new Texture("Textures/cobble.jpg"); Texture _normalMap = new Texture("Textures/cobbleNormal.jpg"); + LevelLoader levelLoader = new LevelLoader(_shader, _texture, _normalMap, _defaultMaterial, _mainLight); - // --- Create Scene Graph --- _rootNode = new SceneNode(); - // Create Example Object - _buildingObject = ShapeFactory.CreateTexturedCube(); - _buildingRender = new RenderObject(_buildingObject, _shader, _texture, _defaultMaterial, _mainLight); - _buildingRender.NormalMap = _normalMap; - _buildingNode = new SceneNode(_buildingRender); - _buildingNode.Position = new Vector3(2.0f, -1.0f, 0.0f); - _buildingNode.Scale = new Vector3(0.9f, 0.1f, 0.1f); - _rootNode.AddChild(_buildingNode); + string levelFilePath = "Levels/level1.txt"; + levelLoader.LoadLevel(levelFilePath, _rootNode, _wallColliders); + + // --- Create Scene Graph --- + // Create Character Object + _cameraPosition = new Vector3(-2.5f, 0.0f, 1.5f); + _camera = new Camera(_cameraPosition, _cameraFront, _cameraUp); CursorState = CursorState.Grabbed; @@ -138,6 +139,15 @@ namespace TheLabs base.OnUpdateFrame(e); _rotation += (float)e.Time; var input = KeyboardState; + float gravity = -9.81f; + + _camera._position.Y += gravity * (float)e.Time; + float floorHeight = 0.0f; + + if (_camera._position.Y < floorHeight) + { + _camera._position.Y = floorHeight; + } if (input.IsKeyDown(Keys.Escape)) { @@ -186,6 +196,17 @@ namespace TheLabs { _pitch -= _rotationSpeed * (float)e.Time; } + + if (input.IsKeyDown(Keys.Space)) + { + + if (_camera._position.Y <= floorHeight + 0.01f) + { + _camera._position.Y += 10.0f * (float)e.Time; + } + + } + _pitch = MathHelper.Clamp(_pitch, -89.0f, 89.0f); Vector3 front; _camera._target.X = MathF.Cos(MathHelper.DegreesToRadians(_yaw)) * MathF.Cos(MathHelper.DegreesToRadians(_pitch)); @@ -193,8 +214,30 @@ namespace TheLabs _camera._target.Z = MathF.Sin(MathHelper.DegreesToRadians(_yaw)) * MathF.Cos(MathHelper.DegreesToRadians(_pitch)); _cameraFront = Vector3.Normalize(_camera._target); - var _cameraRight = Vector3.Normalize(Vector3.Cross(_cameraFront, _camera._up)); - if (input.IsKeyDown(Keys.W)) _camera._position += _cameraFront * _cameraSpeed * (float)e.Time; + var _cameraRight = Vector3.Normalize(Vector3.Cross(_cameraFront, _camera._up)); + if (input.IsKeyDown(Keys.W)) + { + Vector3 proposedPosition = _camera._position + _cameraFront * _cameraSpeed * (float)e.Time; + BoxCollider playerCollider = new BoxCollider(proposedPosition, playerSize); + + bool safe = true; + foreach (var wall in _wallColliders) + { + if (playerCollider.CheckCollision(wall)) + { + safe = false; + break; + } + } + + if (safe) + { + _camera._position = proposedPosition; + + } + + } + if (input.IsKeyDown(Keys.S)) _camera._position -= _cameraFront * _cameraSpeed * (float)e.Time; if (input.IsKeyDown(Keys.A)) _camera._position -= _cameraRight * _cameraSpeed * (float)e.Time; if (input.IsKeyDown(Keys.D)) _camera._position += _cameraRight * _cameraSpeed * (float)e.Time; diff --git a/TheRepo/TheLabs/ShapeFactory.cs b/TheRepo/TheLabs/ShapeFactory.cs index f633adf..0235fb0 100644 --- a/TheRepo/TheLabs/ShapeFactory.cs +++ b/TheRepo/TheLabs/ShapeFactory.cs @@ -332,26 +332,31 @@ public static class ShapeFactory return new Mesh(vertices.ToArray(), indices.ToArray(), Mesh.VertexLayout.PosTexNormal); } - public static Mesh createTexturedSquare() + public static Mesh CreateTexturedQuad() { - float[] vertices = { - // Format: X, Y, Z, U, V - - // --- Front Face --- - -0.5f, -0.5f, 0.0f, 0f, 0f, // Bottom-left - 0.5f, -0.5f, 0.0f, 1f, 0f, // Bottom-right - 0.5f, 0.5f, 0.0f, 1f, 1f, // Top-right - -0.5f, 0.5f, 0.0f, 0f, 1f, // Top-left - }; - - uint[] indices = { - // Front face - 0, 2, 1, - 0, 2, 3, - }; - - return new Mesh(vertices, indices, Mesh.VertexLayout.PosTex); + List vertices = new List(); + List indices = new List(); + + // Create a flat quad facing UP (Normal 0, 1, 0) + Helpers.AddFace(vertices, indices, + new Vertex(new Vector3(-0.5f, 0.0f, 0.5f), new Vector3(0, 1, 0), new Vector2(0, 0), Vector3.Zero, Vector3.Zero), // BL + new Vertex(new Vector3( 0.5f, 0.0f, 0.5f), new Vector3(0, 1, 0), new Vector2(1, 0), Vector3.Zero, Vector3.Zero), // BR + new Vertex(new Vector3( 0.5f, 0.0f, -0.5f), new Vector3(0, 1, 0), new Vector2(1, 1), Vector3.Zero, Vector3.Zero), // TR + new Vertex(new Vector3(-0.5f, 0.0f, -0.5f), new Vector3(0, 1, 0), new Vector2(0, 1), Vector3.Zero, Vector3.Zero) // TL + ); + + // Convert to arrays and return + List finalFloats = new List(); + foreach (var v in vertices) + { + finalFloats.Add(v.Position.X); finalFloats.Add(v.Position.Y); finalFloats.Add(v.Position.Z); + finalFloats.Add(v.Normal.X); finalFloats.Add(v.Normal.Y); finalFloats.Add(v.Normal.Z); + finalFloats.Add(v.TexCoords.X); finalFloats.Add(v.TexCoords.Y); + finalFloats.Add(v.Tangent.X); finalFloats.Add(v.Tangent.Y); finalFloats.Add(v.Tangent.Z); + finalFloats.Add(v.Bitangent.X); finalFloats.Add(v.Bitangent.Y); finalFloats.Add(v.Bitangent.Z); + } + + return new Mesh(finalFloats.ToArray(), indices.ToArray(), Mesh.VertexLayout.PosTexNormalTangent); } - } \ No newline at end of file diff --git a/TheRepo/TheLabs/TheLabs.csproj b/TheRepo/TheLabs/TheLabs.csproj index 00c10e4..48de6b6 100644 --- a/TheRepo/TheLabs/TheLabs.csproj +++ b/TheRepo/TheLabs/TheLabs.csproj @@ -33,5 +33,10 @@ + + + PreserveNewest + +