diff --git a/src/Core/Entity.bf b/src/Core/Entity.bf index b421143..fc1ffad 100644 --- a/src/Core/Entity.bf +++ b/src/Core/Entity.bf @@ -301,6 +301,26 @@ namespace Strawberry return SceneHitbox.Intersects(rect); } + public bool Check(Scene scene) + { + return scene.SolidGrid != null && Check(scene.SolidGrid); + } + + public bool Check(Scene scene, Point offset) + { + return scene.SolidGrid != null && Check(scene.SolidGrid, offset); + } + + public bool Check(Grid grid) + { + return grid.Check(SceneHitbox); + } + + public bool Check(Grid grid, Point offset) + { + return grid.Check(SceneHitbox + offset); + } + public bool Check(Entity other) { return other.Collidable && SceneHitbox.Intersects(other.SceneHitbox); diff --git a/src/Core/Scene.bf b/src/Core/Scene.bf index 34ef919..2d96a61 100644 --- a/src/Core/Scene.bf +++ b/src/Core/Scene.bf @@ -6,6 +6,7 @@ namespace Strawberry public class Scene { public float TimeStarted { get; private set; } + public Grid SolidGrid; private List entities; private HashSet toRemove; @@ -20,6 +21,9 @@ namespace Strawberry public ~this() { + if (SolidGrid != null) + delete SolidGrid; + for (var e in entities) if (e.DeleteOnRemove) delete e; diff --git a/src/JSON/JSON.bf b/src/JSON/JSON.bf index e7445ba..97e336d 100644 --- a/src/JSON/JSON.bf +++ b/src/JSON/JSON.bf @@ -14,9 +14,12 @@ namespace Strawberry public enum Types { Null, Bool, Number, String, Array, Object }; public Types Type { get; private set; } - public bool Bool; - public float Number; - public String String; + public readonly bool Bool; + public readonly float Number; + public readonly String String; + + public int Int => (int)Number; + public char8 Char => String[0]; private List array; private Dictionary children; @@ -102,6 +105,15 @@ namespace Strawberry } } + public int ArrayLength + { + get + { + Runtime.Assert(Type == .Array); + return array.Count; + } + } + public void ArrayPush(JSON json) { Runtime.Assert(Type == .Array); @@ -124,6 +136,15 @@ namespace Strawberry array.Clear(); } + public List.Enumerator ArrayEnumerator + { + get + { + Runtime.Assert(Type == .Array); + return array.GetEnumerator(); + } + } + // Object public JSON this[String key] @@ -157,6 +178,33 @@ namespace Strawberry delete children.GetAndRemove(key).Value.value; } + public Dictionary.Enumerator ObjectEnumerator + { + get + { + Runtime.Assert(Type == .Object); + return children.GetEnumerator(); + } + } + + public Dictionary.KeyEnumerator ObjectKeyEnumerator + { + get + { + Runtime.Assert(Type == .Object); + return children.Keys; + } + } + + public Dictionary.ValueEnumerator ObjectValueEnumerator + { + get + { + Runtime.Assert(Type == .Object); + return children.Values; + } + } + // Operators static public implicit operator JSON(bool val) @@ -179,6 +227,13 @@ namespace Strawberry return new JSON(val); } + static public implicit operator JSON(char8 val) + { + let str = scope String(); + str.Concat(val); + return new JSON(str); + } + static public implicit operator bool(JSON json) { Runtime.Assert(json.Type == .Bool); @@ -203,6 +258,12 @@ namespace Strawberry return json.String; } + static public implicit operator char8(JSON json) + { + Runtime.Assert(json.Type == .String); + return json.String[0]; + } + static public JSON CreateArray() { let json = new JSON(.Array); diff --git a/src/Physics/Actor.bf b/src/Physics/Actor.bf index 0811d73..f4d4308 100644 --- a/src/Physics/Actor.bf +++ b/src/Physics/Actor.bf @@ -17,7 +17,7 @@ namespace Strawberry public bool GroundCheck(int distance = 1) { - return Check(.(0, distance)) || CheckOutside(.(0, distance)); + return Check(.(0, distance)) || Check(Scene, .(0, distance)) || CheckOutside(.(0, distance)); } public virtual bool IsRiding(Solid solid) @@ -89,6 +89,20 @@ namespace Strawberry return true; } + if (Check(Scene.SolidGrid, .(sign, 0))) + { + let c = Collision( + Point.Right * sign, + Math.Abs(amount), + Math.Abs(amount - move), + null, + pusher + ); + + onCollide?.Invoke(c); + return true; + } + X += sign; move -= sign; } @@ -120,6 +134,20 @@ namespace Strawberry return true; } + if (Check(Scene.SolidGrid, .(0, sign))) + { + let c = Collision( + Point.Right * sign, + Math.Abs(amount), + Math.Abs(amount - move), + null, + pusher + ); + + onCollide?.Invoke(c); + return true; + } + Y += sign; move -= sign; } diff --git a/src/Physics/Grid.bf b/src/Physics/Grid.bf new file mode 100644 index 0000000..92572e2 --- /dev/null +++ b/src/Physics/Grid.bf @@ -0,0 +1,121 @@ +using System; + +namespace Strawberry +{ + public class Grid + { + public Point CellSize; + public Point Offset; + + private char8[,] contents ~ delete _; + + public this(int cellWidth, int cellHeight, int cellsX, int cellsY, int offsetX = 0, int offsetY = 0) + { + CellSize = .(cellWidth, cellHeight); + Offset = .(offsetX, offsetY); + + contents = new char8[cellsX, cellsY]; + } + + public this(JSON ogmoJson) + : this(ogmoJson["gridCellWidth"], ogmoJson["gridCellHeight"], ogmoJson["gridCellsX"], ogmoJson["gridCellsY"], ogmoJson["offsetX"], ogmoJson["offsetY"]) + { + var x = 0; + var y = 0; + let data = ogmoJson["grid"]; + + for (let i < data.ArrayLength) + { + contents[x, y] = data[i]; + + x++; + if (x >= contents.GetLength(0)) + { + x = 0; + y++; + } + } + } + + public char8 this[int x, int y] + { + [Inline] + get + { + return contents[x, y]; + } + + [Inline] + set + { + contents[x, y] = value; + } + } + + public char8 this[Point p] + { + [Inline] + get + { + return contents[p.X, p.Y]; + } + + [Inline] + set + { + contents[p.X, p.Y] = value; + } + } + + public int CellsX => contents.GetLength(0); + public int CellsY => contents.GetLength(1); + + public bool IsInBounds(Point p) + { + return p.X >= 0 && p.Y >= 0 && p.X < CellsX && p.Y < CellsY; + } + + public bool Check(Entity entity) + { + return Check(entity.SceneHitbox); + } + + public bool Check(Rect rect) + { + Point from = .( + (int)Math.Floor((rect.X - Offset.X) / (float)CellSize.X), + (int)Math.Floor((rect.Y - Offset.Y) / (float)CellSize.Y) + ); + Point to = .( + (int)Math.Ceiling((rect.Right - Offset.X) / (float)CellSize.X), + (int)Math.Ceiling((rect.Bottom - Offset.Y) / (float)CellSize.Y) + ); + + for (int x = from.X; x < to.X; x++) + { + for (int y = from.Y; y < to.Y; y++) + { + let p = Point(x, y); + if (IsInBounds(p) && this[p] != '0') + return true; + } + } + + return false; + } + + public bool Check(Point point) + { + Point check = (point - Offset) / CellSize; + return IsInBounds(check) && this[check] != '0'; + } + + public void Draw(Color color) + { + for (let x < CellsX) + for (let y < CellsY) + if (this[x, y] != '0') + Draw.Rect(Rect(x, y, 1, 1) * CellSize + Offset, color); + } + } +} diff --git a/src/Physics/JumpThru.bf b/src/Physics/JumpThru.bf index d508a06..1c294eb 100644 --- a/src/Physics/JumpThru.bf +++ b/src/Physics/JumpThru.bf @@ -9,6 +9,12 @@ namespace Strawberry Hitbox = Rect(0, 0, width, 2); } + public this(JSON json) + : this(.(json), json["width"]) + { + + } + public override void MoveExactX(int amount) { if (Collidable) diff --git a/src/Struct/Point.bf b/src/Struct/Point.bf index 605eca6..178d546 100644 --- a/src/Struct/Point.bf +++ b/src/Struct/Point.bf @@ -27,6 +27,12 @@ namespace Strawberry Y = y; } + public this(JSON json) + : this(json["x"], json["y"]) + { + + } + public override void ToString(String strBuffer) { strBuffer.Set("Point [ "); @@ -61,9 +67,19 @@ namespace Strawberry return Point(a.X * b, a.Y * b); } + static public Point operator*(Point a, Point b) + { + return Point(a.X * b.X, a.Y * b.Y); + } + static public Point operator/(Point a, int b) { return Point(a.X / b, a.Y / b); } + + static public Point operator/(Point a, Point b) + { + return Point(a.X / b.X, a.Y / b.Y); + } } } diff --git a/src/Struct/Rect.bf b/src/Struct/Rect.bf index 67de538..21b9f2e 100644 --- a/src/Struct/Rect.bf +++ b/src/Struct/Rect.bf @@ -22,6 +22,12 @@ namespace Strawberry Height = height; } + public this(JSON json) + : this(json["x"], json["y"], json["width"], json["height"]) + { + + } + public int Left { [Inline] @@ -82,6 +88,8 @@ namespace Strawberry } } + public Point Origin => .(X, Y); + public Rect MirrorX(int axis = 0) { var rect = this; @@ -138,5 +146,25 @@ namespace Strawberry { return Rect(a.X - b.X, a.Y - b.Y, a.Width, a.Height); } + + static public Rect operator/(Rect a, int b) + { + return Rect(a.X / b, a.Y / b, a.Width / b, a.Height / b); + } + + static public Rect operator/(Rect a, Point b) + { + return Rect(a.X / b.X, a.Y / b.Y, a.Width / b.X, a.Height / b.Y); + } + + static public Rect operator*(Rect a, int b) + { + return Rect(a.X * b, a.Y * b, a.Width * b, a.Height * b); + } + + static public Rect operator*(Rect a, Point b) + { + return Rect(a.X * b.X, a.Y * b.Y, a.Width * b.X, a.Height * b.Y); + } } }