diff --git a/SampleGame/src/Program.bf b/SampleGame/src/Program.bf index d98ad92..1f7c2c3 100644 --- a/SampleGame/src/Program.bf +++ b/SampleGame/src/Program.bf @@ -1,4 +1,5 @@ using System; +using Strawberry.SDL2; namespace Strawberry.Sample { diff --git a/src/Core/Entity.bf b/src/Core/Entity.bf index 150f316..3522679 100644 --- a/src/Core/Entity.bf +++ b/src/Core/Entity.bf @@ -423,7 +423,7 @@ namespace Strawberry public void DrawHitbox(Color color) { - Draw.Rect(SceneHitbox, color); + Game.Batcher.Rect(SceneHitbox, color); } static public int Compare(Entity a, Entity b) diff --git a/src/Core/Game.bf b/src/Core/Game.bf index 114884b..bd53731 100644 --- a/src/Core/Game.bf +++ b/src/Core/Game.bf @@ -29,7 +29,8 @@ namespace Strawberry private Dictionary> componentAssignableLists; public PlatformLayer PlatformLayer { get; private set; } - public Color ClearColor = .Red; + public Batcher Batcher { get; private set; } + public Color ClearColor = .Black; private bool* keyboardState; private int32 updateCounter; @@ -53,6 +54,7 @@ namespace Strawberry Directory.SetCurrentDirectory(exeDir); platformLayer.Init(); + Batcher = platformLayer.CreateBatcher(); VirtualInputs = new List(); Input.[Friend]Init(); @@ -83,6 +85,9 @@ namespace Strawberry DisposeTypeLists(); Input.[Friend]Dispose(); Strawberry.Console.Dispose(); + + delete Batcher; + Game = null; } @@ -97,7 +102,6 @@ namespace Strawberry uint32 tick = PlatformLayer.Ticks; msCounter += (tick - prevTick); - prevTick = tick; if (Time.FixedTimestep) { @@ -112,13 +116,14 @@ namespace Strawberry } else { - Time.RawDelta = msCounter / 1000; + Time.RawDelta = (tick - prevTick) / 1000f; PlatformLayer.UpdateInput(); Update(); Input.AfterUpdate(); } Render(); + prevTick = tick; } } @@ -157,21 +162,18 @@ namespace Strawberry private void Render() { PlatformLayer.RenderBegin(); - //Draw(); + Draw(); PlatformLayer.RenderEnd(); } public virtual void Draw() { - if (Scene != null) - { - Draw.PushCamera(Scene.Camera.Round()); - Scene.Draw(); - Draw.PopCamera(); - } + Scene?.Draw(); if (Console.Enabled) Strawberry.Console.[Friend]Draw(); + + Batcher.Draw(); } public Scene Scene diff --git a/src/Core/Scene.bf b/src/Core/Scene.bf index 83732fd..f0b0f0a 100644 --- a/src/Core/Scene.bf +++ b/src/Core/Scene.bf @@ -8,7 +8,6 @@ namespace Strawberry public float TimeStarted { get; private set; } public Grid SolidGrid; public Rect Bounds; - public Vector Camera; private List entities; private HashSet toRemove; diff --git a/src/Physics/Grid.bf b/src/Physics/Grid.bf index 0a0b7c4..adb5589 100644 --- a/src/Physics/Grid.bf +++ b/src/Physics/Grid.bf @@ -173,7 +173,7 @@ namespace Strawberry for (let x < CellsX) for (let y < CellsY) if (this[x, y] != '0') - Draw.Rect(Rect(x, y, 1, 1) * CellSize + Offset, color); + Game.Batcher.Rect(Rect(x, y, 1, 1) * CellSize + Offset, color); } } } diff --git a/src/Physics/Solid.bf b/src/Physics/Solid.bf index 8044c07..5353b7d 100644 --- a/src/Physics/Solid.bf +++ b/src/Physics/Solid.bf @@ -88,7 +88,7 @@ namespace Strawberry public override void Draw() { - DrawHitbox(.(255, 255, 255, 255)); + DrawHitbox(.White); } } } diff --git a/src/PlatformLayer/Batcher.bf b/src/PlatformLayer/Batcher.bf index 763c9aa..6a60b87 100644 --- a/src/PlatformLayer/Batcher.bf +++ b/src/PlatformLayer/Batcher.bf @@ -1,110 +1,20 @@ -using System.Collections; -using System; - namespace Strawberry { - public class Batcher + public abstract class Batcher { - static public int VertexSize => sizeof(Vertex); + public abstract void Draw(); - private List batchStack = new List() ~ DeleteContainerAndItems!(_); - private Batch top => batchStack.Count > 0 ? batchStack[batchStack.Count - 1] : null; + protected abstract void PushQuad(Vertex a, Vertex b, Vertex c, Vertex d); + protected abstract void PushTri(Vertex a, Vertex b, Vertex c); - private List vertices = new .() ~ delete _; - private List indices = new .() ~ delete _; - - private uint32 vaoID; - private uint32 vertexBufferID; - private uint32 indexBufferID; - - public this() + public void Rect(float x, float y, float w, float h, Color color) { - GL.glGenVertexArrays(1, &vaoID); - GL.glBindVertexArray(vaoID); - GL.glGenBuffers(1, &vertexBufferID); - GL.glGenBuffers(1, &indexBufferID); - GL.glBindVertexArray(0); + PushQuad(.Shape(.(x, y), color), .Shape(.(x + w, y), color), .Shape(.(x + w, y + h), color), .Shape(.(x, y + h), color)); } - public ~this() + public void Rect(Rect rect, Color color) { - GL.glDeleteBuffers(1, &vertexBufferID); - GL.glDeleteBuffers(1, &indexBufferID); - GL.glDeleteVertexArrays(1, &vaoID); - } - - public void Draw() - { - GL.glDisable(GL.GL_CULL_FACE); - - GL.glBindVertexArray(vaoID); - - GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBufferID); - GL.glEnableVertexAttribArray(0); - GL.glVertexAttribPointer(0, 2, GL.GL_FLOAT, GL.GL_FALSE, Batcher.VertexSize, (void*)0); - GL.glEnableVertexAttribArray(1); - GL.glVertexAttribPointer(1, 2, GL.GL_FLOAT, GL.GL_FALSE, Batcher.VertexSize, (void*)8); - GL.glEnableVertexAttribArray(2); - GL.glVertexAttribPointer(2, 4, GL.GL_UNSIGNED_BYTE, GL.GL_TRUE, Batcher.VertexSize, (void*)16); - GL.glEnableVertexAttribArray(3); - GL.glVertexAttribPointer(3, 3, GL.GL_UNSIGNED_BYTE, GL.GL_TRUE, Batcher.VertexSize, (void*)20); - GL.glBufferData(GL.GL_ARRAY_BUFFER, vertices.Count * sizeof(Vertex), vertices.Ptr, GL.GL_DYNAMIC_DRAW); - - GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBufferID); - GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices.Count * sizeof(uint32), indices.Ptr, GL.GL_DYNAMIC_DRAW); - - GL.glDrawElements(GL.GL_TRIANGLES, indices.Count, GL.GL_UNSIGNED_INT, (void*)0); - GL.glBindVertexArray(0); - - vertices.Clear(); - indices.Clear(); - } - - public void PushQuad(Vector a, Vector b, Vector c, Vector d, Color color) - { - uint32 count = (uint32)vertices.Count; - - vertices.Add(Vertex.Shape(a, color)); - vertices.Add(Vertex.Shape(b, color)); - vertices.Add(Vertex.Shape(c, color)); - vertices.Add(Vertex.Shape(d, color)); - - indices.Add(count + 0); - indices.Add(count + 1); - indices.Add(count + 2); - indices.Add(count + 0); - indices.Add(count + 2); - indices.Add(count + 3); - } - - private class Batch - { - uint32 bufferHandle; - - public this() - { - //GL.glGenBuffers(1, &bufferHandle); - //GL.glBindBuffer(GL.GL_ARRAY_BUFFER, bufferHandle); - //GL.glDeleteBuffers(1, &bufferHandle); - } - } - - [Ordered, Packed, CRepr] - private struct Vertex - { - public Vector Position; - public Vector TexCoord; - public Color Color; - public (uint8, uint8, uint8) Mode; - - static public Vertex Shape(Vector pos, Color color) - { - Vertex v = Vertex(); - v.Position = pos; - v.Color = color; - v.Mode = (0, 0, 255); - return v; - } + Rect(rect.X, rect.Y, rect.Width, rect.Height, color); } } } diff --git a/src/PlatformLayer/PlatformLayer.bf b/src/PlatformLayer/PlatformLayer.bf index dd9654d..d6271ff 100644 --- a/src/PlatformLayer/PlatformLayer.bf +++ b/src/PlatformLayer/PlatformLayer.bf @@ -23,50 +23,7 @@ namespace Strawberry //Graphics public abstract Texture LoadTexture(String path); - } - - public abstract class Texture - { - public int Width { get; private set; } - public int Height { get; private set; } - - public virtual this(int width, int height, uint8* pixels) - { - Width = width; - Height = height; - } - } - - public abstract class Shader - { - public bool IsValid { get; protected set; } - - public this(ShaderDef def) - { - - } - } - - public struct ShaderDef - { - public String Vertex; - public String Fragment; - - public this(String vertex, String fragment) - { - Vertex = vertex; - Fragment = fragment; - } - - public this(String[2] str) - { - Vertex = str[0]; - Fragment = str[1]; - } - - static implicit public operator ShaderDef(String[2] str) - { - return ShaderDef(str); - } + public abstract Batcher CreateBatcher(); + public abstract Shader CreateShader(ShaderDef def); } } diff --git a/src/PlatformLayer/SDL2/SDL2Batcher.bf b/src/PlatformLayer/SDL2/SDL2Batcher.bf new file mode 100644 index 0000000..28c98e0 --- /dev/null +++ b/src/PlatformLayer/SDL2/SDL2Batcher.bf @@ -0,0 +1,88 @@ +using System.Collections; +using System; + +namespace Strawberry.SDL2 +{ + public class SDL2Batcher : Batcher + { + private List vertices = new .() ~ delete _; + private List indices = new .() ~ delete _; + + private uint32 vaoID; + private uint32 vertexBufferID; + private uint32 indexBufferID; + + public this() + { + GL.glGenVertexArrays(1, &vaoID); + GL.glBindVertexArray(vaoID); + GL.glGenBuffers(1, &vertexBufferID); + GL.glGenBuffers(1, &indexBufferID); + GL.glBindVertexArray(0); + } + + public ~this() + { + GL.glDeleteBuffers(1, &vertexBufferID); + GL.glDeleteBuffers(1, &indexBufferID); + GL.glDeleteVertexArrays(1, &vaoID); + } + + public override void Draw() + { + GL.glDisable(GL.GL_CULL_FACE); + + GL.glBindVertexArray(vaoID); + + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBufferID); + GL.glEnableVertexAttribArray(0); + GL.glVertexAttribPointer(0, 2, GL.GL_FLOAT, GL.GL_FALSE, sizeof(Vertex), (void*)0); + GL.glEnableVertexAttribArray(1); + GL.glVertexAttribPointer(1, 2, GL.GL_FLOAT, GL.GL_FALSE, sizeof(Vertex), (void*)8); + GL.glEnableVertexAttribArray(2); + GL.glVertexAttribPointer(2, 4, GL.GL_UNSIGNED_BYTE, GL.GL_TRUE, sizeof(Vertex), (void*)16); + GL.glEnableVertexAttribArray(3); + GL.glVertexAttribPointer(3, 3, GL.GL_UNSIGNED_BYTE, GL.GL_TRUE, sizeof(Vertex), (void*)20); + GL.glBufferData(GL.GL_ARRAY_BUFFER, vertices.Count * sizeof(Vertex), vertices.Ptr, GL.GL_DYNAMIC_DRAW); + + GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBufferID); + GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices.Count * sizeof(uint32), indices.Ptr, GL.GL_DYNAMIC_DRAW); + + GL.glDrawElements(GL.GL_TRIANGLES, indices.Count, GL.GL_UNSIGNED_INT, (void*)0); + GL.glBindVertexArray(0); + + vertices.Clear(); + indices.Clear(); + } + + protected override void PushQuad(Vertex a, Vertex b, Vertex c, Vertex d) + { + uint32 count = (uint32)vertices.Count; + + vertices.Add(a); + vertices.Add(b); + vertices.Add(c); + vertices.Add(d); + + indices.Add(count + 0); + indices.Add(count + 1); + indices.Add(count + 2); + indices.Add(count + 0); + indices.Add(count + 2); + indices.Add(count + 3); + } + + protected override void PushTri(Vertex a, Vertex b, Vertex c) + { + uint32 count = (uint32)vertices.Count; + + vertices.Add(a); + vertices.Add(b); + vertices.Add(c); + + indices.Add(count + 0); + indices.Add(count + 1); + indices.Add(count + 2); + } + } +} diff --git a/src/PlatformLayer/SDL2PlatformLayer.bf b/src/PlatformLayer/SDL2/SDL2PlatformLayer.bf similarity index 74% rename from src/PlatformLayer/SDL2PlatformLayer.bf rename to src/PlatformLayer/SDL2/SDL2PlatformLayer.bf index 062e73f..dee6b20 100644 --- a/src/PlatformLayer/SDL2PlatformLayer.bf +++ b/src/PlatformLayer/SDL2/SDL2PlatformLayer.bf @@ -2,7 +2,7 @@ using SDL2; using System; using System.Diagnostics; -namespace Strawberry +namespace Strawberry.SDL2 { public class SDL2PlatformLayer : PlatformLayer { @@ -118,11 +118,6 @@ namespace Strawberry } } - static void* SdlGetProcAddress(StringView string) - { - return SDL.SDL_GL_GetProcAddress(string.ToScopeCStr!()); - } - public ~this() { delete gamepads; @@ -134,6 +129,11 @@ namespace Strawberry SDL.Quit(); } + static void* SdlGetProcAddress(StringView string) + { + return SDL.SDL_GL_GetProcAddress(string.ToScopeCStr!()); + } + public override bool Closed() { SDL.Event event; @@ -149,21 +149,12 @@ namespace Strawberry GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); GL.glUseProgram(glProgram); - float zNearPlane = 0; - float zFarPlane = 1000; - - float[16] mat = - .(2.0f / Game.Width, 0, 0, 0, - 0, 2.0f / Game.Height, 0, 0, - 0, 0, 1.0f / (zNearPlane - zFarPlane), zNearPlane / (zNearPlane - zFarPlane), - 0, 0, 0, 1); + Mat4x4 mat = Mat4x4.CreateOrthographic(Game.Width, Game.Height * 0.5f, 0, 1); + mat *= Mat4x4.CreateScale(.(1, -1, 1)); + mat *= Mat4x4.CreateTranslation(.(-1, 1, 0)); let loc = GL.glGetUniformLocation(glProgram, "u_matrix"); - GL.glUniformMatrix4fv(loc, 1, GL.GL_FALSE, &mat); - - Batcher b = scope Batcher(); - b.PushQuad(.(-40, -40), .(40, -40), .(40, 40), .(-40, 40), .Yellow); - b.Draw(); + GL.glUniformMatrix4fv(loc, 1, GL.GL_FALSE, &mat.Values); } public override void RenderEnd() @@ -219,73 +210,15 @@ namespace Strawberry else return val / 32768f; } - } - class SDL2Texture : Texture - { - private uint32 handle; - - public this(int width, int height, uint8* pixels) - : base(width, height, pixels) + public override Batcher CreateBatcher() { - GL.glGenTextures(1, &handle); - GL.glBindTexture(GL.GL_TEXTURE_2D, handle); - GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixels); + return new SDL2Batcher(); } - public ~this() + public override Shader CreateShader(ShaderDef def) { - GL.glDeleteTextures(1, &handle); - } - } - - class SDL2Shader : Shader - { - public uint vertexHandle; - public uint fragmentHandle; - - public this(ShaderDef def) - : base(def) - { - IsValid = true; - int32 logLen = 0; - char8[1024] log; - - vertexHandle = GL.glCreateShader(GL.GL_VERTEX_SHADER); - { - int32 len = (int32)def.Vertex.Length; - char8* data = def.Vertex.CStr(); - GL.glShaderSource(vertexHandle, 1, &data, &len); - GL.glCompileShader(vertexHandle); - GL.glGetShaderInfoLog(vertexHandle, 1024, &logLen, &log); - - if (logLen > 0) - { - Calc.Log(&log, logLen); - IsValid = false; - } - } - - fragmentHandle = GL.glCreateShader(GL.GL_FRAGMENT_SHADER); - { - int32 len = (int32)def.Fragment.Length; - char8* data = def.Fragment.CStr(); - GL.glShaderSource(fragmentHandle, 1, &data, &len); - GL.glCompileShader(fragmentHandle); - GL.glGetShaderInfoLog(fragmentHandle, 1024, &logLen, &log); - - if (logLen > 0) - { - Calc.Log(&log, logLen); - IsValid = false; - } - } - } - - public ~this() - { - GL.glDeleteShader(vertexHandle); - GL.glDeleteShader(fragmentHandle); + return new SDL2Shader(def); } } } diff --git a/src/PlatformLayer/SDL2/SDL2Shader.bf b/src/PlatformLayer/SDL2/SDL2Shader.bf new file mode 100644 index 0000000..ff992fd --- /dev/null +++ b/src/PlatformLayer/SDL2/SDL2Shader.bf @@ -0,0 +1,52 @@ +namespace Strawberry.SDL2 +{ + class SDL2Shader : Shader + { + public uint vertexHandle; + public uint fragmentHandle; + + public this(ShaderDef def) + : base(def) + { + IsValid = true; + int32 logLen = 0; + char8[1024] log; + + vertexHandle = GL.glCreateShader(GL.GL_VERTEX_SHADER); + { + int32 len = (int32)def.Vertex.Length; + char8* data = def.Vertex.CStr(); + GL.glShaderSource(vertexHandle, 1, &data, &len); + GL.glCompileShader(vertexHandle); + GL.glGetShaderInfoLog(vertexHandle, 1024, &logLen, &log); + + if (logLen > 0) + { + Calc.Log(&log, logLen); + IsValid = false; + } + } + + fragmentHandle = GL.glCreateShader(GL.GL_FRAGMENT_SHADER); + { + int32 len = (int32)def.Fragment.Length; + char8* data = def.Fragment.CStr(); + GL.glShaderSource(fragmentHandle, 1, &data, &len); + GL.glCompileShader(fragmentHandle); + GL.glGetShaderInfoLog(fragmentHandle, 1024, &logLen, &log); + + if (logLen > 0) + { + Calc.Log(&log, logLen); + IsValid = false; + } + } + } + + public ~this() + { + GL.glDeleteShader(vertexHandle); + GL.glDeleteShader(fragmentHandle); + } + } +} diff --git a/src/PlatformLayer/SDL2/SDL2Texture.bf b/src/PlatformLayer/SDL2/SDL2Texture.bf new file mode 100644 index 0000000..e9631b2 --- /dev/null +++ b/src/PlatformLayer/SDL2/SDL2Texture.bf @@ -0,0 +1,20 @@ +namespace Strawberry.SDL2 +{ + class SDL2Texture : Texture + { + private uint32 handle; + + public this(int width, int height, uint8* pixels) + : base(width, height, pixels) + { + GL.glGenTextures(1, &handle); + GL.glBindTexture(GL.GL_TEXTURE_2D, handle); + GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixels); + } + + public ~this() + { + GL.glDeleteTextures(1, &handle); + } + } +} diff --git a/src/PlatformLayer/Shader.bf b/src/PlatformLayer/Shader.bf new file mode 100644 index 0000000..37d7c13 --- /dev/null +++ b/src/PlatformLayer/Shader.bf @@ -0,0 +1,12 @@ +namespace Strawberry +{ + public abstract class Shader + { + public bool IsValid { get; protected set; } + + public this(ShaderDef def) + { + + } + } +} diff --git a/src/PlatformLayer/ShaderDef.bf b/src/PlatformLayer/ShaderDef.bf new file mode 100644 index 0000000..529d957 --- /dev/null +++ b/src/PlatformLayer/ShaderDef.bf @@ -0,0 +1,27 @@ +using System; + +namespace Strawberry +{ + public struct ShaderDef + { + public String Vertex; + public String Fragment; + + public this(String vertex, String fragment) + { + Vertex = vertex; + Fragment = fragment; + } + + public this(String[2] str) + { + Vertex = str[0]; + Fragment = str[1]; + } + + static implicit public operator ShaderDef(String[2] str) + { + return ShaderDef(str); + } + } +} diff --git a/src/PlatformLayer/Texture.bf b/src/PlatformLayer/Texture.bf new file mode 100644 index 0000000..8b40433 --- /dev/null +++ b/src/PlatformLayer/Texture.bf @@ -0,0 +1,14 @@ +namespace Strawberry +{ + public abstract class Texture + { + public int Width { get; private set; } + public int Height { get; private set; } + + public virtual this(int width, int height, uint8* pixels) + { + Width = width; + Height = height; + } + } +} diff --git a/src/PlatformLayer/Vertex.bf b/src/PlatformLayer/Vertex.bf new file mode 100644 index 0000000..90e9c54 --- /dev/null +++ b/src/PlatformLayer/Vertex.bf @@ -0,0 +1,22 @@ +using System; + +namespace Strawberry +{ + [Ordered, Packed, CRepr] + public struct Vertex + { + public Vector Position; + public Vector TexCoord; + public Color Color; + public (uint8, uint8, uint8) Mode; + + static public Vertex Shape(Vector pos, Color color) + { + Vertex v = Vertex(); + v.Position = pos; + v.Color = color; + v.Mode = (0, 0, 255); + return v; + } + } +} diff --git a/src/Static/Console.bf b/src/Static/Console.bf index fa675de..9c34fb6 100644 --- a/src/Static/Console.bf +++ b/src/Static/Console.bf @@ -147,8 +147,8 @@ namespace Strawberry { if (enabled && Open) { - Draw.Rect(0, 0, Game.Width, Game.Height, .Black * 0.6f); - Draw.Rect(0, Game.Height - 14, Game.Width, 14, .Black * 0.6f); + Game.Batcher.Rect(0, 0, Game.Width, Game.Height, .Black * 0.6f); + Game.Batcher.Rect(0, Game.Height - 14, Game.Width, 14, .Black * 0.6f); //Entry if (entry.Length > 0) @@ -168,8 +168,8 @@ namespace Strawberry if (row > 0) pos.Y -= 4; - Draw.Text(font, str, pos + .Down, .Black); - Draw.Text(font, str, pos, color); + //Draw.Text(font, str, pos + .Down, .Black); + //Draw.Text(font, str, pos, color); } static private int MessageRows => (int)Math.Ceiling((Game.Height - 14) / 10f); diff --git a/src/Static/Draw.bf b/src/Static/Draw.bf deleted file mode 100644 index f967df6..0000000 --- a/src/Static/Draw.bf +++ /dev/null @@ -1,161 +0,0 @@ -using SDL2; -using System; -using System.Collections; - -namespace Strawberry -{ - static public class Draw - { - static public Point Camera => cameraStack.Count > 0 ? cameraStack.Back : Point.Zero; - - static private List cameraStack = new List() ~ delete _; - - static public void PushCamera(Point camera, bool relative = true) - { - if (relative) - cameraStack.Add(Camera + camera); - else - cameraStack.Add(camera); - } - - static public void PopCamera() - { - if (cameraStack.Count == 0) - Runtime.FatalError("Cannot Pop empty Camera Stack!"); - cameraStack.PopBack(); - } - - static public void Rect(int x, int y, int w, int h, Color color) - { - //SDL.SetRenderDrawBlendMode(Game.Renderer, .Blend); - //SDL.SetRenderDrawColor(Game.Renderer, color.R, color.G, color.B, color.A); - //SDL.RenderFillRect(Game.Renderer, &SDL.Rect((int32)(x - Camera.X), (int32)(y - Camera.Y), (int32)w, (int32)h)); - } - - static public void Rect(Rect rect, Color color) - { - Rect(rect.X, rect.Y, rect.Width, rect.Height, color); - } - - static public void HollowRect(int x, int y, int w, int h, Color color) - { - //SDL.SetRenderDrawBlendMode(Game.Renderer, .Blend); - //SDL.SetRenderDrawColor(Game.Renderer, color.R, color.G, color.B, color.A); - //SDL.RenderDrawRect(Game.Renderer, &SDL.Rect((int32)(x - Camera.X), (int32)(y - Camera.Y), (int32)w, (int32)h)); - } - - static public void HollowRect(Rect rect, Color color) - { - HollowRect(rect.X, rect.Y, rect.Width, rect.Height, color); - } - - static public void Line(Point from, Point to, Color color) - { - let fromn = (Point)(from - Camera); - let ton = (Point)(to - Camera); - - //SDL.SetRenderDrawBlendMode(Game.Renderer, .Blend); - //SDL.SetRenderDrawColor(Game.Renderer, color.R, color.G, color.B, color.A); - //SDL.RenderDrawLine(Game.Renderer, (int32)fromn.X, (int32)fromn.Y, (int32)ton.X, (int32)ton.Y); - } - - static public void Circle(Point at, float radius, Color color, int steps = 16) - { - let add = at - Camera; - - SDL.Point[] points = scope SDL.Point[steps + 1]; - points[0] = SDL.Point((int32)(radius + add.X), (int32)add.Y); - points[steps] = points[0]; - float slice = Calc.Circle / steps; - - for (int i = 1; i < steps; i++) - { - points[i] = SDL.Point( - (int32)(Math.Round(Math.Cos(slice * i) * radius) + add.X), - (int32)(Math.Round(Math.Sin(slice * i) * radius) + add.Y) - ); - } - - //SDL.SetRenderDrawBlendMode(Game.Renderer, .Blend); - //SDL.SetRenderDrawColor(Game.Renderer, color.R, color.G, color.B, color.A); - //SDL.RenderDrawLines(Game.Renderer, &points[0], (int32)steps + 1); - } - - static public void Sprite(Sprite sprite, int frame, Point position) - { - SDL.Rect src = Strawberry.Rect(0, 0, sprite.Width, sprite.Height); - SDL.Rect dst = Strawberry.Rect(position.X - Camera.X, position.Y - Camera.Y, sprite.Width, sprite.Height); - - //SDL.SetTextureBlendMode(sprite[frame].Texture, .Blend); - //SDL.RenderCopy(Game.Renderer, sprite[frame].Texture, &src, &dst); - } - - static public void Sprite(Sprite sprite, int frame, Point position, Point origin) - { - SDL.Point cnt = origin; - SDL.Rect src = Strawberry.Rect(0, 0, sprite.Width, sprite.Height); - SDL.Rect dst = Strawberry.Rect(position.X - origin.X - Camera.X, position.Y - origin.Y - Camera.Y, sprite.Width, sprite.Height); - - //SDL.SetTextureBlendMode(sprite[frame].Texture, .Blend); - //SDL.RenderCopyEx(Game.Renderer, sprite[frame].Texture, &src, &dst, 0, &cnt, .None); - } - - static public void Sprite(Sprite sprite, int frame, Point position, Point origin, float rotation) - { - SDL.Point cnt = origin; - SDL.Rect src = Strawberry.Rect(0, 0, sprite.Width, sprite.Height); - SDL.Rect dst = Strawberry.Rect(position.X - origin.X - Camera.X, position.Y - origin.Y - Camera.Y, sprite.Width, sprite.Height); - - //SDL.SetTextureBlendMode(sprite[frame].Texture, .Blend); - //SDL.RenderCopyEx(Game.Renderer, sprite[frame].Texture, &src, &dst, rotation, &cnt, .None); - } - - static public void SpriteCentered(Sprite sprite, int frame, Point position) - { - Point origin = .(sprite.Width/2, sprite.Height/2); - SDL.Point cnt = origin; - SDL.Rect src = Strawberry.Rect(0, 0, sprite.Width, sprite.Height); - SDL.Rect dst = Strawberry.Rect(position.X - origin.X - Camera.X, position.Y - origin.Y - Camera.Y, sprite.Width, sprite.Height); - - //SDL.SetTextureBlendMode(sprite[frame].Texture, .Blend); - //SDL.RenderCopyEx(Game.Renderer, sprite[frame].Texture, &src, &dst, 0, &cnt, .None); - } - - static public void SpriteCentered(Sprite sprite, int frame, Point position, Color color) - { - Point origin = .(sprite.Width/2, sprite.Height/2); - SDL.Point cnt = origin; - SDL.Rect src = Strawberry.Rect(0, 0, sprite.Width, sprite.Height); - SDL.Rect dst = Strawberry.Rect(position.X - origin.X - Camera.X, position.Y - origin.Y - Camera.Y, sprite.Width, sprite.Height); - - SDL.SetTextureBlendMode(sprite[frame].Texture, .Blend); - SDL.SetTextureColorMod(sprite[frame].Texture, color.R, color.G, color.B); - SDL.SetTextureAlphaMod(sprite[frame].Texture, color.A); - //SDL.RenderCopyEx(Game.Renderer, sprite[frame].Texture, &src, &dst, 0, &cnt, .None); - } - - static public void SpriteCentered(Sprite sprite, int frame, Point position, float rotation) - { - Point origin = .(sprite.Width/2, sprite.Height/2); - SDL.Point cnt = origin; - SDL.Rect src = Strawberry.Rect(0, 0, sprite.Width, sprite.Height); - SDL.Rect dst = Strawberry.Rect(position.X - origin.X - Camera.X, position.Y - origin.Y - Camera.Y, sprite.Width, sprite.Height); - - SDL.SetTextureBlendMode(sprite[frame].Texture, .Blend); - //SDL.RenderCopyEx(Game.Renderer, sprite[frame].Texture, &src, &dst, rotation, &cnt, .None); - } - - static public void Text(SDL2.SDLTTF.Font* font, String text, Point position, Color color) - { - //SDL.SetRenderDrawColor(Game.Renderer, color.R, color.G, color.B, color.A); - let surface = SDLTTF.RenderUTF8_Solid(font, text, color); - //let texture = SDL.CreateTextureFromSurface(Game.Renderer, surface); - - SDL.Rect srcRect = .(0, 0, surface.w, surface.h); - SDL.Rect destRect = .((int32)position.X, (int32)position.Y, surface.w, surface.h); - //SDL.RenderCopy(Game.Renderer, texture, &srcRect, &destRect); - SDL.FreeSurface(surface); - //SDL.DestroyTexture(texture); - } - } -} diff --git a/src/Struct/Matrix.bf b/src/Struct/Mat3x2.bf similarity index 83% rename from src/Struct/Matrix.bf rename to src/Struct/Mat3x2.bf index b088bc1..c42efe2 100644 --- a/src/Struct/Matrix.bf +++ b/src/Struct/Mat3x2.bf @@ -10,9 +10,9 @@ namespace Strawberry */ [Ordered, Packed, CRepr] - public struct Matrix + public struct Mat3x2 { - static public readonly Matrix Identity = Matrix(1, 0, 0, 1, 0, 0); + static public readonly Mat3x2 Identity = Mat3x2(1, 0, 0, 1, 0, 0); public float[6] Values = .(0, 0, 0, 0, 0, 0); @@ -153,7 +153,7 @@ namespace Strawberry } } - public Result Inverse + public Result Inverse { get => Invert(this); @@ -165,70 +165,70 @@ namespace Strawberry //Static Helpers - public static Matrix CreateTranslation(Vector position) + public static Mat3x2 CreateTranslation(Vector position) { - return Matrix( + return Mat3x2( 1, 0, 0, 1, position.X, position.Y ); } - public static Matrix CreateScale(Vector scale) + public static Mat3x2 CreateScale(Vector scale) { - return Matrix( + return Mat3x2( scale.X, 0, 0, scale.Y, 0, 0 ); } - public static Matrix CreateScale(Vector scale, Vector origin) + public static Mat3x2 CreateScale(Vector scale, Vector origin) { float tx = origin.X * (1 - scale.X); float ty = origin.Y * (1 - scale.Y); - return Matrix( + return Mat3x2( scale.X, 0, 0, scale.Y, tx, ty ); } - public static Matrix CreateScale(float scale) + public static Mat3x2 CreateScale(float scale) { - return Matrix( + return Mat3x2( scale, 0, 0, scale, 0, 0 ); } - public static Matrix CreateScale(float scale, Vector origin) + public static Mat3x2 CreateScale(float scale, Vector origin) { float tx = origin.X * (1 - scale); float ty = origin.Y * (1 - scale); - return Matrix( + return Mat3x2( scale, 0, 0, scale, tx, ty ); } - public static Matrix CreateSkew(float radiansX, float radiansY) + public static Mat3x2 CreateSkew(float radiansX, float radiansY) { float xTan = (float)Math.Tan(radiansX); float yTan = (float)Math.Tan(radiansY); - return Matrix( + return Mat3x2( 1, yTan, xTan, 1, 0, 0 ); } - public static Matrix CreateSkew(float radiansX, float radiansY, Vector origin) + public static Mat3x2 CreateSkew(float radiansX, float radiansY, Vector origin) { float xTan = (float)Math.Tan(radiansX); float yTan = (float)Math.Tan(radiansY); @@ -236,14 +236,14 @@ namespace Strawberry float tx = -origin.Y * xTan; float ty = -origin.X * yTan; - return Matrix( + return Mat3x2( 1, yTan, xTan, 1, tx, ty ); } - public static Matrix CreateRotation(float radians) + public static Mat3x2 CreateRotation(float radians) { let rad = (float)Math.IEEERemainder(radians, Math.PI_f * 2); @@ -282,14 +282,14 @@ namespace Strawberry s = (float)Math.Sin(rad); } - return Matrix( + return Mat3x2( c, s, -s, c, 0, 0 ); } - public static Matrix CreateRotation(float radians, Vector origin) + public static Mat3x2 CreateRotation(float radians, Vector origin) { let rad = (float)Math.IEEERemainder(radians, Math.PI_f * 2); @@ -331,7 +331,7 @@ namespace Strawberry float x = origin.X * (1 - c) + origin.Y * s; float y = origin.Y * (1 - c) - origin.X * s; - return Matrix( + return Mat3x2( c, s, -s, c, x, y @@ -361,7 +361,7 @@ namespace Strawberry return (M11 * M22) - (M21 * M12); } - public static Result Invert(Matrix matrix) + public static Result Invert(Mat3x2 matrix) { let det = (matrix.M11 * matrix.M22) - (matrix.M21 * matrix.M12); @@ -370,7 +370,7 @@ namespace Strawberry let invDet = 1.0f / det; - return Matrix( + return Mat3x2( matrix.M22 * invDet, -matrix.M12 * invDet, @@ -382,9 +382,9 @@ namespace Strawberry ); } - public static Matrix Lerp(Matrix a, Matrix b, float t) + public static Mat3x2 Lerp(Mat3x2 a, Mat3x2 b, float t) { - return Matrix( + return Mat3x2( a.M11 + (b.M11 - a.M11) * t, a.M12 + (b.M12 - a.M12) * t, @@ -396,36 +396,36 @@ namespace Strawberry ); } - public static Matrix Negate(Matrix mat) + public static Mat3x2 Negate(Mat3x2 mat) { - return Matrix( + return Mat3x2( -mat.M11, -mat.M12, -mat.M21, -mat.M22, -mat.M31, -mat.M32 ); } - public static Matrix Add(Matrix a, Matrix b) + public static Mat3x2 Add(Mat3x2 a, Mat3x2 b) { - return Matrix( + return Mat3x2( a.M11 + b.M11, a.M12 + b.M12, a.M21 + b.M21, a.M22 + b.M22, a.M31 + b.M31, a.M32 + b.M32 ); } - public static Matrix Subtract(Matrix a, Matrix b) + public static Mat3x2 Subtract(Mat3x2 a, Mat3x2 b) { - return Matrix( + return Mat3x2( a.M11 - b.M11, a.M12 - b.M12, a.M21 - b.M21, a.M22 - b.M22, a.M31 - b.M31, a.M32 - b.M32 ); } - public static Matrix Multiply(Matrix a, Matrix b) + public static Mat3x2 Multiply(Mat3x2 a, Mat3x2 b) { - return Matrix( + return Mat3x2( a.M11 * b.M11 + a.M12 * b.M21, a.M11 * b.M12 + a.M12 * b.M22, @@ -437,9 +437,9 @@ namespace Strawberry ); } - public static Matrix Multiply(Matrix a, float scale) + public static Mat3x2 Multiply(Mat3x2 a, float scale) { - return Matrix( + return Mat3x2( a.M11 * scale, a.M12 * scale, a.M21 * scale, a.M22 * scale, a.M31 * scale, a.M32 * scale @@ -448,36 +448,36 @@ namespace Strawberry // Operators - public static Matrix operator -(Matrix mat) + public static Mat3x2 operator -(Mat3x2 mat) { - return Matrix( + return Mat3x2( -mat.M11, -mat.M12, -mat.M21, -mat.M22, -mat.M31, -mat.M32 ); } - public static Matrix operator +(Matrix a, Matrix b) + public static Mat3x2 operator +(Mat3x2 a, Mat3x2 b) { - return Matrix( + return Mat3x2( a.M11 + b.M11, a.M12 + b.M12, a.M21 + b.M21, a.M22 + b.M22, a.M31 + b.M31, a.M32 + b.M32 ); } - public static Matrix operator -(Matrix a, Matrix b) + public static Mat3x2 operator -(Mat3x2 a, Mat3x2 b) { - return Matrix( + return Mat3x2( a.M11 - b.M11, a.M12 - b.M12, a.M21 - b.M21, a.M22 - b.M22, a.M31 - b.M31, a.M32 - b.M32 ); } - public static Matrix operator *(Matrix a, Matrix b) + public static Mat3x2 operator *(Mat3x2 a, Mat3x2 b) { - return Matrix( + return Mat3x2( a.M11 * b.M11 + a.M12 * b.M21, a.M11 * b.M12 + a.M12 * b.M22, @@ -489,16 +489,16 @@ namespace Strawberry ); } - public static Matrix operator *(Matrix mat, float scale) + public static Mat3x2 operator *(Mat3x2 mat, float scale) { - return Matrix( + return Mat3x2( mat.M11 * scale, mat.M12 * scale, mat.M21 * scale, mat.M22 * scale, mat.M31 * scale, mat.M32 * scale ); } - public static bool operator ==(Matrix a, Matrix b) + public static bool operator ==(Mat3x2 a, Mat3x2 b) { return (a.M11 == b.M11 && a.M22 == b.M22 && // Check diagonal element first for early out. a.M12 == b.M12 && @@ -506,7 +506,7 @@ namespace Strawberry a.M31 == b.M31 && a.M32 == b.M32); } - public static bool operator !=(Matrix a, Matrix b) + public static bool operator !=(Mat3x2 a, Mat3x2 b) { return (a.M11 != b.M11 || a.M12 != b.M12 || a.M21 != b.M21 || a.M22 != b.M22 || diff --git a/src/Struct/Mat4x4.bf b/src/Struct/Mat4x4.bf new file mode 100644 index 0000000..4caf8cc --- /dev/null +++ b/src/Struct/Mat4x4.bf @@ -0,0 +1,327 @@ +using System; + +namespace Strawberry +{ + /* + Based on Matrix3x2.cs by Microsoft, under MIT license + Source: https://github.com/microsoft/referencesource/blob/master/System.Numerics/System/Numerics/Matrix4x4.cs + + Copyright (c) Microsoft. All rights reserved. + Licensed under the MIT license. + */ + + + [Ordered, Packed, CRepr] + public struct Mat4x4 + { + static public readonly Mat4x4 Identity = Mat4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + + public float[16] Values = .(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + public this(float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44) + { + Values = .(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44); + } + + public this() + { + + } + + public float M11 + { + get => Values[0]; + set mut => Values[0] = value; + } + + public float M12 + { + get => Values[1]; + set mut => Values[1] = value; + } + + public float M13 + { + get => Values[2]; + set mut => Values[2] = value; + } + + public float M14 + { + get => Values[3]; + set mut => Values[3] = value; + } + + public float M21 + { + get => Values[4]; + set mut => Values[4] = value; + } + + public float M22 + { + get => Values[5]; + set mut => Values[5] = value; + } + + public float M23 + { + get => Values[6]; + set mut => Values[6] = value; + } + + public float M24 + { + get => Values[7]; + set mut => Values[7] = value; + } + + public float M31 + { + get => Values[8]; + set mut => Values[8] = value; + } + + public float M32 + { + get => Values[9]; + set mut => Values[9] = value; + } + + public float M33 + { + get => Values[10]; + set mut => Values[10] = value; + } + + public float M34 + { + get => Values[11]; + set mut => Values[11] = value; + } + + public float M41 + { + get => Values[12]; + set mut => Values[12] = value; + } + + public float M42 + { + get => Values[13]; + set mut => Values[13] = value; + } + + public float M43 + { + get => Values[14]; + set mut => Values[14] = value; + } + + public float M44 + { + get => Values[15]; + set mut => Values[15] = value; + } + + static public Mat4x4 CreateTranslation(Vector3 pos) + { + return .( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + pos.X, pos.Y, pos.Z, 1 + ); + } + + public static Mat4x4 CreateScale(Vector3 scale) + { + return .( + scale.X, 0, 0, 0, + 0, scale.Y, 0, 0, + 0, 0, scale.Z, 0, + 0, 0, 0, 1 + ); + } + + public static Mat4x4 CreateScale(Vector3 scale, Vector3 origin) + { + float tx = origin.X * (1 - scale.X); + float ty = origin.Y * (1 - scale.Y); + float tz = origin.Z * (1 - scale.Z); + + return .( + scale.X, 0, 0, 0, + 0, scale.Y, 0, 0, + 0, 0, scale.Z, 0, + tx, ty, tz, 1 + ); + } + + public static Mat4x4 CreateRotationX(float radians) + { + + float c = (float)Math.Cos(radians); + float s = (float)Math.Sin(radians); + + // [ 1 0 0 0 ] + // [ 0 c s 0 ] + // [ 0 -s c 0 ] + // [ 0 0 0 1 ] + return .( + 1, 0, 0, 0, + 0, c, s, 0, + 0, -s, c, 0, + 0, 0, 0, 1 + ); + } + + public static Mat4x4 CreateRotationX(float radians, Vector3 origin) + { + float c = (float)Math.Cos(radians); + float s = (float)Math.Sin(radians); + + float y = origin.Y * (1 - c) + origin.Z * s; + float z = origin.Z * (1 - c) - origin.Y * s; + + // [ 1 0 0 0 ] + // [ 0 c s 0 ] + // [ 0 -s c 0 ] + // [ 0 y z 1 ] + return .( + 1, 0, 0, 0, + 0, c, s, 0, + 0, -s, c, 0, + 0, y, z, 1 + ); + } + + public static Mat4x4 CreateRotationY(float radians) + { + float c = (float)Math.Cos(radians); + float s = (float)Math.Sin(radians); + + // [ c 0 -s 0 ] + // [ 0 1 0 0 ] + // [ s 0 c 0 ] + // [ 0 0 0 1 ] + return .( + c, 0, -s, 0, + 0, 1, 0, 0, + s, 0, c, 0, + 0, 0, 0, 1 + ); + } + + public static Mat4x4 CreateRotationY(float radians, Vector3 origin) + { + float c = (float)Math.Cos(radians); + float s = (float)Math.Sin(radians); + + float x = origin.X * (1 - c) - origin.Z * s; + float z = origin.Z * (1 - c) + origin.X * s; + + // [ c 0 -s 0 ] + // [ 0 1 0 0 ] + // [ s 0 c 0 ] + // [ x 0 z 1 ] + return .( + c, 0, -s, 0, + 0, 1, 0, 0, + s, 0, c, 0, + x, 0, z, 1 + ); + } + + public static Mat4x4 CreateRotationZ(float radians) + { + float c = (float)Math.Cos(radians); + float s = (float)Math.Sin(radians); + + // [ c s 0 0 ] + // [ -s c 0 0 ] + // [ 0 0 1 0 ] + // [ 0 0 0 1 ] + return .( + c, s, 0, 0, + -s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ); + } + + public static Mat4x4 CreateRotationZ(float radians, Vector3 centerPoint) + { + float c = (float)Math.Cos(radians); + float s = (float)Math.Sin(radians); + + float x = centerPoint.X * (1 - c) + centerPoint.Y * s; + float y = centerPoint.Y * (1 - c) - centerPoint.X * s; + + // [ c s 0 0 ] + // [ -s c 0 0 ] + // [ 0 0 1 0 ] + // [ x y 0 1 ] + return .( + c, s, 0, 0, + -s, c, 0, 0, + 0, 0, 1, 0, + x, y, 0, 1 + ); + } + + public static Mat4x4 CreateOrthographic(float width, float height, float zNearPlane, float zFarPlane) + { + return .( + 2 / width, 0, 0, 0, + 0, 1 / height, 0, 0, + 0, 0, 1 / (zNearPlane - zFarPlane), 0, + 0, zNearPlane / (zNearPlane - zFarPlane), 0, 1 + ); + } + + static public implicit operator Mat4x4(Mat3x2 mat) + { + return Mat4x4( + mat.M11, mat.M12, 0, 0, + mat.M21, mat.M22, 0, 0, + 0, 0, 1, 0, + mat.M31, mat.M32, 0, 1 + ); + } + + static public Mat4x4 operator *(Mat4x4 a, Mat4x4 b) + { + Mat4x4 m = .(); + + // First row + m.M11 = a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31 + a.M14 * b.M41; + m.M12 = a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32 + a.M14 * b.M42; + m.M13 = a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33 + a.M14 * b.M43; + m.M14 = a.M11 * b.M14 + a.M12 * b.M24 + a.M13 * b.M34 + a.M14 * b.M44; + + // Second row + m.M21 = a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31 + a.M24 * b.M41; + m.M22 = a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32 + a.M24 * b.M42; + m.M23 = a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33 + a.M24 * b.M43; + m.M24 = a.M21 * b.M14 + a.M22 * b.M24 + a.M23 * b.M34 + a.M24 * b.M44; + + // Third row + m.M31 = a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31 + a.M34 * b.M41; + m.M32 = a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32 + a.M34 * b.M42; + m.M33 = a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33 + a.M34 * b.M43; + m.M34 = a.M31 * b.M14 + a.M32 * b.M24 + a.M33 * b.M34 + a.M34 * b.M44; + + // Fourth row + m.M41 = a.M41 * b.M11 + a.M42 * b.M21 + a.M43 * b.M31 + a.M44 * b.M41; + m.M42 = a.M41 * b.M12 + a.M42 * b.M22 + a.M43 * b.M32 + a.M44 * b.M42; + m.M43 = a.M41 * b.M13 + a.M42 * b.M23 + a.M43 * b.M33 + a.M44 * b.M43; + m.M44 = a.M41 * b.M14 + a.M42 * b.M24 + a.M43 * b.M34 + a.M44 * b.M44; + + return m; + } + } +} diff --git a/src/Struct/Vector3.bf b/src/Struct/Vector3.bf new file mode 100644 index 0000000..6c4c1bf --- /dev/null +++ b/src/Struct/Vector3.bf @@ -0,0 +1,16 @@ +namespace Strawberry +{ + public struct Vector3 + { + public float X; + public float Y; + public float Z; + + public this(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + } +}