mirror of
https://github.com/MaddyThorson/StrawberryBF.git
synced 2025-01-18 05:08:27 +08:00
Big restructuring - sample game is currently broken
This commit is contained in:
parent
05c79b296e
commit
3d5130b45b
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
SampleGame/build/*
|
SampleGame/build/*
|
||||||
SampleGame/BeefSpace_User.toml
|
SampleGame/BeefSpace_User.toml
|
||||||
build/*
|
build/*
|
||||||
|
SampleGame/recovery/*
|
||||||
|
@ -7,8 +7,8 @@ namespace Strawberry.Sample
|
|||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
Add(new Player(.(50, 50)));
|
Add(new Player(.(50, 50)));
|
||||||
Add(new Solid(.(0, 168), .(0, 0, 320, 12)));
|
Add(new OldSolid(.(0, 168), .(0, 0, 320, 12)));
|
||||||
Add(new JumpThru(.(200, 132), 48));
|
Add(new OldJumpThru(.(200, 132), 48));
|
||||||
Add(new MovingJumpThru(.(136, 100), 32, .(124, 140), 2f));
|
Add(new MovingJumpThru(.(136, 100), 32, .(124, 140), 2f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
namespace Strawberry.Sample
|
namespace Strawberry.Sample
|
||||||
{
|
{
|
||||||
public class MovingJumpThru : JumpThru
|
public class MovingJumpThru : OldJumpThru
|
||||||
{
|
{
|
||||||
private Point moveFrom;
|
private Point moveFrom;
|
||||||
private Point moveTo;
|
private Point moveTo;
|
||||||
|
@ -2,56 +2,49 @@ using System;
|
|||||||
|
|
||||||
namespace Strawberry.Sample
|
namespace Strawberry.Sample
|
||||||
{
|
{
|
||||||
[Reflect]
|
public class Physics : Component, IHasHitbox, IUpdate
|
||||||
public class Actor : Entity
|
|
||||||
{
|
{
|
||||||
|
public Hitbox Hitbox { get; private set; }
|
||||||
|
public Vector Speed;
|
||||||
|
|
||||||
private Vector remainder;
|
private Vector remainder;
|
||||||
|
|
||||||
// The amount that geometry has pushed or carried this Actor since the last frame
|
public this(Hitbox hitbox)
|
||||||
public Point MovedByGeometry { get; private set; }
|
|
||||||
|
|
||||||
public this(Point position)
|
|
||||||
: base(position)
|
|
||||||
{
|
{
|
||||||
|
Hitbox = hitbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Level Level => SceneAs<Level>();
|
public Level Level => Entity.SceneAs<Level>();
|
||||||
|
|
||||||
public bool Check(Level level)
|
public bool Check(Level level)
|
||||||
{
|
{
|
||||||
return level.SolidGrid != null && Check(level.SolidGrid);
|
return level.SolidGrid != null && Hitbox.Check(level.SolidGrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Check(Level level, Point offset)
|
public bool Check(Level level, Point offset)
|
||||||
{
|
{
|
||||||
return level.SolidGrid != null && Check(level.SolidGrid, offset);
|
return level.SolidGrid != null && Hitbox.Check(level.SolidGrid, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GroundCheck(int distance = 1)
|
public bool GroundCheck(int distance = 1)
|
||||||
{
|
{
|
||||||
return Check<Solid>(.(0, distance)) || Check(Level, .(0, distance)) || CheckOutside<JumpThru>(.(0, distance));
|
return Hitbox.Check<Solid>(.(0, distance)) || Check(Level, .(0, distance)) || Hitbox.CheckOutside<JumpThru>(.(0, distance));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool IsRiding(Solid solid)
|
public virtual bool IsRiding(Solid solid)
|
||||||
{
|
{
|
||||||
return Check(solid, .(0, 1));
|
return Hitbox.Check(solid, .(0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool IsRiding(JumpThru jumpThru)
|
public virtual bool IsRiding(JumpThru jumpThru)
|
||||||
{
|
{
|
||||||
return CheckOutside(jumpThru, .(0, 1));
|
return Hitbox.CheckOutside(jumpThru, .(0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Squish(Collision collision)
|
public void Update()
|
||||||
{
|
{
|
||||||
RemoveSelf();
|
MoveX(Speed.X * Time.Delta);
|
||||||
}
|
MoveY(Speed.Y * Time.Delta);
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
MovedByGeometry = Point.Zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MoveX(float amount, delegate void(Collision) onCollide = null)
|
public bool MoveX(float amount, delegate void(Collision) onCollide = null)
|
||||||
@ -83,130 +76,85 @@ namespace Strawberry.Sample
|
|||||||
[Inline]
|
[Inline]
|
||||||
public void MoveToX(float x)
|
public void MoveToX(float x)
|
||||||
{
|
{
|
||||||
MoveX(x - (X + remainder.X), null);
|
MoveX(x - (Entity.X + remainder.X), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Inline]
|
[Inline]
|
||||||
public void MoveToY(float y)
|
public void MoveToY(float y)
|
||||||
{
|
{
|
||||||
MoveY(y - (Y + remainder.Y), null);
|
MoveY(y - (Entity.Y + remainder.Y), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MoveExactX(int amount, delegate void(Collision) onCollide = null, Geometry pusher = null, Geometry carrier = null)
|
public bool MoveExactX(int amount, delegate void(Collision) onCollide = null)
|
||||||
{
|
{
|
||||||
int move = amount;
|
int move = amount;
|
||||||
int sign = Math.Sign(amount);
|
int sign = Math.Sign(amount);
|
||||||
bool byGeometry = carrier != null || pusher != null;
|
|
||||||
|
|
||||||
while (move != 0)
|
while (move != 0)
|
||||||
{
|
{
|
||||||
let hit = First<Solid>(.(sign, 0));
|
if (Check(Level, .(sign, 0)) || Hitbox.Check<Solid>(.(sign, 0)))
|
||||||
if (hit != null)
|
|
||||||
{
|
{
|
||||||
let c = Collision(
|
let c = Collision(
|
||||||
Cardinals.FromPoint(Point.Right * sign),
|
Cardinals.FromPoint(Point.Right * sign),
|
||||||
Math.Abs(amount),
|
Math.Abs(amount),
|
||||||
Math.Abs(amount - move),
|
Math.Abs(amount - move)
|
||||||
hit,
|
|
||||||
pusher
|
|
||||||
);
|
);
|
||||||
|
|
||||||
onCollide?.Invoke(c);
|
onCollide?.Invoke(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Check(Level, .(sign, 0)))
|
Entity.X += sign;
|
||||||
{
|
|
||||||
let c = Collision(
|
|
||||||
Cardinals.FromPoint(Point.Right * sign),
|
|
||||||
Math.Abs(amount),
|
|
||||||
Math.Abs(amount - move),
|
|
||||||
null,
|
|
||||||
pusher
|
|
||||||
);
|
|
||||||
|
|
||||||
onCollide?.Invoke(c);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
X += sign;
|
|
||||||
if (byGeometry)
|
|
||||||
MovedByGeometry.X += sign;
|
|
||||||
move -= sign;
|
move -= sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MoveExactY(int amount, delegate void(Collision) onCollide = null, Geometry pusher = null, Geometry carrier = null)
|
public bool MoveExactY(int amount, delegate void(Collision) onCollide = null)
|
||||||
{
|
{
|
||||||
int move = amount;
|
int move = amount;
|
||||||
int sign = Math.Sign(amount);
|
int sign = Math.Sign(amount);
|
||||||
bool byGeometry = carrier != null || pusher != null;
|
|
||||||
|
|
||||||
while (move != 0)
|
while (move != 0)
|
||||||
{
|
{
|
||||||
Geometry hit = First<Solid>(.(0, sign));
|
if (Check(Level, .(0, sign)) || Hitbox.Check<Solid>(.(0, sign)) || Hitbox.CheckOutside<JumpThru>(.(0, sign)))
|
||||||
if (hit == null && sign == 1)
|
|
||||||
hit = FirstOutside<JumpThru>(.(0, sign));
|
|
||||||
|
|
||||||
if (hit != null)
|
|
||||||
{
|
{
|
||||||
let c = Collision(
|
let c = Collision(
|
||||||
Cardinals.FromPoint(Point.Down * sign),
|
Cardinals.FromPoint(Point.Down * sign),
|
||||||
Math.Abs(amount),
|
Math.Abs(amount),
|
||||||
Math.Abs(amount - move),
|
Math.Abs(amount - move)
|
||||||
hit,
|
|
||||||
pusher
|
|
||||||
);
|
);
|
||||||
|
|
||||||
onCollide?.Invoke(c);
|
onCollide?.Invoke(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Check(Level, .(0, sign)))
|
Entity.Y += sign;
|
||||||
{
|
|
||||||
let c = Collision(
|
|
||||||
Cardinals.FromPoint(Point.Down * sign),
|
|
||||||
Math.Abs(amount),
|
|
||||||
Math.Abs(amount - move),
|
|
||||||
null,
|
|
||||||
pusher
|
|
||||||
);
|
|
||||||
|
|
||||||
onCollide?.Invoke(c);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Y += sign;
|
|
||||||
if (byGeometry)
|
|
||||||
MovedByGeometry.Y += sign;
|
|
||||||
move -= sign;
|
move -= sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public void ZeroRemainderX()
|
public void ZeroRemainderX()
|
||||||
{
|
{
|
||||||
remainder.X = 0;
|
remainder.X = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public void ZeroRemainderY()
|
public void ZeroRemainderY()
|
||||||
{
|
{
|
||||||
remainder.Y = 0;
|
remainder.Y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public void ZeroRemainders()
|
public void ZeroRemainders()
|
||||||
{
|
{
|
||||||
remainder = Vector.Zero;
|
remainder = Vector.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MoveByGeometry(Point amount)
|
|
||||||
{
|
|
||||||
MovedByGeometry += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CornerCorrection(Cardinals direction, int maxAmount, int lookAhead = 1, int onlySign = 0)
|
public bool CornerCorrection(Cardinals direction, int maxAmount, int lookAhead = 1, int onlySign = 0)
|
||||||
{
|
{
|
||||||
Point dir = direction;
|
Point dir = direction;
|
||||||
@ -215,10 +163,10 @@ namespace Strawberry.Sample
|
|||||||
perp.Y = Math.Abs(perp.Y);
|
perp.Y = Math.Abs(perp.Y);
|
||||||
|
|
||||||
delegate bool(Point) checker;
|
delegate bool(Point) checker;
|
||||||
if (dir == Point.Down)
|
if (dir == Point.Down)
|
||||||
checker = scope:: (p) => !Check(Level, p) && !Check<Solid>(p) && !CheckOutside<JumpThru>(p);
|
checker = scope:: (p) => !Check(Level, p) && !Hitbox.Check<Solid>(p) && !Hitbox.CheckOutside<JumpThru>(p);
|
||||||
else
|
else
|
||||||
checker = scope:: (p) => !Check(Level, p) && !Check<Solid>(p);
|
checker = scope:: (p) => !Check(Level, p) && !Hitbox.Check<Solid>(p);
|
||||||
|
|
||||||
for (int i = 1; i <= maxAmount; i++)
|
for (int i = 1; i <= maxAmount; i++)
|
||||||
{
|
{
|
||||||
@ -230,7 +178,7 @@ namespace Strawberry.Sample
|
|||||||
let offset = dir * lookAhead + perp * i * j;
|
let offset = dir * lookAhead + perp * i * j;
|
||||||
if (checker(offset))
|
if (checker(offset))
|
||||||
{
|
{
|
||||||
Position += offset;
|
Entity.Position += offset;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ using System;
|
|||||||
|
|
||||||
namespace Strawberry.Sample
|
namespace Strawberry.Sample
|
||||||
{
|
{
|
||||||
public class Player : Actor
|
public class Player : Component, IUpdate
|
||||||
{
|
{
|
||||||
public Vector Speed;
|
public Vector Speed;
|
||||||
|
|
||||||
@ -18,10 +18,8 @@ namespace Strawberry.Sample
|
|||||||
Add(tVarJump = new Timer());
|
Add(tVarJump = new Timer());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
|
||||||
|
|
||||||
const float coyoteTime = 0.1f; // Time after leaving a ledge when you can still jump
|
const float coyoteTime = 0.1f; // Time after leaving a ledge when you can still jump
|
||||||
const float varJumpTime = 0.2f; // Time after jumping that you can hold the jump button to continue gaining upward speed
|
const float varJumpTime = 0.2f; // Time after jumping that you can hold the jump button to continue gaining upward speed
|
||||||
const float jumpSpeed = -160;
|
const float jumpSpeed = -160;
|
||||||
|
@ -6,16 +6,12 @@ namespace Strawberry.Sample
|
|||||||
public Cardinals Direction;
|
public Cardinals Direction;
|
||||||
public int Magnitude;
|
public int Magnitude;
|
||||||
public int Completed;
|
public int Completed;
|
||||||
public Geometry Stopper;
|
|
||||||
public Geometry Pusher;
|
|
||||||
|
|
||||||
public this(Cardinals direction, int magnitude, int completed, Geometry stopper, Geometry pusher)
|
public this(Cardinals direction, int magnitude, int completed)
|
||||||
{
|
{
|
||||||
Direction = direction;
|
Direction = direction;
|
||||||
Magnitude = magnitude;
|
Magnitude = magnitude;
|
||||||
Completed = completed;
|
Completed = completed;
|
||||||
Stopper = stopper;
|
|
||||||
Pusher = pusher;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
namespace Strawberry.Sample
|
|
||||||
{
|
|
||||||
public abstract class Geometry : Entity
|
|
||||||
{
|
|
||||||
private Vector remainder;
|
|
||||||
|
|
||||||
public this(Point position)
|
|
||||||
: base(position)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MoveX(float amount)
|
|
||||||
{
|
|
||||||
remainder.X += amount;
|
|
||||||
let move = (int)Math.Round(remainder.X);
|
|
||||||
if (move != 0)
|
|
||||||
{
|
|
||||||
remainder.X -= move;
|
|
||||||
MoveExactX(move);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MoveY(float amount)
|
|
||||||
{
|
|
||||||
remainder.Y += amount;
|
|
||||||
let move = (int)Math.Round(remainder.Y);
|
|
||||||
if (move != 0)
|
|
||||||
{
|
|
||||||
remainder.Y -= move;
|
|
||||||
MoveExactY(move);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Inline]
|
|
||||||
public void Move(Vector amount)
|
|
||||||
{
|
|
||||||
MoveX(amount.X);
|
|
||||||
MoveY(amount.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Inline]
|
|
||||||
public void MoveToX(float x)
|
|
||||||
{
|
|
||||||
MoveX(x - (X + remainder.X));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Inline]
|
|
||||||
public void MoveToY(float y)
|
|
||||||
{
|
|
||||||
MoveY(y - (Y + remainder.Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Inline]
|
|
||||||
public void MoveTo(Vector target)
|
|
||||||
{
|
|
||||||
MoveToX(target.X);
|
|
||||||
MoveToY(target.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void MoveExactX(int amount);
|
|
||||||
public abstract void MoveExactY(int amount);
|
|
||||||
public abstract List<Actor> GetRiders(List<Actor> into);
|
|
||||||
|
|
||||||
public void ZeroRemainderX()
|
|
||||||
{
|
|
||||||
remainder.X = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ZeroRemainderY()
|
|
||||||
{
|
|
||||||
remainder.Y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ZeroRemainders()
|
|
||||||
{
|
|
||||||
remainder = Vector.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,80 +1,14 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Strawberry.Sample
|
namespace Strawberry.Sample
|
||||||
{
|
{
|
||||||
public class JumpThru : Geometry
|
public class JumpThru : Component, IHasHitbox
|
||||||
{
|
{
|
||||||
public this(Point position, int width)
|
public Hitbox Hitbox { get; private set; }
|
||||||
: base(position)
|
|
||||||
|
public this(Hitbox hitbox)
|
||||||
{
|
{
|
||||||
Hitbox = Rect(0, 0, width, 2);
|
Hitbox = hitbox;
|
||||||
}
|
|
||||||
|
|
||||||
public this(JSON json)
|
|
||||||
: this(.(json), json["width"])
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MoveExactX(int amount)
|
|
||||||
{
|
|
||||||
if (Collidable)
|
|
||||||
{
|
|
||||||
let riders = GetRiders(scope List<Actor>());
|
|
||||||
|
|
||||||
X += amount;
|
|
||||||
for (var a in riders)
|
|
||||||
a.MoveExactX(amount, null, null, this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
X += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MoveExactY(int amount)
|
|
||||||
{
|
|
||||||
if (Collidable)
|
|
||||||
{
|
|
||||||
let riders = GetRiders(scope List<Actor>());
|
|
||||||
|
|
||||||
if (amount < 0)
|
|
||||||
{
|
|
||||||
for (var a in Scene.All<Actor>(scope List<Actor>()))
|
|
||||||
{
|
|
||||||
if (riders.Contains(a) || CheckOutside(a, Point.UnitY * amount))
|
|
||||||
{
|
|
||||||
let move = (Top + amount) - a.Bottom;
|
|
||||||
a.MoveExactY(move, null, null, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Y += amount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Collidable = false;
|
|
||||||
|
|
||||||
for (var a in riders)
|
|
||||||
a.MoveExactY(amount, null, null, this);
|
|
||||||
|
|
||||||
Collidable = true;
|
|
||||||
Y += amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Y += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override List<Actor> GetRiders(List<Actor> into)
|
|
||||||
{
|
|
||||||
for (var a in Scene.All<Actor>(scope List<Actor>()))
|
|
||||||
if (a.IsRiding(this))
|
|
||||||
into.Add(a);
|
|
||||||
return into;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Draw()
|
|
||||||
{
|
|
||||||
DrawHitbox(.LightGray);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,93 +2,13 @@ using System.Collections;
|
|||||||
|
|
||||||
namespace Strawberry.Sample
|
namespace Strawberry.Sample
|
||||||
{
|
{
|
||||||
public class Solid : Geometry
|
public class Solid : Component, IHasHitbox
|
||||||
{
|
{
|
||||||
public this(Point position, Rect hitbox)
|
public Hitbox Hitbox { get; private set; }
|
||||||
: base(position)
|
|
||||||
|
public this(Hitbox hitbox)
|
||||||
{
|
{
|
||||||
Hitbox = hitbox;
|
Hitbox = hitbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override List<Actor> GetRiders(List<Actor> into)
|
|
||||||
{
|
|
||||||
for (var a in Scene.All<Actor>(scope List<Actor>()))
|
|
||||||
if (a.IsRiding(this))
|
|
||||||
into.Add(a);
|
|
||||||
return into;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MoveExactX(int amount)
|
|
||||||
{
|
|
||||||
if (Collidable)
|
|
||||||
{
|
|
||||||
let riders = GetRiders(scope List<Actor>());
|
|
||||||
|
|
||||||
X += amount;
|
|
||||||
Collidable = false;
|
|
||||||
|
|
||||||
for (Actor a in Scene.All<Actor>(scope List<Actor>()))
|
|
||||||
{
|
|
||||||
if (Check(a))
|
|
||||||
{
|
|
||||||
//Push
|
|
||||||
int move;
|
|
||||||
if (amount > 0)
|
|
||||||
move = Right - a.Left;
|
|
||||||
else
|
|
||||||
move = Left - a.Right;
|
|
||||||
a.MoveExactX(move, scope => a.Squish, this);
|
|
||||||
}
|
|
||||||
else if (riders.Contains(a))
|
|
||||||
{
|
|
||||||
//Carry
|
|
||||||
a.MoveExactX(amount, null, null, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collidable = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
X += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MoveExactY(int amount)
|
|
||||||
{
|
|
||||||
if (Collidable)
|
|
||||||
{
|
|
||||||
let riders = GetRiders(scope List<Actor>());
|
|
||||||
|
|
||||||
Y += amount;
|
|
||||||
Collidable = false;
|
|
||||||
|
|
||||||
for (Actor a in Scene.All<Actor>(scope List<Actor>()))
|
|
||||||
{
|
|
||||||
if (Check(a))
|
|
||||||
{
|
|
||||||
//Push
|
|
||||||
int move;
|
|
||||||
if (amount > 0)
|
|
||||||
move = Bottom - a.Top;
|
|
||||||
else
|
|
||||||
move = Top - a.Bottom;
|
|
||||||
a.MoveExactY(move, scope => a.Squish, this);
|
|
||||||
}
|
|
||||||
else if (riders.Contains(a))
|
|
||||||
{
|
|
||||||
//Carry
|
|
||||||
a.MoveExactY(amount, null, null, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collidable = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Y += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Draw()
|
|
||||||
{
|
|
||||||
DrawHitbox(.White);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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;
|
using System.Collections;
|
||||||
namespace Strawberry
|
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.
|
// Takes as parameter the T collided with. Return false to stop checking for collisions until next frame.
|
||||||
public delegate bool(T) Action;
|
public delegate bool(T) Action;
|
||||||
|
|
||||||
public this(delegate bool(T) action)
|
public this(Hitbox hitbox, delegate bool(T) action)
|
||||||
: base(true, false)
|
|
||||||
{
|
{
|
||||||
|
Hitbox = hitbox;
|
||||||
Action = action;
|
Action = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,13 +19,13 @@ namespace Strawberry
|
|||||||
delete Action;
|
delete Action;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (Action != null)
|
if (Action != null)
|
||||||
{
|
{
|
||||||
let list = Entity.Scene.All<T>(scope List<T>());
|
let list = Entity.Scene.All<T>(scope List<T>());
|
||||||
for (let t in list)
|
for (let t in list)
|
||||||
if (Entity.Check(t) && !Action(t))
|
if (Hitbox.Check(t) && !Action(t))
|
||||||
break;
|
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
|
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 Dictionary<TIndex, State> states = new Dictionary<TIndex, State>() ~ delete _;
|
||||||
private TIndex state;
|
private TIndex state;
|
||||||
@ -14,7 +14,6 @@ namespace Strawberry
|
|||||||
public TIndex NextState { get; private set; }
|
public TIndex NextState { get; private set; }
|
||||||
|
|
||||||
public this(TIndex startState)
|
public this(TIndex startState)
|
||||||
: base(true, false)
|
|
||||||
{
|
{
|
||||||
NextState = PreviousState = state = startState;
|
NextState = PreviousState = state = startState;
|
||||||
}
|
}
|
||||||
@ -30,7 +29,7 @@ namespace Strawberry
|
|||||||
CallEnter();
|
CallEnter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
CallUpdate();
|
CallUpdate();
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,27 @@ using System.Diagnostics;
|
|||||||
|
|
||||||
namespace Strawberry
|
namespace Strawberry
|
||||||
{
|
{
|
||||||
public class Timer : Component
|
public class Timer : Component, IUpdate
|
||||||
{
|
{
|
||||||
private float value;
|
private float value;
|
||||||
|
|
||||||
public Action OnComplete ~ delete _;
|
public Action OnComplete ~ delete _;
|
||||||
public bool RemoveOnComplete;
|
public bool RemoveOnComplete;
|
||||||
|
|
||||||
public this()
|
|
||||||
: base(false, false)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(Action onComplete, bool destroyOnComplete = false)
|
public this(Action onComplete, bool destroyOnComplete = false)
|
||||||
: base(false, false)
|
|
||||||
{
|
{
|
||||||
OnComplete = onComplete;
|
OnComplete = onComplete;
|
||||||
RemoveOnComplete = destroyOnComplete;
|
RemoveOnComplete = destroyOnComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
public this(float value, Action onComplete, bool destroyOnComplete = false)
|
public this(float value, Action onComplete, bool destroyOnComplete = false)
|
||||||
: base(false, false)
|
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
OnComplete = onComplete;
|
OnComplete = onComplete;
|
||||||
RemoveOnComplete = destroyOnComplete;
|
RemoveOnComplete = destroyOnComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (value > 0)
|
if (value > 0)
|
||||||
{
|
{
|
||||||
@ -39,8 +31,6 @@ namespace Strawberry
|
|||||||
if (value <= 0)
|
if (value <= 0)
|
||||||
{
|
{
|
||||||
value = 0;
|
value = 0;
|
||||||
Active = false;
|
|
||||||
|
|
||||||
OnComplete?.Invoke();
|
OnComplete?.Invoke();
|
||||||
if (RemoveOnComplete)
|
if (RemoveOnComplete)
|
||||||
RemoveSelf();
|
RemoveSelf();
|
||||||
@ -60,7 +50,6 @@ namespace Strawberry
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
this.value = Math.Max(0, value);
|
this.value = Math.Max(0, value);
|
||||||
Active = (this.value > 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +57,6 @@ namespace Strawberry
|
|||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
value = 0;
|
value = 0;
|
||||||
Active = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static public implicit operator bool(Timer timer)
|
static public implicit operator bool(Timer timer)
|
||||||
|
@ -1,33 +1,42 @@
|
|||||||
using System;
|
using System;
|
||||||
namespace Strawberry
|
namespace Strawberry
|
||||||
{
|
{
|
||||||
public class Tween : Component
|
public class Tween : Component, IUpdate
|
||||||
{
|
{
|
||||||
public Ease.Easer Easer ~ delete _;
|
public Ease.Easer Easer ~ delete _;
|
||||||
public delegate void(float) OnUpdate ~ delete _;
|
public delegate void(float) OnUpdate ~ delete _;
|
||||||
public delegate void() OnComplete ~ delete _;
|
public delegate void() OnComplete ~ delete _;
|
||||||
public bool RemoveOnComplete;
|
public bool RemoveOnComplete;
|
||||||
|
|
||||||
|
public bool Playing { get; private set; }
|
||||||
public float T { 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)
|
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;
|
Easer = easer;
|
||||||
OnUpdate = onUpdate;
|
OnUpdate = onUpdate;
|
||||||
OnComplete = onComplete;
|
OnComplete = onComplete;
|
||||||
RemoveOnComplete = removeOnComplete;
|
RemoveOnComplete = removeOnComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public float Eased => Easer != null ? Easer(T) : T;
|
public float Eased => Easer != null ? Easer(T) : T;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
T = 0;
|
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);
|
T = Math.Min(T + Time.Delta, 1);
|
||||||
OnUpdate?.Invoke(Eased);
|
OnUpdate?.Invoke(Eased);
|
||||||
@ -35,7 +44,7 @@ namespace Strawberry
|
|||||||
if (T >= 1)
|
if (T >= 1)
|
||||||
{
|
{
|
||||||
OnComplete?.Invoke();
|
OnComplete?.Invoke();
|
||||||
Active = false;
|
Playing = false;
|
||||||
if (RemoveOnComplete)
|
if (RemoveOnComplete)
|
||||||
RemoveSelf();
|
RemoveSelf();
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,6 @@ namespace Strawberry
|
|||||||
{
|
{
|
||||||
public Entity Entity { get; private set; }
|
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)
|
private void Added(Entity entity)
|
||||||
{
|
{
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
@ -27,13 +18,20 @@ namespace Strawberry
|
|||||||
|
|
||||||
public virtual void Started() { }
|
public virtual void Started() { }
|
||||||
public virtual void Ended() { }
|
public virtual void Ended() { }
|
||||||
public virtual void Update() { }
|
|
||||||
public virtual void Draw() { }
|
|
||||||
|
|
||||||
[Inline]
|
[Inline]
|
||||||
public void RemoveSelf()
|
public void RemoveSelf()
|
||||||
{
|
{
|
||||||
Entity?.Remove(this);
|
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
|
namespace Strawberry
|
||||||
{
|
{
|
||||||
public abstract class Entity
|
public sealed class Entity
|
||||||
{
|
{
|
||||||
public Scene Scene { get; private set; }
|
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;
|
public bool DeleteOnRemove = true;
|
||||||
|
|
||||||
private List<Component> components = new List<Component>() ~ delete _;
|
private List<Component> components = new List<Component>() ~ delete _;
|
||||||
@ -40,32 +36,18 @@ namespace Strawberry
|
|||||||
Scene = null;
|
Scene = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Started()
|
public void Started()
|
||||||
{
|
{
|
||||||
for (var c in components)
|
for (var c in components)
|
||||||
c.Started();
|
c.Started();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Ended()
|
public void Ended()
|
||||||
{
|
{
|
||||||
for (var c in components)
|
for (var c in components)
|
||||||
c.Ended();
|
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]
|
[Inline]
|
||||||
public void RemoveSelf()
|
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 =====
|
// ===== Misc =====
|
||||||
|
|
||||||
public void DrawHitbox(Color color)
|
[Inline]
|
||||||
{
|
|
||||||
Game.Batcher.Rect(SceneHitbox, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DrawHitboxOutline(Color color)
|
|
||||||
{
|
|
||||||
Game.Batcher.Rect(SceneHitboxOutline, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T SceneAs<T>() where T : Scene
|
public T SceneAs<T>() where T : Scene
|
||||||
{
|
{
|
||||||
Runtime.Assert(Scene is T, "Scene type mismatch!");
|
Runtime.Assert(Scene is T, "Scene type mismatch!");
|
||||||
return Scene as T;
|
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 scene;
|
||||||
private Scene switchToScene;
|
private Scene switchToScene;
|
||||||
private bool updating;
|
private bool updating;
|
||||||
private Dictionary<Type, List<Type>> entityAssignableLists;
|
|
||||||
private Dictionary<Type, List<Type>> componentAssignableLists;
|
|
||||||
|
|
||||||
public PlatformLayer PlatformLayer { get; private set; }
|
public PlatformLayer PlatformLayer { get; private set; }
|
||||||
public Batcher Batcher { get; private set; }
|
public Batcher Batcher { get; private set; }
|
||||||
@ -60,9 +58,9 @@ namespace Strawberry
|
|||||||
VirtualInputs = new List<VirtualInput>();
|
VirtualInputs = new List<VirtualInput>();
|
||||||
Input.[Friend]Init();
|
Input.[Friend]Init();
|
||||||
|
|
||||||
BuildTypeLists();
|
Tracker.[Friend]BuildAssignmentLists();
|
||||||
Assets.LoadAll();
|
Assets.LoadAll();
|
||||||
Strawberry.Console.Init();
|
Strawberry.StrwConsole.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
@ -83,9 +81,8 @@ namespace Strawberry
|
|||||||
}
|
}
|
||||||
|
|
||||||
Assets.DisposeAll();
|
Assets.DisposeAll();
|
||||||
DisposeTypeLists();
|
|
||||||
Input.[Friend]Dispose();
|
Input.[Friend]Dispose();
|
||||||
Strawberry.Console.Dispose();
|
Strawberry.StrwConsole.Dispose();
|
||||||
|
|
||||||
delete Batcher;
|
delete Batcher;
|
||||||
|
|
||||||
@ -157,7 +154,7 @@ namespace Strawberry
|
|||||||
Time.Elapsed += Time.Delta;
|
Time.Elapsed += Time.Delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
Strawberry.Console.[Friend]Update();
|
Strawberry.StrwConsole.[Friend]Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Render()
|
private void Render()
|
||||||
@ -171,8 +168,8 @@ namespace Strawberry
|
|||||||
{
|
{
|
||||||
Scene?.Draw();
|
Scene?.Draw();
|
||||||
|
|
||||||
if (Strawberry.Console.Enabled)
|
if (Strawberry.StrwConsole.Enabled)
|
||||||
Strawberry.Console.[Friend]Draw();
|
Strawberry.StrwConsole.[Friend]Draw();
|
||||||
|
|
||||||
Batcher.Draw();
|
Batcher.Draw();
|
||||||
}
|
}
|
||||||
@ -191,57 +188,5 @@ namespace Strawberry
|
|||||||
switchToScene = value;
|
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 List<Entity> entities;
|
||||||
private HashSet<Entity> toRemove;
|
private HashSet<Entity> toRemove;
|
||||||
private HashSet<Entity> toAdd;
|
private HashSet<Entity> toAdd;
|
||||||
private Dictionary<Type, List<Entity>> entityTracker;
|
|
||||||
private Dictionary<Type, List<Component>> componentTracker;
|
private Dictionary<Type, List<Component>> componentTracker;
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
@ -19,12 +18,10 @@ namespace Strawberry
|
|||||||
toAdd = new HashSet<Entity>();
|
toAdd = new HashSet<Entity>();
|
||||||
toRemove = 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>>();
|
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>());
|
componentTracker.Add(type, new List<Component>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,10 +39,6 @@ namespace Strawberry
|
|||||||
|
|
||||||
delete toRemove;
|
delete toRemove;
|
||||||
|
|
||||||
for (let list in entityTracker.Values)
|
|
||||||
delete list;
|
|
||||||
delete entityTracker;
|
|
||||||
|
|
||||||
for (let list in componentTracker.Values)
|
for (let list in componentTracker.Values)
|
||||||
delete list;
|
delete list;
|
||||||
delete componentTracker;
|
delete componentTracker;
|
||||||
@ -59,26 +52,23 @@ namespace Strawberry
|
|||||||
public virtual void Update()
|
public virtual void Update()
|
||||||
{
|
{
|
||||||
UpdateLists();
|
UpdateLists();
|
||||||
for (let e in entities)
|
|
||||||
if (e.Active)
|
|
||||||
e.Update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Draw()
|
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)
|
if (e.Scene == null)
|
||||||
toAdd.Add(e);
|
toAdd.Add(e);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T Remove<T>(T e) where T : Entity
|
public Entity Remove(Entity e)
|
||||||
{
|
{
|
||||||
if (e.Scene == this)
|
if (e.Scene == this)
|
||||||
toRemove.Add(e);
|
toRemove.Add(e);
|
||||||
@ -92,7 +82,6 @@ namespace Strawberry
|
|||||||
for (let e in toRemove)
|
for (let e in toRemove)
|
||||||
{
|
{
|
||||||
entities.Remove(e);
|
entities.Remove(e);
|
||||||
UntrackEntity(e);
|
|
||||||
e.[Friend]Removed();
|
e.[Friend]Removed();
|
||||||
if (e.DeleteOnRemove)
|
if (e.DeleteOnRemove)
|
||||||
delete e;
|
delete e;
|
||||||
@ -106,11 +95,8 @@ namespace Strawberry
|
|||||||
for (let e in toAdd)
|
for (let e in toAdd)
|
||||||
{
|
{
|
||||||
entities.Add(e);
|
entities.Add(e);
|
||||||
TrackEntity(e);
|
|
||||||
e.[Friend]Added(this);
|
e.[Friend]Added(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
entities.Sort(scope => Entity.Compare);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let e in entities)
|
for (let e in entities)
|
||||||
@ -126,33 +112,15 @@ namespace Strawberry
|
|||||||
|
|
||||||
// Tracking
|
// 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)
|
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);
|
componentTracker[t].Add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UntrackComponent(Component 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);
|
componentTracker[t].Remove(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,75 +139,6 @@ namespace Strawberry
|
|||||||
return (TimeElapsed - offset) % (interval * 2) >= interval;
|
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
|
Finding Components
|
||||||
*/
|
*/
|
||||||
@ -249,25 +148,64 @@ namespace Strawberry
|
|||||||
return componentTracker[typeof(T)].Count;
|
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);
|
into.Add(c as T);
|
||||||
return into;
|
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)])
|
for (T c in componentTracker[typeof(T)])
|
||||||
if (c.Entity.Check(point))
|
if (c.Hitbox.Check(point))
|
||||||
into.Add(c as T);
|
into.Add(c as T);
|
||||||
return into;
|
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)])
|
for (T c in componentTracker[typeof(T)])
|
||||||
if (c.Entity.Check(rect))
|
if (c.Hitbox.Check(rect))
|
||||||
into.Add(c as T);
|
into.Add(c as T);
|
||||||
return into;
|
return into;
|
||||||
}
|
}
|
||||||
|
@ -143,9 +143,14 @@ namespace Strawberry
|
|||||||
return p.X >= 0 && p.Y >= 0 && p.X < CellsX && p.Y < CellsY;
|
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)
|
public bool Check(Rect rect)
|
||||||
|
@ -19,7 +19,7 @@ namespace Strawberry
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Reflect]
|
[Reflect]
|
||||||
static public class Console
|
static public class StrwConsole
|
||||||
{
|
{
|
||||||
static public bool Open;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user