mirror of
				https://github.com/MaddyThorson/StrawberryBF.git
				synced 2025-11-04 01:41:33 +08:00 
			
		
		
		
	Big restructuring - sample game is currently broken
This commit is contained in:
		
							
								
								
									
										288
									
								
								src/Components/Collision/Hitbox.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								src/Components/Collision/Hitbox.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,288 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	public class Hitbox : Component, IDebugDraw
 | 
			
		||||
	{
 | 
			
		||||
		public bool Collidable = true;
 | 
			
		||||
		public Rect Rect;
 | 
			
		||||
 | 
			
		||||
		public void DebugDraw()
 | 
			
		||||
		{
 | 
			
		||||
			Game.Batcher.Rect(SceneHitbox, .Red);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Width
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Rect.Width;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Rect.Width = value;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Height
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Rect.Height;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Rect.Height = value;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Rect SceneHitbox
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Rect + Entity.Position;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Left
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Entity.X + Rect.Left;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Entity.X = value - Rect.Left;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Right
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Entity.X + Rect.Right;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Entity.X = value - Rect.Right;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Top
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Entity.Y + Rect.Top;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Entity.Y = value - Rect.Top;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Bottom
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Entity.Y + Rect.Bottom;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Entity.Y = value - Rect.Bottom;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// ===== Collisions =====
 | 
			
		||||
 | 
			
		||||
		public bool Check(Point point)
 | 
			
		||||
		{
 | 
			
		||||
			return SceneHitbox.Contains(point);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Rect rect)
 | 
			
		||||
		{
 | 
			
		||||
			return SceneHitbox.Intersects(rect);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Grid grid)
 | 
			
		||||
		{
 | 
			
		||||
			return grid != null && grid.Check(SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Grid grid, Point offset)
 | 
			
		||||
		{
 | 
			
		||||
			return grid != null && grid.Check(SceneHitbox + offset);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Hitbox other)
 | 
			
		||||
		{
 | 
			
		||||
			return other.Collidable && SceneHitbox.Intersects(other.SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Hitbox other, Point offset)
 | 
			
		||||
		{
 | 
			
		||||
			return other.Collidable && (SceneHitbox + offset).Intersects(other.SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool CheckOutside(Hitbox other, Point offset)
 | 
			
		||||
		{
 | 
			
		||||
			return other.Collidable && !SceneHitbox.Intersects(other.SceneHitbox) && (SceneHitbox + offset).Intersects(other.SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>(T other) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			return Check(other.Hitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>(T other, Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			return Check(other.Hitbox, offset);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool CheckOutside<T>(T other, Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			return CheckOutside(other.Hitbox, offset);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>() where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e.Hitbox))
 | 
			
		||||
					return true;
 | 
			
		||||
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>(Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e.Hitbox, offset))
 | 
			
		||||
					return true;
 | 
			
		||||
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool CheckOutside<T>(Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e.Hitbox, offset))
 | 
			
		||||
					return true;
 | 
			
		||||
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>() where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e.Hitbox))
 | 
			
		||||
					return e;
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>(Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e.Hitbox, offset))
 | 
			
		||||
					return e;
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T FirstOutside<T>(Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e.Hitbox, offset))
 | 
			
		||||
					return e;
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T LeftmostOutside<T>(Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			T ret = null;
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e.Hitbox, offset) && (ret == null || e.Hitbox.Left < ret.Hitbox.Left))
 | 
			
		||||
					ret = e;
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T RightmostOutside<T>(Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			T ret = null;
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e.Hitbox, offset) && (ret == null || e.Hitbox.Right > ret.Hitbox.Right))
 | 
			
		||||
					ret = e;
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T TopmostOutside<T>(Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			T ret = null;
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e.Hitbox, offset) && (ret == null || e.Hitbox.Top < ret.Hitbox.Top))
 | 
			
		||||
					ret = e;
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T BottommostOutside<T>(Point offset) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			T ret = null;
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e.Hitbox, offset) && (ret == null || e.Hitbox.Bottom > ret.Hitbox.Bottom))
 | 
			
		||||
					ret = e;
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(List<T> into) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e.Hitbox))
 | 
			
		||||
					into.Add(e);
 | 
			
		||||
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(Point offset, List<T> into) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e.Hitbox, offset))
 | 
			
		||||
					into.Add(e);
 | 
			
		||||
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> AllOutside<T>(Point offset, List<T> into) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e.Hitbox, offset))
 | 
			
		||||
					into.Add(e);
 | 
			
		||||
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +1,16 @@
 | 
			
		||||
