diff --git a/SampleGame/BeefProj.toml b/SampleGame/BeefProj.toml index c003121..76cb18f 100644 --- a/SampleGame/BeefProj.toml +++ b/SampleGame/BeefProj.toml @@ -10,3 +10,9 @@ DefaultNamespace = "Strawberry.Sample" [[Project.DistinctOptions]] Filter = "" ReflectAlwaysInclude = "IncludeAll" + +[[ProjectFolder.Items]] +Type = "Folder" +Name = "Physics" +AutoInclude = true +Source = ["Physics.bf", "Solid.bf", "JumpThru.bf"] diff --git a/src/Components/Collision/Hitbox.bf b/src/Components/Collision/Hitbox.bf index c2c725f..a32da05 100644 --- a/src/Components/Collision/Hitbox.bf +++ b/src/Components/Collision/Hitbox.bf @@ -112,7 +112,9 @@ namespace Strawberry } } - // ===== Collisions ===== + /* + Single Collisions + */ public bool Check(Point point) { @@ -164,6 +166,10 @@ namespace Strawberry return CheckOutside(other.Hitbox, offset); } + /* + Type Collisions + */ + public bool Check() where T : Component, IHasHitbox { for (var e in Scene.All(scope List())) @@ -284,5 +290,130 @@ namespace Strawberry return into; } + + /* + Type Collision w/ Conditions + */ + + public bool Check(delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && Check(e.Hitbox)) + return true; + + return false; + } + + public bool Check(Point offset, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && Check(e.Hitbox, offset)) + return true; + + return false; + } + + public bool CheckOutside(Point offset, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && CheckOutside(e.Hitbox, offset)) + return true; + + return false; + } + + public T First(delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && Check(e.Hitbox)) + return e; + + return null; + } + + public T First(Point offset, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && Check(e.Hitbox, offset)) + return e; + + return null; + } + + public T FirstOutside(Point offset, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && CheckOutside(e.Hitbox, offset)) + return e; + + return null; + } + + public T LeftmostOutside(Point offset, delegate bool(T) condition) where T : Component, IHasHitbox + { + T ret = null; + for (var e in Scene.All(scope List())) + if (condition(e) && CheckOutside(e.Hitbox, offset) && (ret == null || e.Hitbox.Left < ret.Hitbox.Left)) + ret = e; + + return ret; + } + + public T RightmostOutside(Point offset, delegate bool(T) condition) where T : Component, IHasHitbox + { + T ret = null; + for (var e in Scene.All(scope List())) + if (condition(e) && CheckOutside(e.Hitbox, offset) && (ret == null || e.Hitbox.Right > ret.Hitbox.Right)) + ret = e; + + return ret; + } + + public T TopmostOutside(Point offset, delegate bool(T) condition) where T : Component, IHasHitbox + { + T ret = null; + for (var e in Scene.All(scope List())) + if (condition(e) && CheckOutside(e.Hitbox, offset) && (ret == null || e.Hitbox.Top < ret.Hitbox.Top)) + ret = e; + + return ret; + } + + public T BottommostOutside(Point offset, delegate bool(T) condition) where T : Component, IHasHitbox + { + T ret = null; + for (var e in Scene.All(scope List())) + if (condition(e) && CheckOutside(e.Hitbox, offset) && (ret == null || e.Hitbox.Bottom > ret.Hitbox.Bottom)) + ret = e; + + return ret; + } + + public List All(List into, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && Check(e.Hitbox)) + into.Add(e); + + return into; + } + + public List All(Point offset, List into, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && Check(e.Hitbox, offset)) + into.Add(e); + + return into; + } + + public List AllOutside(Point offset, List into, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (var e in Scene.All(scope List())) + if (condition(e) && CheckOutside(e.Hitbox, offset)) + into.Add(e); + + return into; + } } } diff --git a/src/Components/Logic/StateMachine.bf b/src/Components/Logic/StateMachine.bf index 81b02ea..8252bff 100644 --- a/src/Components/Logic/StateMachine.bf +++ b/src/Components/Logic/StateMachine.bf @@ -24,7 +24,7 @@ namespace Strawberry delete s; } - public override void Started() + public override void Awake() { CallEnter(); } diff --git a/src/Core/Component.bf b/src/Core/Component.bf index 24aef0e..5d14309 100644 --- a/src/Core/Component.bf +++ b/src/Core/Component.bf @@ -5,19 +5,11 @@ namespace Strawberry public abstract class Component { public Entity Entity { get; private set; } + public bool IsAwake { get; private set; } - private void Added(Entity entity) - { - Entity = entity; - } - - private void Removed() - { - Entity = null; - } - - public virtual void Started() { } - public virtual void Ended() { } + public virtual void Added() { } + public virtual void Awake() { } + public virtual void End() { } [Inline] public void RemoveSelf() diff --git a/src/Core/Entity.bf b/src/Core/Entity.bf index f1bfa3e..5915323 100644 --- a/src/Core/Entity.bf +++ b/src/Core/Entity.bf @@ -6,6 +6,7 @@ namespace Strawberry public sealed class Entity { public Scene Scene { get; private set; } + public bool IsAwake { get; private set; } public bool DeleteOnRemove = true; private List components = new List() ~ delete _; @@ -32,20 +33,27 @@ namespace Strawberry private void Removed() { - Ended(); + for (var c in components) + { + c.End(); + c.[Friend]IsAwake = false; + } Scene = null; + IsAwake = false; } - public void Started() + private void AwakeCheck() { for (var c in components) - c.Started(); - } + { + if (!c.[Friend]IsAwake) + { + c.Awake(); + c.[Friend]IsAwake = true; + } + } - public void Ended() - { - for (var c in components) - c.Ended(); + IsAwake = true; } [Inline] @@ -78,7 +86,7 @@ namespace Strawberry { components.Remove(c); Scene.[Friend]UntrackComponent(c); - c.[Friend]Removed(); + c.[Friend]Entity = null; delete c; } @@ -91,7 +99,17 @@ namespace Strawberry { components.Add(c); Scene.[Friend]TrackComponent(c); - c.[Friend]Added(this); + c.[Friend]Entity = this; + c.Added(); + } + + if (IsAwake) + { + for (var c in toAdd) + { + c.Awake(); + c.[Friend]IsAwake = true; + } } toAdd.Clear(); diff --git a/src/Core/Scene.bf b/src/Core/Scene.bf index d3e3255..cdc9878 100644 --- a/src/Core/Scene.bf +++ b/src/Core/Scene.bf @@ -97,17 +97,13 @@ namespace Strawberry entities.Add(e); e.[Friend]Added(this); } + toAdd.Clear(); } for (let e in entities) e.[Friend]UpdateLists(); - - if (toAdd.Count > 0) - { - for (let e in toAdd) - e.Started(); - toAdd.Clear(); - } + for (let e in entities) + e.[Friend]AwakeCheck(); } // Tracking @@ -148,6 +144,24 @@ namespace Strawberry return componentTracker[typeof(T)].Count; } + public int Count(delegate bool(T) condition) where T : Component + { + int count = 0; + for (T c in componentTracker[typeof(T)]) + if (condition(c)) + count++; + return count; + } + + public bool Check(delegate bool(T) condition) where T : Component + { + for (T c in componentTracker[typeof(T)]) + if (condition(c)) + return true; + return false; + } + + public bool Check(Point point) where T : Component, IHasHitbox { for (T c in componentTracker[typeof(T)]) @@ -164,13 +178,21 @@ namespace Strawberry return false; } - public T First() where T : Component, IHasHitbox + public T First() where T : Component { for (T c in componentTracker[typeof(T)]) return c; return null; } + public T First(delegate bool(T) condition) where T : Component + { + for (T c in componentTracker[typeof(T)]) + if (condition(c)) + return c; + return null; + } + public T First(Point point) where T : Component, IHasHitbox { for (T c in componentTracker[typeof(T)]) @@ -179,6 +201,14 @@ namespace Strawberry return null; } + public T First(Point point, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (T c in componentTracker[typeof(T)]) + if (condition(c) && c.Hitbox.Check(point)) + return c as T; + return null; + } + public T First(Rect rect) where T : Component, IHasHitbox { for (T c in componentTracker[typeof(T)]) @@ -187,13 +217,29 @@ namespace Strawberry return null; } - public List All(List into) where T : Component, IHasHitbox + public T First(Rect rect, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (T c in componentTracker[typeof(T)]) + if (condition(c) && c.Hitbox.Check(rect)) + return c as T; + return null; + } + + public List All(List into) where T : Component { for (T c in componentTracker[typeof(T)]) into.Add(c as T); return into; } + public List All(List into, delegate bool(T) condition) where T : Component + { + for (T c in componentTracker[typeof(T)]) + if (condition(c)) + into.Add(c as T); + return into; + } + public List All(Point point, List into) where T : Component, IHasHitbox { for (T c in componentTracker[typeof(T)]) @@ -202,10 +248,18 @@ namespace Strawberry return into; } - public List All(Rect rect, List into) where T : Component, IHasHitbox + public List All(Point point, List into, delegate bool(T) condition) where T : Component, IHasHitbox { for (T c in componentTracker[typeof(T)]) - if (c.Hitbox.Check(rect)) + if (condition(c) && c.Hitbox.Check(point)) + into.Add(c as T); + return into; + } + + public List All(Rect rect, List into, delegate bool(T) condition) where T : Component, IHasHitbox + { + for (T c in componentTracker[typeof(T)]) + if (condition(c) && c.Hitbox.Check(rect)) into.Add(c as T); return into; } diff --git a/src/PlatformLayer/Batcher.bf b/src/PlatformLayer/Batcher.bf index 290b6c9..89cfac5 100644 --- a/src/PlatformLayer/Batcher.bf +++ b/src/PlatformLayer/Batcher.bf @@ -49,6 +49,11 @@ namespace Strawberry Rect(rect.X, rect.Y, rect.Width, rect.Height, color); } + public void Pixel(int x, int y, Color color) + { + Rect(x, y, 1, 1, color); + } + public void Tri(Vector a, Vector b, Vector c, Color color) { PushTri(.Shape, null,