Change folder structure, add solution to the root.

This commit is contained in:
2023-06-18 17:19:03 +02:00
parent d5f5fb5614
commit 15747d7e9b
51 changed files with 33 additions and 6 deletions

View 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;
}
}

View 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);
}
}

View 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);
}
}
}

View File

@@ -0,0 +1,9 @@
using System.Numerics;
namespace DaggerFramework.SceneGraph
{
public class Entity2d : Entity
{
public Vector2 Position { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public interface IDrawable
{
public void Draw(Renderer renderer);
}
}

View 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;
}
}

View 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;
}
}

View 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(_contents, _fontSize, _fontColor);
}
private string _contents = string.Empty;
private int _fontSize = 16;
private Color _fontColor = Color.White;
}
}

View File

@@ -0,0 +1,58 @@
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public class EntityLayer : Layer
{
public List<Entity> Entities { get => _entities; }
public EntityLayer(List<Entity> entities)
{
_entities = entities;
}
public EntityLayer()
{
_entities = new List<Entity>();
}
public bool AddEntity(Entity entity)
{
entity.Id = Entities.Count;
entity.Layer = this;
Entities.Add(entity);
return true;
}
public void DestroyEntity(int at)
{
_entities.RemoveAt(at);
}
protected override void OnStart()
{
foreach (var entity in _entities)
{
entity.Layer = this;
entity.Start();
}
}
protected override void OnUpdate(double dt)
{
foreach (var entity in _entities)
{
entity.Update(dt);
}
}
protected override void OnDraw(Renderer renderer)
{
foreach (IDrawable drawable in _entities)
{
drawable.Draw(renderer);
}
}
private List<Entity> _entities;
}
}

View File

@@ -0,0 +1,11 @@
namespace DaggerFramework.SceneGraph
{
public interface IMainLoop
{
public void Init();
public void Start();
public bool ShouldStop();
public void Update();
public double DeltaTime { get; }
}
}

View File

@@ -0,0 +1,21 @@
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public abstract class Layer : IDrawable
{
public Scene Scene { get; set; }
public InputHandler Input { get; set; }
public void Draw(Renderer renderer) => OnDraw(renderer);
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 OnUpdate(double dt) { }
protected virtual void OnInput(InputHandler input) { }
protected abstract void OnDraw(Renderer renderer);
}
}

View File

@@ -0,0 +1,82 @@
using System.Drawing;
using System.Numerics;
using DaggerFramework.Audio;
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public class Scene : IMainLoop
{
public Renderer Renderer { get => _renderer; set => _renderer = value; }
public InputHandler Input { get => _input; set => _input = value; }
public AudioBackend Audio => _audioBackend;
public double DeltaTime => Renderer.GetFrameTime();
public Scene(Renderer renderer, InputHandler input, AudioBackend audioBackend)
{
_renderer = renderer;
_input = input;
_audioBackend = audioBackend;
_layers = new Dictionary<string, Layer>();
}
public Scene(Renderer renderer)
{
_renderer = renderer;
}
public void Init() => SetupRenderer();
public void Start()
{
foreach (var layer in _layers.Values)
{
layer.Input = _input;
layer.Start();
}
}
public void Update()
{
foreach (var layer in _layers)
{
layer.Value.Update(DeltaTime);
}
Draw();
}
public void AddLayer(string name, Layer layer)
{
layer.Scene = this;
_layers.Add(name, layer);
}
public bool ShouldStop() => Renderer.WindowShouldClose();
private void Draw()
{
Renderer.BeginFrame();
Renderer.ClearBackground(Color.Black);
foreach (var layer in _layers.Values)
{
layer.Draw(_renderer);
}
Renderer.EndFrame();
Audio.Update();
}
private void SetupRenderer()
{
Renderer.CreateWindow("Game", new Vector2(1280, 720));
Renderer.Initialize(new RendererSettings { Msaa = Msaa.Msaa4x, UseVSync = true });
Renderer.SetTargetFps(60);
}
private Dictionary<string, Layer> _layers;
private Renderer _renderer;
private AudioBackend _audioBackend;
private InputHandler _input;
}
}