using System.Collections;
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	public class OnCollide<T> : Component where T : Entity
 | 
			
		||||
	public class OnCollide<T> : Component, IHasHitbox, IUpdate where T : Component, IHasHitbox
 | 
			
		||||
	{
 | 
			
		||||
		public Hitbox Hitbox { get; private set; }
 | 
			
		||||
 | 
			
		||||
		// Takes as parameter the T collided with. Return false to stop checking for collisions until next frame.
 | 
			
		||||
		public delegate bool(T) Action;
 | 
			
		||||
 | 
			
		||||
		public this(delegate bool(T) action)
 | 
			
		||||
			: base(true, false)
 | 
			
		||||
		public this(Hitbox hitbox, delegate bool(T) action)
 | 
			
		||||
		{
 | 
			
		||||
			Hitbox = hitbox;
 | 
			
		||||
			Action = action;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -17,13 +19,13 @@ namespace Strawberry
 | 
			
		||||
			delete Action;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Update()
 | 
			
		||||
		public void Update()
 | 
			
		||||
		{
 | 
			
		||||
			if (Action != null)
 | 
			
		||||
			{
 | 
			
		||||
				let list = Entity.Scene.All<T>(scope List<T>());
 | 
			
		||||
				for (let t in list)
 | 
			
		||||
					if (Entity.Check(t) && !Action(t))
 | 
			
		||||
					if (Hitbox.Check(t) && !Action(t))
 | 
			
		||||
						break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
							
								
								
									
										19
									
								
								src/Components/Drawing/DrawHitbox.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Components/Drawing/DrawHitbox.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	public class DrawHitbox : Component, IHasHitbox, IDraw
 | 
			
		||||
	{
 | 
			
		||||
		public Hitbox Hitbox { get; private set; }
 | 
			
		||||
		public Color Color;
 | 
			
		||||
 | 
			
		||||
		public this(Hitbox hitbox, Color color)
 | 
			
		||||
		{
 | 
			
		||||
			Hitbox = hitbox;
 | 
			
		||||
			Color = color;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Draw()
 | 
			
		||||
		{
 | 
			
		||||
			Game.Batcher.Rect(Hitbox.SceneHitbox, Color);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/Components/Interfaces/IDebugDraw.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Components/Interfaces/IDebugDraw.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	[ComponentInterface]
 | 
			
		||||
	public interface IDebugDraw
 | 
			
		||||
	{
 | 
			
		||||
		public void DebugDraw();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/Components/Interfaces/IDraw.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Components/Interfaces/IDraw.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	[ComponentInterface]
 | 
			
		||||
	public interface IDraw
 | 
			
		||||
	{
 | 
			
		||||
		public void Draw();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/Components/Interfaces/IHasHitbox.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Components/Interfaces/IHasHitbox.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	[ComponentInterface]
 | 
			
		||||
	public interface IHasHitbox
 | 
			
		||||
	{
 | 
			
		||||
		public Hitbox Hitbox { get; }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/Components/Interfaces/ILateUpdate.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Components/Interfaces/ILateUpdate.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	[ComponentInterface]
 | 
			
		||||
	public interface ILateUpdate
 | 
			
		||||
	{
 | 
			
		||||
		public void LateUpdate();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/Components/Interfaces/IUpdate.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Components/Interfaces/IUpdate.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	[ComponentInterface]
 | 
			
		||||
	public interface IUpdate
 | 
			
		||||
	{
 | 
			
		||||
		public void Update();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -4,7 +4,7 @@ using System.Diagnostics;
 | 
			
		||||
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	public class StateMachine<TIndex> : Component where TIndex : struct, IHashable
 | 
			
		||||
	public class StateMachine<TIndex> : Component, IUpdate where TIndex : struct, IHashable
 | 
			
		||||
	{
 | 
			
		||||
		private Dictionary<TIndex, State> states = new Dictionary<TIndex, State>() ~ delete _;
 | 
			
		||||
		private TIndex state;
 | 
			
		||||
@ -14,7 +14,6 @@ namespace Strawberry
 | 
			
		||||
		public TIndex NextState { get; private set; }
 | 
			
		||||
 | 
			
		||||
		public this(TIndex startState)
 | 
			
		||||
			: base(true, false)
 | 
			
		||||
		{
 | 
			
		||||
			NextState = PreviousState = state = startState;
 | 
			
		||||
		}
 | 
			
		||||
@ -30,7 +29,7 @@ namespace Strawberry
 | 
			
		||||
			CallEnter();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Update()
 | 
			
		||||
		public void Update()
 | 
			
		||||
		{
 | 
			
		||||
			CallUpdate();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -3,35 +3,27 @@ using System.Diagnostics;
 | 
			
		||||
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	public class Timer : Component
 | 
			
		||||
	public class Timer : Component, IUpdate
 | 
			
		||||
	{
 | 
			
		||||
		private float value;
 | 
			
		||||
 | 
			
		||||
		public Action OnComplete ~ delete _;
 | 
			
		||||
		public bool RemoveOnComplete;
 | 
			
		||||
 | 
			
		||||
		public this()
 | 
			
		||||
			: base(false, false)
 | 
			
		||||
		{
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public this(Action onComplete, bool destroyOnComplete = false)
 | 
			
		||||
			: base(false, false)
 | 
			
		||||
		{
 | 
			
		||||
			OnComplete = onComplete;
 | 
			
		||||
			RemoveOnComplete = destroyOnComplete;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public this(float value, Action onComplete, bool destroyOnComplete = false)
 | 
			
		||||
			: base(false, false)
 | 
			
		||||
		{
 | 
			
		||||
			Value = value;
 | 
			
		||||
			OnComplete = onComplete;
 | 
			
		||||
			RemoveOnComplete = destroyOnComplete;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Update()
 | 
			
		||||
		public void Update()
 | 
			
		||||
		{
 | 
			
		||||
			if (value > 0)
 | 
			
		||||
			{
 | 
			
		||||
@ -39,8 +31,6 @@ namespace Strawberry
 | 
			
		||||
				if (value <= 0)
 | 
			
		||||
				{
 | 
			
		||||
					value = 0;
 | 
			
		||||
					Active = false;
 | 
			
		||||
 | 
			
		||||
					OnComplete?.Invoke();
 | 
			
		||||
					if (RemoveOnComplete)
 | 
			
		||||
						RemoveSelf();
 | 
			
		||||
@ -60,7 +50,6 @@ namespace Strawberry
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				this.value = Math.Max(0, value);
 | 
			
		||||
				Active = (this.value > 0);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -68,7 +57,6 @@ namespace Strawberry
 | 
			
		||||
		public void Clear()
 | 
			
		||||
		{
 | 
			
		||||
			value = 0;
 | 
			
		||||
			Active = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		static public implicit operator bool(Timer timer)
 | 
			
		||||
 | 
			
		||||
@ -1,33 +1,42 @@
 | 
			
		||||
using System;
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	public class Tween : Component
 | 
			
		||||
	public class Tween : Component, IUpdate
 | 
			
		||||
	{
 | 
			
		||||
		public Ease.Easer Easer ~ delete _;
 | 
			
		||||
		public delegate void(float) OnUpdate ~ delete _;
 | 
			
		||||
		public delegate void() OnComplete ~ delete _;
 | 
			
		||||
		public bool RemoveOnComplete;
 | 
			
		||||
 | 
			
		||||
		public bool Playing { get; private set; }
 | 
			
		||||
		public float T { get; private set; }
 | 
			
		||||
 | 
			
		||||
		public this(Ease.Easer easer = null, delegate void(float) onUpdate = null, delegate void() onComplete = null, bool removeOnComplete = true, bool start = true)
 | 
			
		||||
			: base(start, false)
 | 
			
		||||
		{
 | 
			
		||||
			Playing = start;
 | 
			
		||||
			Easer = easer;
 | 
			
		||||
			OnUpdate = onUpdate;
 | 
			
		||||
			OnComplete = onComplete;
 | 
			
		||||
			RemoveOnComplete = removeOnComplete;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Inline]
 | 
			
		||||
		public float Eased => Easer != null ? Easer(T) : T;
 | 
			
		||||
 | 
			
		||||
		[Inline]
 | 
			
		||||
		public void Play()
 | 
			
		||||
		{
 | 
			
		||||
			T = 0;
 | 
			
		||||
			Active = true;
 | 
			
		||||
			Playing = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Update()
 | 
			
		||||
		[Inline]
 | 
			
		||||
		public void Stop()
 | 
			
		||||
		{
 | 
			
		||||
			Playing = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Update()
 | 
			
		||||
		{
 | 
			
		||||
			T = Math.Min(T + Time.Delta, 1);
 | 
			
		||||
			OnUpdate?.Invoke(Eased);
 | 
			
		||||
@ -35,7 +44,7 @@ namespace Strawberry
 | 
			
		||||
			if (T >= 1)
 | 
			
		||||
			{
 | 
			
		||||
				OnComplete?.Invoke();
 | 
			
		||||
				Active = false;
 | 
			
		||||
				Playing = false;
 | 
			
		||||
				if (RemoveOnComplete)
 | 
			
		||||
					RemoveSelf();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -6,15 +6,6 @@ namespace Strawberry
 | 
			
		||||
	{
 | 
			
		||||
		public Entity Entity { get; private set; }
 | 
			
		||||
 | 
			
		||||
		public bool Active;
 | 
			
		||||
		public bool Visible;
 | 
			
		||||
 | 
			
		||||
		public this(bool active, bool visible)
 | 
			
		||||
		{
 | 
			
		||||
			Active = active;
 | 
			
		||||
			Visible = visible;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void Added(Entity entity)
 | 
			
		||||
		{
 | 
			
		||||
			Entity = entity;
 | 
			
		||||
@ -27,13 +18,20 @@ namespace Strawberry
 | 
			
		||||
 | 
			
		||||
		public virtual void Started() { }
 | 
			
		||||
		public virtual void Ended() { }
 | 
			
		||||
		public virtual void Update() { }
 | 
			
		||||
		public virtual void Draw() { }
 | 
			
		||||
 | 
			
		||||
		[Inline]
 | 
			
		||||
		public void RemoveSelf()
 | 
			
		||||
		{
 | 
			
		||||
			Entity?.Remove(this);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Inline]
 | 
			
		||||
		public Scene Scene => Entity?.Scene;
 | 
			
		||||
 | 
			
		||||
		[Inline]
 | 
			
		||||
		public T SceneAs<T>() where T : Scene
 | 
			
		||||
		{
 | 
			
		||||
			return Entity.SceneAs<T>();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/Core/ComponentInterfaceAttribute.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/Core/ComponentInterfaceAttribute.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	public struct ComponentInterfaceAttribute : Attribute
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -3,13 +3,9 @@ using System.Collections;
 | 
			
		||||
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	public abstract class Entity
 | 
			
		||||
	public sealed class Entity
 | 
			
		||||
	{
 | 
			
		||||
		public Scene Scene { get; private set; }
 | 
			
		||||
		public int Priority;
 | 
			
		||||
		public bool Active = true;
 | 
			
		||||
		public bool Visible = true;
 | 
			
		||||
		public bool Collidable = true;
 | 
			
		||||
		public bool DeleteOnRemove = true;
 | 
			
		||||
 | 
			
		||||
		private List<Component> components = new List<Component>() ~ delete _;
 | 
			
		||||
@ -40,32 +36,18 @@ namespace Strawberry
 | 
			
		||||
			Scene = null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public virtual void Started()
 | 
			
		||||
		public void Started()
 | 
			
		||||
		{
 | 
			
		||||
			for (var c in components)
 | 
			
		||||
				c.Started();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public virtual void Ended()
 | 
			
		||||
		public void Ended()
 | 
			
		||||
		{
 | 
			
		||||
			for (var c in components)
 | 
			
		||||
				c.Ended();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public virtual void Update()
 | 
			
		||||
		{
 | 
			
		||||
			for (var c in components)
 | 
			
		||||
				if (c.Active)
 | 
			
		||||
					c.Update();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public virtual void Draw()
 | 
			
		||||
		{
 | 
			
		||||
			for (var c in components)
 | 
			
		||||
				if (c.Visible)
 | 
			
		||||
					c.Draw();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Inline]
 | 
			
		||||
		public void RemoveSelf()
 | 
			
		||||
		{
 | 
			
		||||
@ -195,302 +177,13 @@ namespace Strawberry
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// ===== Hitbox =====
 | 
			
		||||
 | 
			
		||||
		public Rect Hitbox;
 | 
			
		||||
 | 
			
		||||
		public int Width
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Hitbox.Width;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Hitbox.Width = value;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Height
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Hitbox.Height;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Hitbox.Height = value;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Rect SceneHitbox
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Hitbox + Position;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Rect SceneHitboxOutline
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				Rect hb = Hitbox + Position;
 | 
			
		||||
				hb.X -= 1;
 | 
			
		||||
				hb.Y -= 1;
 | 
			
		||||
				hb.Width += 2;
 | 
			
		||||
				hb.Height += 2;
 | 
			
		||||
				return hb;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Left
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Position.X + Hitbox.Left;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				X = value - Hitbox.Left;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Right
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Position.X + Hitbox.Right;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Y = value - Hitbox.Right;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Top
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Position.Y + Hitbox.Top;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Y = value - Hitbox.Top;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Bottom
 | 
			
		||||
		{
 | 
			
		||||
			[Inline]
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return Position.Y + Hitbox.Bottom;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			[Inline]
 | 
			
		||||
			set
 | 
			
		||||
			{
 | 
			
		||||
				Y = value - Hitbox.Bottom;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// ===== Collisions =====
 | 
			
		||||
 | 
			
		||||
		public bool Check(Point point)
 | 
			
		||||
		{
 | 
			
		||||
			return SceneHitbox.Contains(point);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Rect rect)
 | 
			
		||||
		{
 | 
			
		||||
			return SceneHitbox.Intersects(rect);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Grid grid)
 | 
			
		||||
		{
 | 
			
		||||
			return grid != null && grid.Check(SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Grid grid, Point offset)
 | 
			
		||||
		{
 | 
			
		||||
			return grid != null && grid.Check(SceneHitbox + offset);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Entity other)
 | 
			
		||||
		{
 | 
			
		||||
			return other.Collidable && SceneHitbox.Intersects(other.SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Entity other, Point offset)
 | 
			
		||||
		{
 | 
			
		||||
			return other.Collidable && (SceneHitbox + offset).Intersects(other.SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool CheckOutside(Entity other, Point offset)
 | 
			
		||||
		{
 | 
			
		||||
			return other.Collidable && !SceneHitbox.Intersects(other.SceneHitbox) && (SceneHitbox + offset).Intersects(other.SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>() where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e))
 | 
			
		||||
					return true;
 | 
			
		||||
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>(Point offset) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e, offset))
 | 
			
		||||
					return true;
 | 
			
		||||
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool CheckOutside<T>(Point offset) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e, offset))
 | 
			
		||||
					return true;
 | 
			
		||||
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>() where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e))
 | 
			
		||||
					return e;
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>(Point offset) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e, offset))
 | 
			
		||||
					return e;
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T FirstOutside<T>(Point offset) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e, offset))
 | 
			
		||||
					return e;
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T LeftmostOutside<T>(Point offset) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			T ret = null;
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e, offset) && (ret == null || e.Left < ret.Left))
 | 
			
		||||
					ret = e;
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T RightmostOutside<T>(Point offset) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			T ret = null;
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e, offset) && (ret == null || e.Right > ret.Right))
 | 
			
		||||
					ret = e;
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T TopmostOutside<T>(Point offset) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			T ret = null;
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e, offset) && (ret == null || e.Top < ret.Top))
 | 
			
		||||
					ret = e;
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T BottommostOutside<T>(Point offset) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			T ret = null;
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e, offset) && (ret == null || e.Bottom > ret.Bottom))
 | 
			
		||||
					ret = e;
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(List<T> into) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e))
 | 
			
		||||
					into.Add(e);
 | 
			
		||||
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(Point offset, List<T> into) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (Check(e, offset))
 | 
			
		||||
					into.Add(e);
 | 
			
		||||
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> AllOutside<T>(Point offset, List<T> into) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (var e in Scene.All<T>(scope List<T>()))
 | 
			
		||||
				if (CheckOutside(e, offset))
 | 
			
		||||
					into.Add(e);
 | 
			
		||||
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// ===== Misc =====
 | 
			
		||||
 | 
			
		||||
		public void DrawHitbox(Color color)
 | 
			
		||||
		{
 | 
			
		||||
			Game.Batcher.Rect(SceneHitbox, color);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void DrawHitboxOutline(Color color)
 | 
			
		||||
		{
 | 
			
		||||
			Game.Batcher.Rect(SceneHitboxOutline, color);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Inline]
 | 
			
		||||
		public T SceneAs<T>() where T : Scene
 | 
			
		||||
		{
 | 
			
		||||
			Runtime.Assert(Scene is T, "Scene type mismatch!");
 | 
			
		||||
			return Scene as T;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		static public int Compare(Entity a, Entity b)
 | 
			
		||||
		{
 | 
			
		||||
			return a.Priority <=> b.Priority; 
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,6 @@ namespace Strawberry
 | 
			
		||||
		private Scene scene;
 | 
			
		||||
		private Scene switchToScene;
 | 
			
		||||
		private bool updating;
 | 
			
		||||
		private Dictionary<Type, List<Type>> entityAssignableLists;
 | 
			
		||||
		private Dictionary<Type, List<Type>> componentAssignableLists;
 | 
			
		||||
 | 
			
		||||
		public PlatformLayer PlatformLayer { get; private set; }
 | 
			
		||||
		public Batcher Batcher { get; private set; }
 | 
			
		||||
@ -60,9 +58,9 @@ namespace Strawberry
 | 
			
		||||
			VirtualInputs = new List<VirtualInput>();
 | 
			
		||||
			Input.[Friend]Init();
 | 
			
		||||
 | 
			
		||||
			BuildTypeLists();
 | 
			
		||||
			Tracker.[Friend]BuildAssignmentLists();
 | 
			
		||||
			Assets.LoadAll();
 | 
			
		||||
			Strawberry.Console.Init();
 | 
			
		||||
			Strawberry.StrwConsole.Init();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ~this()
 | 
			
		||||
@ -83,9 +81,8 @@ namespace Strawberry
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Assets.DisposeAll();
 | 
			
		||||
			DisposeTypeLists();
 | 
			
		||||
			Input.[Friend]Dispose();
 | 
			
		||||
			Strawberry.Console.Dispose();
 | 
			
		||||
			Strawberry.StrwConsole.Dispose();
 | 
			
		||||
 | 
			
		||||
			delete Batcher;
 | 
			
		||||
 | 
			
		||||
@ -157,7 +154,7 @@ namespace Strawberry
 | 
			
		||||
				Time.Elapsed += Time.Delta;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Strawberry.Console.[Friend]Update();
 | 
			
		||||
			Strawberry.StrwConsole.[Friend]Update();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void Render()
 | 
			
		||||
@ -171,8 +168,8 @@ namespace Strawberry
 | 
			
		||||
		{
 | 
			
		||||
			Scene?.Draw();
 | 
			
		||||
 | 
			
		||||
			if (Strawberry.Console.Enabled)
 | 
			
		||||
				Strawberry.Console.[Friend]Draw();
 | 
			
		||||
			if (Strawberry.StrwConsole.Enabled)
 | 
			
		||||
				Strawberry.StrwConsole.[Friend]Draw();
 | 
			
		||||
 | 
			
		||||
			Batcher.Draw();
 | 
			
		||||
		}
 | 
			
		||||
@ -191,57 +188,5 @@ namespace Strawberry
 | 
			
		||||
				switchToScene = value;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Type assignable caching
 | 
			
		||||
 | 
			
		||||
		private void BuildTypeLists()
 | 
			
		||||
		{
 | 
			
		||||
			/*
 | 
			
		||||
				For each Type that extends Entity, we build a list of all the other Entity Types that it is assignable to.
 | 
			
		||||
				We cache these lists, and use them later to bucket Entities as they are added to the Scene.
 | 
			
		||||
				This allows us to retrieve Entities by type very easily.
 | 
			
		||||
			*/
 | 
			
		||||
 | 
			
		||||
			entityAssignableLists = new Dictionary<Type, List<Type>>();
 | 
			
		||||
			for (let type in Type.Enumerator())
 | 
			
		||||
			{	
 | 
			
		||||
				if (type != typeof(Entity) && type.IsSubtypeOf(typeof(Entity)))
 | 
			
		||||
				{
 | 
			
		||||
					let list = new List<Type>();
 | 
			
		||||
					for (let check in Type.Enumerator())
 | 
			
		||||
						if (check != typeof(Entity) && check.IsSubtypeOf(typeof(Entity)) && type.IsSubtypeOf(check))
 | 
			
		||||
							list.Add(check);
 | 
			
		||||
					entityAssignableLists.Add(type, list);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
				And then we also do this for components
 | 
			
		||||
			*/
 | 
			
		||||
 | 
			
		||||
			componentAssignableLists = new Dictionary<Type, List<Type>>();
 | 
			
		||||
			for (let type in Type.Enumerator())
 | 
			
		||||
			{	
 | 
			
		||||
				if (type != typeof(Component) && type.IsSubtypeOf(typeof(Component)))
 | 
			
		||||
				{
 | 
			
		||||
					let list = new List<Type>();
 | 
			
		||||
					for (let check in Type.Enumerator())
 | 
			
		||||
						if (check != typeof(Component) && check.IsSubtypeOf(typeof(Component)) && type.IsSubtypeOf(check))
 | 
			
		||||
							list.Add(check);
 | 
			
		||||
					componentAssignableLists.Add(type, list);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void DisposeTypeLists()
 | 
			
		||||
		{
 | 
			
		||||
			for (let list in entityAssignableLists.Values)
 | 
			
		||||
				delete list;
 | 
			
		||||
			delete entityAssignableLists;
 | 
			
		||||
 | 
			
		||||
			for (let list in componentAssignableLists.Values)
 | 
			
		||||
				delete list;
 | 
			
		||||
			delete componentAssignableLists;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,6 @@ namespace Strawberry
 | 
			
		||||
		private List<Entity> entities;
 | 
			
		||||
		private HashSet<Entity> toRemove;
 | 
			
		||||
		private HashSet<Entity> toAdd;
 | 
			
		||||
		private Dictionary<Type, List<Entity>> entityTracker;
 | 
			
		||||
		private Dictionary<Type, List<Component>> componentTracker;
 | 
			
		||||
 | 
			
		||||
		public this()
 | 
			
		||||
@ -19,12 +18,10 @@ namespace Strawberry
 | 
			
		||||
			toAdd = new HashSet<Entity>();
 | 
			
		||||
			toRemove = new HashSet<Entity>();
 | 
			
		||||
 | 
			
		||||
			entityTracker = new Dictionary<Type, List<Entity>>();
 | 
			
		||||
			for (let type in Game.[Friend]entityAssignableLists.Keys)
 | 
			
		||||
				entityTracker.Add(type, new List<Entity>());
 | 
			
		||||
 | 
			
		||||
			componentTracker = new Dictionary<Type, List<Component>>();
 | 
			
		||||
			for (let type in Game.[Friend]componentAssignableLists.Keys)
 | 
			
		||||
			for (let type in Tracker.AssignmentLists.Keys)
 | 
			
		||||
				componentTracker.Add(type, new List<Component>());
 | 
			
		||||
			for (let type in Tracker.Interfaces)
 | 
			
		||||
				componentTracker.Add(type, new List<Component>());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -42,10 +39,6 @@ namespace Strawberry
 | 
			
		||||
 | 
			
		||||
			delete toRemove;
 | 
			
		||||
 | 
			
		||||
			for (let list in entityTracker.Values)
 | 
			
		||||
				delete list;
 | 
			
		||||
			delete entityTracker;
 | 
			
		||||
 | 
			
		||||
			for (let list in componentTracker.Values)
 | 
			
		||||
				delete list;
 | 
			
		||||
			delete componentTracker;
 | 
			
		||||
@ -59,26 +52,23 @@ namespace Strawberry
 | 
			
		||||
		public virtual void Update()
 | 
			
		||||
		{
 | 
			
		||||
			UpdateLists();
 | 
			
		||||
			for (let e in entities)
 | 
			
		||||
				if (e.Active)
 | 
			
		||||
					e.Update();
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public virtual void Draw()
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entities)
 | 
			
		||||
				if (e.Visible)
 | 
			
		||||
					e.Draw();
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T Add<T>(T e) where T : Entity
 | 
			
		||||
		public Entity Add(Entity e)
 | 
			
		||||
		{
 | 
			
		||||
			if (e.Scene == null)
 | 
			
		||||
				toAdd.Add(e);
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T Remove<T>(T e) where T : Entity
 | 
			
		||||
		public Entity Remove(Entity e)
 | 
			
		||||
		{
 | 
			
		||||
			if (e.Scene == this)
 | 
			
		||||
				toRemove.Add(e);
 | 
			
		||||
@ -92,7 +82,6 @@ namespace Strawberry
 | 
			
		||||
				for (let e in toRemove)
 | 
			
		||||
				{
 | 
			
		||||
					entities.Remove(e);
 | 
			
		||||
					UntrackEntity(e);
 | 
			
		||||
					e.[Friend]Removed();
 | 
			
		||||
					if (e.DeleteOnRemove)
 | 
			
		||||
						delete e;
 | 
			
		||||
@ -106,11 +95,8 @@ namespace Strawberry
 | 
			
		||||
				for (let e in toAdd)
 | 
			
		||||
				{
 | 
			
		||||
					entities.Add(e);
 | 
			
		||||
					TrackEntity(e);
 | 
			
		||||
					e.[Friend]Added(this);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				entities.Sort(scope => Entity.Compare);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (let e in entities)
 | 
			
		||||
@ -126,33 +112,15 @@ namespace Strawberry
 | 
			
		||||
 | 
			
		||||
		// Tracking
 | 
			
		||||
 | 
			
		||||
		private void TrackEntity(Entity e)
 | 
			
		||||
		{
 | 
			
		||||
			for (let t in Game.[Friend]entityAssignableLists[e.GetType()])
 | 
			
		||||
				entityTracker[t].Add(e);
 | 
			
		||||
 | 
			
		||||
			for (let c in e.[Friend]components)
 | 
			
		||||
				TrackComponent(c);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void UntrackEntity(Entity e)
 | 
			
		||||
		{
 | 
			
		||||
			for (let t in Game.[Friend]entityAssignableLists[e.GetType()])
 | 
			
		||||
				entityTracker[t].Remove(e);
 | 
			
		||||
 | 
			
		||||
			for (let c in e.[Friend]components)
 | 
			
		||||
				UntrackComponent(c);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void TrackComponent(Component c)
 | 
			
		||||
		{
 | 
			
		||||
			for (let t in Game.[Friend]componentAssignableLists[c.GetType()])
 | 
			
		||||
			for (let t in Tracker.AssignmentLists[c.GetType()])
 | 
			
		||||
				componentTracker[t].Add(c);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void UntrackComponent(Component c)
 | 
			
		||||
		{
 | 
			
		||||
			for (let t in Game.[Friend]componentAssignableLists[c.GetType()])
 | 
			
		||||
			for (let t in Tracker.AssignmentLists[c.GetType()])
 | 
			
		||||
				componentTracker[t].Remove(c);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -171,75 +139,6 @@ namespace Strawberry
 | 
			
		||||
			return (TimeElapsed - offset) % (interval * 2) >= interval;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Finding Entities
 | 
			
		||||
 | 
			
		||||
		public int Count<T>() where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			return entityTracker[typeof(T)].Count;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>(Point point) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entityTracker[typeof(T)])
 | 
			
		||||
				if (e.Check(point))
 | 
			
		||||
					return true;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>(Rect rect) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entityTracker[typeof(T)])
 | 
			
		||||
				if (e.Check(rect))
 | 
			
		||||
					return true;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>() where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entityTracker[typeof(T)])
 | 
			
		||||
				return e as T;
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>(Point point) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entityTracker[typeof(T)])
 | 
			
		||||
				if (e.Check(point))
 | 
			
		||||
					return e as T;
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>(Rect rect) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entityTracker[typeof(T)])
 | 
			
		||||
				if (e.Check(rect))
 | 
			
		||||
					return e as T;
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(List<T> into) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entityTracker[typeof(T)])
 | 
			
		||||
				into.Add(e as T);
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(Point point, List<T> into) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entityTracker[typeof(T)])
 | 
			
		||||
				if (e.Check(point))
 | 
			
		||||
					into.Add(e as T);
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(Rect rect, List<T> into) where T : Entity
 | 
			
		||||
		{
 | 
			
		||||
			for (let e in entityTracker[typeof(T)])
 | 
			
		||||
				if (e.Check(rect))
 | 
			
		||||
					into.Add(e as T);
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
			Finding Components
 | 
			
		||||
		*/
 | 
			
		||||
@ -249,25 +148,64 @@ namespace Strawberry
 | 
			
		||||
			return componentTracker[typeof(T)].Count;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(List<T> into) where T : Component
 | 
			
		||||
		public bool Check<T>(Point point) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (let c in componentTracker[typeof(T)])
 | 
			
		||||
			for (T c in componentTracker[typeof(T)])
 | 
			
		||||
				if (c.Hitbox.Check(point))
 | 
			
		||||
					return true;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check<T>(Rect rect) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (T c in componentTracker[typeof(T)])
 | 
			
		||||
				if (c.Hitbox.Check(rect))
 | 
			
		||||
					return true;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>() where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (T c in componentTracker[typeof(T)])
 | 
			
		||||
				return c;
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>(Point point) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (T c in componentTracker[typeof(T)])
 | 
			
		||||
				if (c.Hitbox.Check(point))
 | 
			
		||||
					return c as T;
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public T First<T>(Rect rect) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (T c in componentTracker[typeof(T)])
 | 
			
		||||
				if (c.Hitbox.Check(rect))
 | 
			
		||||
					return c as T;
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(List<T> into) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (T c in componentTracker[typeof(T)])
 | 
			
		||||
				into.Add(c as T);
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(Point point, List<T> into) where T : Component
 | 
			
		||||
		public List<T> All<T>(Point point, List<T> into) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (let c in componentTracker[typeof(T)])
 | 
			
		||||
				if (c.Entity.Check(point))
 | 
			
		||||
			for (T c in componentTracker[typeof(T)])
 | 
			
		||||
				if (c.Hitbox.Check(point))
 | 
			
		||||
					into.Add(c as T);
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<T> All<T>(Rect rect, List<T> into) where T : Component
 | 
			
		||||
		public List<T> All<T>(Rect rect, List<T> into) where T : Component, IHasHitbox
 | 
			
		||||
		{
 | 
			
		||||
			for (let c in componentTracker[typeof(T)])
 | 
			
		||||
				if (c.Entity.Check(rect))
 | 
			
		||||
			for (T c in componentTracker[typeof(T)])
 | 
			
		||||
				if (c.Hitbox.Check(rect))
 | 
			
		||||
					into.Add(c as T);
 | 
			
		||||
			return into;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -143,9 +143,14 @@ namespace Strawberry
 | 
			
		||||
			return p.X >= 0 && p.Y >= 0 && p.X < CellsX && p.Y < CellsY;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Entity entity)
 | 
			
		||||
		public bool Check(Hitbox hitbox)
 | 
			
		||||
		{
 | 
			
		||||
			return Check(entity.SceneHitbox);
 | 
			
		||||
			return Check(hitbox.SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(IHasHitbox other)
 | 
			
		||||
		{
 | 
			
		||||
			return Check(other.Hitbox.SceneHitbox);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Check(Rect rect)
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ namespace Strawberry
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[Reflect]
 | 
			
		||||
	static public class Console
 | 
			
		||||
	static public class StrwConsole
 | 
			
		||||
	{
 | 
			
		||||
		static public bool Open;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								src/Static/Tracker.bf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/Static/Tracker.bf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System;
 | 
			
		||||
namespace Strawberry
 | 
			
		||||
{
 | 
			
		||||
	static public class Tracker
 | 
			
		||||
	{
 | 
			
		||||
		static public Dictionary<Type, List<Type>> AssignmentLists = new .() ~ DeleteDictionaryAndValues!(_);
 | 
			
		||||
		static public List<Type> Interfaces = new .() ~ delete _;
 | 
			
		||||
 | 
			
		||||
		static private void BuildAssignmentLists()
 | 
			
		||||
		{
 | 
			
		||||
			// Find all interfaces with ComponentInterfaceAttribute
 | 
			
		||||
			for (let type in Type.Enumerator())
 | 
			
		||||
				if (type.IsInterface && type.HasCustomAttribute<ComponentInterfaceAttribute>())
 | 
			
		||||
					Interfaces.Add(type);
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
				For each Type that extends Component, we build a list of all the tracked Interfaces it implements.
 | 
			
		||||
				We use these lists later to bucket Components as they are added to the Scene.
 | 
			
		||||
				This allows us to retrieve Components by their type or by any of their implemented interface types.
 | 
			
		||||
			*/
 | 
			
		||||
 | 
			
		||||
			for (let type in Type.Enumerator())
 | 
			
		||||
			{	
 | 
			
		||||
				if (type != typeof(Component) && type.IsSubtypeOf(typeof(Component)))
 | 
			
		||||
				{
 | 
			
		||||
					let list = new List<Type>();
 | 
			
		||||
					list.Add(type);
 | 
			
		||||
					for (let check in Interfaces)
 | 
			
		||||
						if (type.IsSubtypeOf(check))
 | 
			
		||||
							list.Add(check);
 | 
			
		||||
 | 
			
		||||
					AssignmentLists.Add(type, list);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user