mirror of
https://github.com/MaddyThorson/StrawberryBF.git
synced 2024-11-25 16:18:56 +08:00
Initial commit
This commit is contained in:
commit
4a44eb0f26
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
8
BeefProj.toml
Normal file
8
BeefProj.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FileVersion = 1
|
||||||
|
Dependencies = {corlib = "*", SDL2 = "*"}
|
||||||
|
|
||||||
|
[Project]
|
||||||
|
Name = "Strawberry"
|
||||||
|
TargetType = "BeefLib"
|
||||||
|
StartupObject = "Program"
|
||||||
|
DefaultNamespace = "Strawberry"
|
16
src/Draw.bf
Normal file
16
src/Draw.bf
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
static public class Draw
|
||||||
|
{
|
||||||
|
static public void Rect(int x, int y, int w, int h, SDL2.SDL.Color color)
|
||||||
|
{
|
||||||
|
SDL2.SDL.SetRenderDrawColor(Game.mRenderer, color.r, color.g, color.b, color.a);
|
||||||
|
SDL2.SDL.RenderFillRect(Game.mRenderer, &SDL2.SDL.Rect((int32)x, (int32)y, (int32)w, (int32)h));
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void Rect(Rect rect, SDL2.SDL.Color color)
|
||||||
|
{
|
||||||
|
Rect(rect.X, rect.Y, rect.Width, rect.Height, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
347
src/Entity.bf
Normal file
347
src/Entity.bf
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace BeefMonocle
|
||||||
|
{
|
||||||
|
public class Entity
|
||||||
|
{
|
||||||
|
public Scene Scene { get; private set; }
|
||||||
|
public int Depth;
|
||||||
|
public bool Active = true;
|
||||||
|
public bool Visible = true;
|
||||||
|
public bool Collidable = true;
|
||||||
|
public bool DeleteOnRemove = true;
|
||||||
|
|
||||||
|
public this(int x, int y)
|
||||||
|
{
|
||||||
|
Positionf = .(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Added(Scene scene)
|
||||||
|
{
|
||||||
|
Scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Removed()
|
||||||
|
{
|
||||||
|
Scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Started()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Draw()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== Position =====
|
||||||
|
|
||||||
|
public Vector Positionf;
|
||||||
|
|
||||||
|
public float Xf
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Positionf.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Positionf.X = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Yf
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Positionf.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Positionf.Y = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point Position
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Positionf.Round();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Positionf = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int X
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (int)Math.Round(Positionf.X);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Positionf.X = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Y
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (int)Math.Round(Positionf.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Positionf.Y = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 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 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(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 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(SDL2.SDL.Color color)
|
||||||
|
{
|
||||||
|
Draw.Rect(SceneHitbox, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public int operator<=>(Entity a, Entity b)
|
||||||
|
{
|
||||||
|
return a.Depth <=> b.Depth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
src/Game.bf
Normal file
105
src/Game.bf
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
using SDL2;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace BeefMonocle
|
||||||
|
{
|
||||||
|
static
|
||||||
|
{
|
||||||
|
static public Game Game;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Game : SDLApp
|
||||||
|
{
|
||||||
|
public List<VirtualInput> VirtualInputs;
|
||||||
|
public float DeltaTime { get; private set; }
|
||||||
|
public float Time { get; private set; }
|
||||||
|
public float PreviousTime { get; private set; }
|
||||||
|
|
||||||
|
private Scene scene;
|
||||||
|
private Scene switchToScene;
|
||||||
|
private bool updating;
|
||||||
|
private SDL.Rect screenRect;
|
||||||
|
|
||||||
|
public this(String windowTitle, int32 width, int32 height)
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
Game = this;
|
||||||
|
VirtualInputs = new List<VirtualInput>();
|
||||||
|
DeltaTime = 1 / 60f;
|
||||||
|
|
||||||
|
mTitle.Set(windowTitle);
|
||||||
|
mWidth = width;
|
||||||
|
mHeight = height;
|
||||||
|
|
||||||
|
screenRect = SDL.Rect(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
if (scene != null)
|
||||||
|
delete scene;
|
||||||
|
|
||||||
|
if (switchToScene != scene && switchToScene != null)
|
||||||
|
delete switchToScene;
|
||||||
|
|
||||||
|
delete VirtualInputs;
|
||||||
|
|
||||||
|
Game = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new virtual void Init()
|
||||||
|
{
|
||||||
|
base.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
//Switch scenes
|
||||||
|
if (switchToScene != scene)
|
||||||
|
{
|
||||||
|
if (scene != null)
|
||||||
|
delete scene;
|
||||||
|
scene = switchToScene;
|
||||||
|
scene.Started();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i in VirtualInputs)
|
||||||
|
i.Update();
|
||||||
|
|
||||||
|
if (scene != null)
|
||||||
|
scene.Update();
|
||||||
|
|
||||||
|
PreviousTime = Time;
|
||||||
|
Time += DeltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
base.Draw();
|
||||||
|
|
||||||
|
SDL2.SDL.SetRenderDrawColor(mRenderer, 0, 0, 0, 255);
|
||||||
|
SDL2.SDL.RenderFillRect(mRenderer, &screenRect);
|
||||||
|
|
||||||
|
if (Scene != null)
|
||||||
|
Scene.Draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scene Scene
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (switchToScene != scene && switchToScene != null)
|
||||||
|
delete switchToScene;
|
||||||
|
switchToScene = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
194
src/Input/VirtualAxis.bf
Normal file
194
src/Input/VirtualAxis.bf
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public class VirtualAxis : VirtualInput
|
||||||
|
{
|
||||||
|
public enum OverlapBehaviors { TakeNewer, TakeOlder, CancelOut }
|
||||||
|
|
||||||
|
public float Value { get; private set; }
|
||||||
|
public int IntValue { get; private set; }
|
||||||
|
public bool Pressed { get; private set; }
|
||||||
|
public bool Released { get; private set; }
|
||||||
|
public bool Repeating { get; private set; }
|
||||||
|
|
||||||
|
private List<Node> nodes;
|
||||||
|
private float pressBuffer;
|
||||||
|
private float releaseBuffer;
|
||||||
|
private float repeatStart;
|
||||||
|
private float repeatInterval;
|
||||||
|
|
||||||
|
private float lastPress;
|
||||||
|
private float lastRelease;
|
||||||
|
private float lastPressClear;
|
||||||
|
private float lastReleaseClear;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
nodes = new List<Node>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
for (var n in nodes)
|
||||||
|
delete n;
|
||||||
|
delete nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
for (var n in nodes)
|
||||||
|
n.Update();
|
||||||
|
|
||||||
|
//Value
|
||||||
|
let last = IntValue;
|
||||||
|
Value = 0;
|
||||||
|
for (var n in nodes)
|
||||||
|
{
|
||||||
|
if (n.Value != 0)
|
||||||
|
{
|
||||||
|
Value = n.Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IntValue = Math.Sign(Value);
|
||||||
|
|
||||||
|
//Press
|
||||||
|
if (last != IntValue && IntValue != 0)
|
||||||
|
lastPress = Game.Time;
|
||||||
|
Pressed = IntValue != 0 && lastPress > lastPressClear && Game.Time - lastPress <= pressBuffer;
|
||||||
|
|
||||||
|
//Repeat
|
||||||
|
if (IntValue != 0 && repeatStart > 0 && Game.Time - lastPress >= repeatStart)
|
||||||
|
{
|
||||||
|
Repeating = true;
|
||||||
|
|
||||||
|
int a = (int)((Game.PreviousTime - lastPress) / repeatInterval);
|
||||||
|
int b = (int)((Game.Time - lastPress) / repeatInterval);
|
||||||
|
if (a != b)
|
||||||
|
Pressed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Repeating = false;
|
||||||
|
|
||||||
|
//Release
|
||||||
|
if (last != 0 && IntValue == 0)
|
||||||
|
lastRelease = Game.Time;
|
||||||
|
Released = IntValue == 0 && lastRelease > lastReleaseClear && Game.Time - lastRelease <= releaseBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearPressBuffer()
|
||||||
|
{
|
||||||
|
lastPressClear = Game.Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearReleaseBuffer()
|
||||||
|
{
|
||||||
|
lastReleaseClear = Game.Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup Calls
|
||||||
|
|
||||||
|
public VirtualAxis Keys(SDL2.SDL.Scancode negativeKey, SDL2.SDL.Scancode positiveKey, OverlapBehaviors overlapBehavior = .TakeNewer)
|
||||||
|
{
|
||||||
|
nodes.Add(new KeyboardKeys(negativeKey, positiveKey, overlapBehavior));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualAxis PressBuffer(float time)
|
||||||
|
{
|
||||||
|
pressBuffer = time;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualAxis ReleaseBuffer(float time)
|
||||||
|
{
|
||||||
|
releaseBuffer = time;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualAxis Repeat(float start, float interval)
|
||||||
|
{
|
||||||
|
repeatStart = start;
|
||||||
|
repeatInterval = interval;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nodes
|
||||||
|
|
||||||
|
private abstract class Node
|
||||||
|
{
|
||||||
|
public abstract float Value { get; }
|
||||||
|
public virtual void Update() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class KeyboardKeys : Node
|
||||||
|
{
|
||||||
|
public OverlapBehaviors OverlapBehavior;
|
||||||
|
public SDL2.SDL.Scancode NegativeKeycode;
|
||||||
|
public SDL2.SDL.Scancode PositiveKeycode;
|
||||||
|
|
||||||
|
private float value;
|
||||||
|
private bool turned;
|
||||||
|
|
||||||
|
public this(SDL2.SDL.Scancode negativeKey, SDL2.SDL.Scancode positiveKey, OverlapBehaviors overlapBehavior = .TakeNewer)
|
||||||
|
{
|
||||||
|
NegativeKeycode = negativeKey;
|
||||||
|
PositiveKeycode = positiveKey;
|
||||||
|
OverlapBehavior = overlapBehavior;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
if (Game.IsKeyDown(PositiveKeycode))
|
||||||
|
{
|
||||||
|
if (Game.IsKeyDown(NegativeKeycode))
|
||||||
|
{
|
||||||
|
switch (OverlapBehavior)
|
||||||
|
{
|
||||||
|
case OverlapBehaviors.CancelOut:
|
||||||
|
value = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OverlapBehaviors.TakeNewer:
|
||||||
|
if (!turned)
|
||||||
|
{
|
||||||
|
value *= -1;
|
||||||
|
turned = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OverlapBehaviors.TakeOlder:
|
||||||
|
//value stays the same
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
turned = false;
|
||||||
|
value = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Game.IsKeyDown(NegativeKeycode))
|
||||||
|
{
|
||||||
|
turned = false;
|
||||||
|
value = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
turned = false;
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
src/Input/VirtualButton.bf
Normal file
137
src/Input/VirtualButton.bf
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public class VirtualButton : VirtualInput
|
||||||
|
{
|
||||||
|
public bool Check { get; private set; }
|
||||||
|
public bool Pressed { get; private set; }
|
||||||
|
public bool Released { get; private set; }
|
||||||
|
public bool Repeating { get; private set; }
|
||||||
|
|
||||||
|
private List<Node> nodes;
|
||||||
|
private float pressBuffer;
|
||||||
|
private float releaseBuffer;
|
||||||
|
private float repeatStart;
|
||||||
|
private float repeatInterval;
|
||||||
|
|
||||||
|
private float lastPress;
|
||||||
|
private float lastRelease;
|
||||||
|
private float lastPressClear;
|
||||||
|
private float lastReleaseClear;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
nodes = new List<Node>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
for (var n in nodes)
|
||||||
|
delete n;
|
||||||
|
delete nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
override public void Update()
|
||||||
|
{
|
||||||
|
//Check
|
||||||
|
let last = Check;
|
||||||
|
Check = false;
|
||||||
|
for (var n in nodes)
|
||||||
|
{
|
||||||
|
if (n.Check)
|
||||||
|
{
|
||||||
|
Check = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Press
|
||||||
|
if (!last && Check)
|
||||||
|
lastPress = Game.Time;
|
||||||
|
Pressed = Check && lastPress > lastPressClear && Game.Time - lastPress <= pressBuffer;
|
||||||
|
|
||||||
|
//Repeat
|
||||||
|
if (Check && repeatStart > 0 && Game.Time - lastPress >= repeatStart)
|
||||||
|
{
|
||||||
|
Repeating = true;
|
||||||
|
|
||||||
|
int a = (int)((Game.PreviousTime - lastPress) / repeatInterval);
|
||||||
|
int b = (int)((Game.Time - lastPress) / repeatInterval);
|
||||||
|
if (a != b)
|
||||||
|
Pressed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Repeating = false;
|
||||||
|
|
||||||
|
//Release
|
||||||
|
if (last && !Check)
|
||||||
|
lastRelease = Game.Time;
|
||||||
|
Released = !Check && lastRelease > lastReleaseClear && Game.Time - lastRelease <= releaseBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearPressBuffer()
|
||||||
|
{
|
||||||
|
lastPressClear = Game.Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearReleaseBuffer()
|
||||||
|
{
|
||||||
|
lastReleaseClear = Game.Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup Calls
|
||||||
|
|
||||||
|
public VirtualButton Key(SDL2.SDL.Scancode keycode)
|
||||||
|
{
|
||||||
|
nodes.Add(new KeyboardKey(keycode));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualButton PressBuffer(float time)
|
||||||
|
{
|
||||||
|
pressBuffer = time;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualButton ReleaseBuffer(float time)
|
||||||
|
{
|
||||||
|
releaseBuffer = time;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualButton Repeat(float start, float interval)
|
||||||
|
{
|
||||||
|
repeatStart = start;
|
||||||
|
repeatInterval = interval;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nodes
|
||||||
|
|
||||||
|
private abstract class Node
|
||||||
|
{
|
||||||
|
public abstract bool Check { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class KeyboardKey : Node
|
||||||
|
{
|
||||||
|
public SDL2.SDL.Scancode Keycode;
|
||||||
|
|
||||||
|
public this(SDL2.SDL.Scancode keycode)
|
||||||
|
{
|
||||||
|
Keycode = keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
override public bool Check
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Game.IsKeyDown(Keycode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
src/Input/VirtualInput.bf
Normal file
20
src/Input/VirtualInput.bf
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public abstract class VirtualInput
|
||||||
|
{
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
Game.VirtualInputs.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
Game.VirtualInputs.Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
src/Numerics/Point.bf
Normal file
58
src/Numerics/Point.bf
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public struct Point
|
||||||
|
{
|
||||||
|
static public readonly Point Right = Point(1, 0);
|
||||||
|
static public readonly Point Left = Point(-1, 0);
|
||||||
|
static public readonly Point Up = Point(0, -1);
|
||||||
|
static public readonly Point Down = Point(0, 1);
|
||||||
|
static public readonly Point Zero = Point(0, 0);
|
||||||
|
static public readonly Point One = Point(1, 1);
|
||||||
|
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
this = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(int x, int y)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public explicit operator Point(Vector a)
|
||||||
|
{
|
||||||
|
return Point((int)a.X, (int)a.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public bool operator==(Point a, Point b)
|
||||||
|
{
|
||||||
|
return a.X == b.X && a.Y == b.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Point operator+(Point a, Point b)
|
||||||
|
{
|
||||||
|
return Point(a.X + b.X, a.Y + b.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Point operator-(Point a, Point b)
|
||||||
|
{
|
||||||
|
return Point(a.X - b.X, a.Y - b.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Point operator*(Point a, int b)
|
||||||
|
{
|
||||||
|
return Point(a.X * b, a.Y * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Point operator/(Point a, int b)
|
||||||
|
{
|
||||||
|
return Point(a.X / b, a.Y / b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
129
src/Numerics/Rect.bf
Normal file
129
src/Numerics/Rect.bf
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public struct Rect
|
||||||
|
{
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
public int Width;
|
||||||
|
public int Height;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
this = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(int x, int y, int width, int height)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Left
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return X;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
X = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Right
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return X + Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
X = value - Width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Top
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
Y = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Bottom
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Y + Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
Y = value - Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect MirrorX(int axis = 0)
|
||||||
|
{
|
||||||
|
var rect = this;
|
||||||
|
rect.X = axis - X - Width;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect MirrorY(int axis = 0)
|
||||||
|
{
|
||||||
|
var rect = this;
|
||||||
|
rect.Y = axis - Y - Height;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect Inflate(int amount)
|
||||||
|
{
|
||||||
|
return Rect(X - amount, Y - amount, Width + amount * 2, Height + amount * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Intersects(Rect rect)
|
||||||
|
{
|
||||||
|
return (X + Width) > rect.X && (rect.X + rect.Width) > X && (Y + Height) > rect.Y && (rect.Y + rect.Height) > Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(Point point)
|
||||||
|
{
|
||||||
|
return point.X >= X && point.X < X + Width && point.Y >= Y && point.Y < Y + Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public bool operator==(Rect a, Rect b)
|
||||||
|
{
|
||||||
|
return a.X == b.X && a.Y == b.Y && a.Width == b.Width && a.Height == b.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Rect operator+(Rect a, Point b)
|
||||||
|
{
|
||||||
|
return Rect(a.X + b.X, a.Y + b.Y, a.Width, a.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Rect operator-(Rect a, Point b)
|
||||||
|
{
|
||||||
|
return Rect(a.X - b.X, a.Y - b.Y, a.Width, a.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
82
src/Numerics/Vector.bf
Normal file
82
src/Numerics/Vector.bf
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public struct Vector
|
||||||
|
{
|
||||||
|
static public readonly Vector Right = Vector(1, 0);
|
||||||
|
static public readonly Vector Left = Vector(-1, 0);
|
||||||
|
static public readonly Vector Up = Vector(0, -1);
|
||||||
|
static public readonly Vector Down = Vector(0, 1);
|
||||||
|
static public readonly Vector Zero = Vector(0, 0);
|
||||||
|
static public readonly Vector One = Vector(1, 1);
|
||||||
|
|
||||||
|
public float X;
|
||||||
|
public float Y;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
this = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(float x, float y)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Length
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Math.Sqrt(LengthSquared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float LengthSquared
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return X * X + Y * Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public Point Round()
|
||||||
|
{
|
||||||
|
return Point((int)Math.Round(X), (int)Math.Round(Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
static public operator Vector(Point a)
|
||||||
|
{
|
||||||
|
return Vector(a.X, a.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public bool operator==(Vector a, Vector b)
|
||||||
|
{
|
||||||
|
return a.X == b.X && a.Y == b.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Vector operator+(Vector a, Vector b)
|
||||||
|
{
|
||||||
|
return Vector(a.X + b.X, a.Y + b.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Vector operator-(Vector a, Vector b)
|
||||||
|
{
|
||||||
|
return Vector(a.X - b.X, a.Y - b.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Vector operator*(Vector a, float b)
|
||||||
|
{
|
||||||
|
return Vector(a.X * b, a.Y * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Vector operator/(Vector a, float b)
|
||||||
|
{
|
||||||
|
return Vector(a.X / b, a.Y / b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
112
src/Physics/Actor.bf
Normal file
112
src/Physics/Actor.bf
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
[Reflect]
|
||||||
|
public class Actor : Entity
|
||||||
|
{
|
||||||
|
private Vector remainder;
|
||||||
|
|
||||||
|
public this(int x, int y)
|
||||||
|
: base(x, y)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GroundCheck(int distance = 1)
|
||||||
|
{
|
||||||
|
return Check<Solid>(.(0, distance));
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool IsRiding(Solid solid)
|
||||||
|
{
|
||||||
|
return Check(solid, .(0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Squish()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveX(float amount, Action onCollide = null)
|
||||||
|
{
|
||||||
|
remainder.X += amount;
|
||||||
|
let move = (int)Math.Round(remainder.X);
|
||||||
|
if (move != 0)
|
||||||
|
{
|
||||||
|
remainder.X -= move;
|
||||||
|
return MoveExactX(move, onCollide);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveY(float amount, Action onCollide = null)
|
||||||
|
{
|
||||||
|
remainder.Y += amount;
|
||||||
|
let move = (int)Math.Round(remainder.Y);
|
||||||
|
if (move != 0)
|
||||||
|
{
|
||||||
|
remainder.Y -= move;
|
||||||
|
return MoveExactY(move, onCollide);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveExactX(int amount, Action onCollide = null)
|
||||||
|
{
|
||||||
|
int move = amount;
|
||||||
|
int sign = Math.Sign(amount);
|
||||||
|
while (move != 0)
|
||||||
|
{
|
||||||
|
if (Check<Solid>(.(sign, 0)))
|
||||||
|
{
|
||||||
|
ZeroRemainderX();
|
||||||
|
onCollide?.Invoke();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
X += sign;
|
||||||
|
move -= sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveExactY(int amount, Action onCollide = null)
|
||||||
|
{
|
||||||
|
int move = amount;
|
||||||
|
int sign = Math.Sign(amount);
|
||||||
|
while (move != 0)
|
||||||
|
{
|
||||||
|
if (Check<Solid>(.(0, sign)))
|
||||||
|
{
|
||||||
|
ZeroRemainderY();
|
||||||
|
onCollide?.Invoke();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Y += sign;
|
||||||
|
move -= sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ZeroRemainderX()
|
||||||
|
{
|
||||||
|
remainder.X = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ZeroRemainderY()
|
||||||
|
{
|
||||||
|
remainder.Y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ZeroRemainder()
|
||||||
|
{
|
||||||
|
remainder = Vector.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
src/Physics/Platform.bf
Normal file
57
src/Physics/Platform.bf
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public abstract class Platform : Entity
|
||||||
|
{
|
||||||
|
private Vector remainder;
|
||||||
|
|
||||||
|
public this(int x, int y)
|
||||||
|
: base(x, y)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveX(float amount, Action onCollide = null)
|
||||||
|
{
|
||||||
|
remainder.X += amount;
|
||||||
|
let move = (int)Math.Round(remainder.X);
|
||||||
|
if (move != 0)
|
||||||
|
{
|
||||||
|
remainder.X -= move;
|
||||||
|
MoveExactX(move, onCollide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveY(float amount, Action onCollide = null)
|
||||||
|
{
|
||||||
|
remainder.Y += amount;
|
||||||
|
let move = (int)Math.Round(remainder.Y);
|
||||||
|
if (move != 0)
|
||||||
|
{
|
||||||
|
remainder.Y -= move;
|
||||||
|
MoveExactY(move, onCollide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void MoveExactX(int amount, Action onCollide = null);
|
||||||
|
public abstract void MoveExactY(int amount, Action onCollide = null);
|
||||||
|
public abstract List<Actor> GetRiders(List<Actor> into);
|
||||||
|
|
||||||
|
public void ZeroRemainderX()
|
||||||
|
{
|
||||||
|
remainder.X = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ZeroRemainderY()
|
||||||
|
{
|
||||||
|
remainder.Y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ZeroRemainder()
|
||||||
|
{
|
||||||
|
remainder = Vector.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
src/Physics/Solid.bf
Normal file
42
src/Physics/Solid.bf
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public class Solid : Platform
|
||||||
|
{
|
||||||
|
public this(int x, int y, Rect hitbox)
|
||||||
|
: base(x, y)
|
||||||
|
{
|
||||||
|
Hitbox = hitbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
DrawHitbox(.(255, 255, 255, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
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, System.Action onCollide = null)
|
||||||
|
{
|
||||||
|
if (amount != 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MoveExactY(int amount, System.Action onCollide = null)
|
||||||
|
{
|
||||||
|
if (amount != 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
148
src/Scene.bf
Normal file
148
src/Scene.bf
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Strawberry
|
||||||
|
{
|
||||||
|
public class Scene
|
||||||
|
{
|
||||||
|
private List<Entity> entities;
|
||||||
|
private HashSet<Entity> toRemove;
|
||||||
|
private HashSet<Entity> toAdd;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
entities = new List<Entity>();
|
||||||
|
toAdd = new HashSet<Entity>();
|
||||||
|
toRemove = new HashSet<Entity>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
for (var e in entities)
|
||||||
|
if (e.DeleteOnRemove)
|
||||||
|
delete e;
|
||||||
|
delete entities;
|
||||||
|
|
||||||
|
for (var e in toAdd)
|
||||||
|
if (e.DeleteOnRemove)
|
||||||
|
delete e;
|
||||||
|
delete toAdd;
|
||||||
|
|
||||||
|
delete toRemove;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Started()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
UpdateLists();
|
||||||
|
for (var e in entities)
|
||||||
|
if (e.Active)
|
||||||
|
e.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Draw()
|
||||||
|
{
|
||||||
|
for (var e in entities)
|
||||||
|
if (e.Visible)
|
||||||
|
e.Draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Add<T>(T e) where T : Entity
|
||||||
|
{
|
||||||
|
if (e.Scene == null)
|
||||||
|
toAdd.Add(e);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Remove<T>(T e) where T : Entity
|
||||||
|
{
|
||||||
|
if (e.Scene == this)
|
||||||
|
toRemove.Add(e);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLists()
|
||||||
|
{
|
||||||
|
if (toRemove.Count > 0)
|
||||||
|
{
|
||||||
|
for (var e in toRemove)
|
||||||
|
{
|
||||||
|
entities.Remove(e);
|
||||||
|
e.Removed();
|
||||||
|
if (e.DeleteOnRemove)
|
||||||
|
delete e;
|
||||||
|
}
|
||||||
|
|
||||||
|
toRemove.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toAdd.Count > 0)
|
||||||
|
{
|
||||||
|
for (var e in toAdd)
|
||||||
|
{
|
||||||
|
entities.Add(e);
|
||||||
|
e.Added(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var e in toAdd)
|
||||||
|
e.Started();
|
||||||
|
|
||||||
|
toAdd.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finding Entities
|
||||||
|
|
||||||
|
public T First<T>() where T : Entity
|
||||||
|
{
|
||||||
|
for (var e in entities)
|
||||||
|
if (e is T)
|
||||||
|
return e as T;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T First<T>(Point point) where T : Entity
|
||||||
|
{
|
||||||
|
for (var e in entities)
|
||||||
|
if (e is T && e.Check(point))
|
||||||
|
return e as T;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T First<T>(Rect rect) where T : Entity
|
||||||
|
{
|
||||||
|
for (var e in entities)
|
||||||
|
if (e is T && e.Check(rect))
|
||||||
|
return e as T;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> All<T>(List<T> into) where T : Entity
|
||||||
|
{
|
||||||
|
for (var e in entities)
|
||||||
|
if (e is T)
|
||||||
|
into.Add(e as T);
|
||||||
|
return into;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> All<T>(Point point, List<T> into) where T : Entity
|
||||||
|
{
|
||||||
|
for (var e in entities)
|
||||||
|
if (e is T && e.Check(point))
|
||||||
|
into.Add(e as T);
|
||||||
|
return into;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> All<T>(Rect rect, List<T> into) where T : Entity
|
||||||
|
{
|
||||||
|
for (var e in entities)
|
||||||
|
if (e is T && e.Check(rect))
|
||||||
|
into.Add(e as T);
|
||||||
|
return into;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user