Add Color record struct, small refactor, create a DaggerFramework.SceneGraph namespace.
This commit is contained in:
18
Source/SceneGraph/Entities/CircleShape2d.cs
Executable file
18
Source/SceneGraph/Entities/CircleShape2d.cs
Executable file
@@ -0,0 +1,18 @@
|
||||
using DaggerFramework.Rendering;
|
||||
|
||||
namespace DaggerFramework.SceneGraph
|
||||
{
|
||||
public class CircleShape2d : Drawable2d
|
||||
{
|
||||
public float Radius { get => _radius; set => _radius = value; }
|
||||
public Color Color { get => _color; set => _color = value; }
|
||||
|
||||
public override void OnDraw(Renderer renderer)
|
||||
{
|
||||
renderer.DrawCircle(_radius, _color);
|
||||
}
|
||||
|
||||
private float _radius;
|
||||
private Color _color;
|
||||
}
|
||||
}
|
||||
15
Source/SceneGraph/Entities/Drawable2d.cs
Executable file
15
Source/SceneGraph/Entities/Drawable2d.cs
Executable file
@@ -0,0 +1,15 @@
|
||||
using DaggerFramework.Rendering;
|
||||
|
||||
namespace DaggerFramework.SceneGraph
|
||||
{
|
||||
public abstract class Drawable2d : Entity2d, IDrawable
|
||||
{
|
||||
public void Draw(Renderer renderer)
|
||||
{
|
||||
renderer.SetTransform(Position);
|
||||
OnDraw(renderer);
|
||||
}
|
||||
|
||||
public abstract void OnDraw(Renderer renderer);
|
||||
}
|
||||
}
|
||||
27
Source/SceneGraph/Entities/Entity.cs
Executable file
27
Source/SceneGraph/Entities/Entity.cs
Executable file
@@ -0,0 +1,27 @@
|
||||
using DaggerFramework.Audio;
|
||||
|
||||
namespace DaggerFramework.SceneGraph
|
||||
{
|
||||
public class Entity
|
||||
{
|
||||
public EntityLayer Layer { get; set; }
|
||||
public InputHandler Input => Layer.Scene.Input;
|
||||
public AudioBackend Audio => Layer.Scene.Audio;
|
||||
public int Id { get; set; }
|
||||
|
||||
public void Start() => OnStart();
|
||||
public void Update(double dt) => OnUpdate(dt);
|
||||
public void ReceiveInput(InputHandler input) => OnInput(input);
|
||||
|
||||
protected virtual void OnStart() { }
|
||||
protected virtual void OnDestroy() { }
|
||||
protected virtual void OnUpdate(double dt) { }
|
||||
protected virtual void OnInput(InputHandler input) { }
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
OnDestroy();
|
||||
Layer?.DestroyEntity(Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Source/SceneGraph/Entities/Entity2d.cs
Executable file
9
Source/SceneGraph/Entities/Entity2d.cs
Executable file
@@ -0,0 +1,9 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace DaggerFramework.SceneGraph
|
||||
{
|
||||
public class Entity2d : Entity
|
||||
{
|
||||
public Vector2 Position { get; set; }
|
||||
}
|
||||
}
|
||||
9
Source/SceneGraph/Entities/IDrawable.cs
Executable file
9
Source/SceneGraph/Entities/IDrawable.cs
Executable file
@@ -0,0 +1,9 @@
|
||||
using DaggerFramework.Rendering;
|
||||
|
||||
namespace DaggerFramework.SceneGraph
|
||||
{
|
||||
public interface IDrawable
|
||||
{
|
||||
public void Draw(Renderer renderer);
|
||||
}
|
||||
}
|
||||
158
Source/SceneGraph/Entities/Particles2d.cs
Normal file
158
Source/SceneGraph/Entities/Particles2d.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using DaggerFramework.Rendering;
|
||||
|
||||
namespace DaggerFramework.SceneGraph
|
||||
{
|
||||
// TODO: add oneshot parameter.
|
||||
public class Particles2d : Drawable2d
|
||||
{
|
||||
public int MaxParticles => _maxParticles;
|
||||
|
||||
public void BeginEmit(ParticleSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
_maxParticles = _settings.MaxParticles;
|
||||
_particleIndex = _maxParticles - 1;
|
||||
InitializeParticles();
|
||||
}
|
||||
public void Restart()
|
||||
{
|
||||
CleanupParticles();
|
||||
InitializeParticles();
|
||||
}
|
||||
public override void OnDraw(Renderer renderer)
|
||||
{
|
||||
foreach (var particle in _particles)
|
||||
{
|
||||
if (!particle.Alive) continue;
|
||||
|
||||
var t = particle.LifeTimeRemaining / particle.LifeTime;
|
||||
var scale = MathUtils.Lerp(_settings.ScaleEnd, _settings.ScaleBegin, t);
|
||||
var color = MathUtils.LerpColor(_settings.ColorEnd, _settings.ColorBegin, t);
|
||||
|
||||
renderer.SetTransform(particle.Position, particle.Rotation);
|
||||
renderer.DrawRectangle(Vector2.One * scale, color);
|
||||
}
|
||||
}
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
// Emit();
|
||||
}
|
||||
protected override void OnUpdate(double dt)
|
||||
{
|
||||
base.OnUpdate(dt);
|
||||
|
||||
var rate = (int)MathUtils.Lerp(1, _maxParticles, _settings.Explosiveness);
|
||||
for (int i = 0; i < rate; i++)
|
||||
{
|
||||
Emit();
|
||||
}
|
||||
|
||||
for (int i = 0; i < _maxParticles; i++)
|
||||
{
|
||||
var particle = _particles[i];
|
||||
if (!particle.Alive) continue;
|
||||
|
||||
if (particle.LifeTimeRemaining <= 0.0f)
|
||||
{
|
||||
particle.Alive = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
particle.LifeTimeRemaining -= (float)dt;
|
||||
particle.Velocity += _settings.Gravity * (float)dt;
|
||||
particle.Position += particle.Velocity * (float)dt;
|
||||
particle.Rotation += particle.AngularVelocity * (float)dt;
|
||||
|
||||
particle.Velocity -= particle.Velocity * _settings.Damping * (float)dt;
|
||||
|
||||
_particles[i] = particle;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeParticles()
|
||||
{
|
||||
_particles = new Particle[_maxParticles];
|
||||
}
|
||||
|
||||
private void Emit()
|
||||
{
|
||||
Particle particle = _particles[_particleIndex];
|
||||
if (!(particle.LifeTimeRemaining <= 0)) return;
|
||||
particle.Alive = true;
|
||||
particle.Position = GetEmitPosition();
|
||||
particle.Velocity = _settings.Direction * _settings.LinearVelocity;
|
||||
|
||||
particle.Velocity += Vector2.One * _settings.LinearVelocityRandom * ((float)_random.NextDouble() - 0.5f);
|
||||
|
||||
particle.AngularVelocity = _settings.AngularVelocity;
|
||||
particle.AngularVelocity += 1f * _settings.AngularVelocityRandom * ((float)_random.NextDouble() - 0.5f);
|
||||
|
||||
particle.LifeTime = _settings.LifeTime;
|
||||
particle.LifeTimeRemaining = particle.LifeTime;
|
||||
|
||||
_particles[_particleIndex] = particle;
|
||||
_particleIndex = --_particleIndex <= 0 ? _maxParticles - 1 : --_particleIndex;
|
||||
}
|
||||
|
||||
private void CleanupParticles() => Array.Clear(_particles);
|
||||
private Vector2 GetEmitPosition()
|
||||
{
|
||||
// https://gamedev.stackexchange.com/questions/26713/calculate-random-points-pixel-within-a-circle-image
|
||||
var angle = _random.NextDouble() * Math.PI * 2;
|
||||
float radius = (float)Math.Sqrt(_random.NextDouble()) * _settings.EmitRadius;
|
||||
|
||||
float x = Position.X + radius * (float)Math.Cos(angle);
|
||||
float y = Position.Y + radius * (float)Math.Sin(angle);
|
||||
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
private ParticleSettings _settings;
|
||||
private int _maxParticles;
|
||||
private Particle[] _particles;
|
||||
private int _particleIndex;
|
||||
|
||||
// TODO: replace a random function for better distribution and performance.
|
||||
private LehmerRandom _random = new LehmerRandom();
|
||||
}
|
||||
|
||||
public struct ParticleSettings
|
||||
{
|
||||
public ParticleSettings()
|
||||
{
|
||||
}
|
||||
public float EmitRadius;
|
||||
public float LifeTime;
|
||||
public float Explosiveness;
|
||||
public int MaxParticles;
|
||||
public Vector2 Direction;
|
||||
public float LinearVelocity;
|
||||
public float AngularVelocity = 0.0f;
|
||||
public float AngularVelocityRandom;
|
||||
public float LinearVelocityRandom;
|
||||
public Vector2 Gravity;
|
||||
public float ScaleBegin = 16f;
|
||||
public float ScaleEnd = 0.0f;
|
||||
public Color ColorBegin = Color.White;
|
||||
public Color ColorEnd = Color.Black;
|
||||
public float Damping = 0.0f;
|
||||
}
|
||||
|
||||
public struct Particle
|
||||
{
|
||||
public Particle()
|
||||
{
|
||||
}
|
||||
public Vector2 Position;
|
||||
public Vector2 Velocity;
|
||||
public float AngularVelocity;
|
||||
public float LifeTime;
|
||||
public float LifeTimeRemaining;
|
||||
public float Scale;
|
||||
public float Rotation;
|
||||
public bool Alive = true;
|
||||
}
|
||||
}
|
||||
25
Source/SceneGraph/Entities/Sprite2d.cs
Executable file
25
Source/SceneGraph/Entities/Sprite2d.cs
Executable file
@@ -0,0 +1,25 @@
|
||||
using System.Drawing;
|
||||
|
||||
using DaggerFramework.Rendering;
|
||||
|
||||
namespace DaggerFramework.SceneGraph
|
||||
{
|
||||
public class Sprite2d : Drawable2d
|
||||
{
|
||||
public Texture2d Texture { get => _texture; set => _texture = value; }
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
var renderer = Layer.Scene.Renderer;
|
||||
_texId = renderer.LoadTexture(_texture);
|
||||
}
|
||||
|
||||
public override void OnDraw(Renderer renderer)
|
||||
{
|
||||
renderer.DrawTexture(_texId, Color.White);
|
||||
}
|
||||
|
||||
private Texture2d _texture;
|
||||
private int _texId;
|
||||
}
|
||||
}
|
||||
21
Source/SceneGraph/Entities/Text2d.cs
Normal file
21
Source/SceneGraph/Entities/Text2d.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using DaggerFramework.Rendering;
|
||||
using System.Drawing;
|
||||
|
||||
namespace DaggerFramework.SceneGraph
|
||||
{
|
||||
public class Text2d : Drawable2d
|
||||
{
|
||||
public string Contents { get => _contents; set => _contents = value; }
|
||||
public int FontSize { get => _fontSize; set => _fontSize = value; }
|
||||
public Color FontColor { get => _fontColor; set => _fontColor = value; }
|
||||
|
||||
public override void OnDraw(Renderer renderer)
|
||||
{
|
||||
renderer.DrawDebugText(Position, _contents, _fontSize, _fontColor);
|
||||
}
|
||||
|
||||
private string _contents = string.Empty;
|
||||
private int _fontSize = 16;
|
||||
private Color _fontColor = Color.White;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user