Update Game, add IGame.
This commit is contained in:
@@ -1,16 +1,29 @@
|
|||||||
using Voile;
|
using Voile;
|
||||||
using Voile.Resources;
|
using Voile.Resources;
|
||||||
using Voile.Utils;
|
|
||||||
using Voile.Input;
|
using Voile.Input;
|
||||||
using Voile.Systems.Particles;
|
using Voile.Systems.Particles;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Diagnostics;
|
using Voile.Rendering;
|
||||||
|
|
||||||
public class TestGame : BaseGame
|
public class TestGame : Game
|
||||||
{
|
{
|
||||||
|
public override string Name => "Jump Adventures 2";
|
||||||
public override string ResourceRoot => "Resources/";
|
public override string ResourceRoot => "Resources/";
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
InitializeSystemsDefault();
|
||||||
|
|
||||||
|
_particleSystem = new ParticleSystem();
|
||||||
|
AddSystemToUpdate(_particleSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Shutdown()
|
||||||
|
{
|
||||||
|
ShutdownDefault();
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadResources()
|
protected override void LoadResources()
|
||||||
{
|
{
|
||||||
ResourceManager.AddResourceLoaderAssociation(new ParticleEmitterSettingsResourceLoader());
|
ResourceManager.AddResourceLoaderAssociation(new ParticleEmitterSettingsResourceLoader());
|
||||||
@@ -30,19 +43,14 @@ public class TestGame : BaseGame
|
|||||||
|
|
||||||
protected override void Ready()
|
protected override void Ready()
|
||||||
{
|
{
|
||||||
_particleSystem = new ParticleSystem();
|
|
||||||
Input.AddInputMapping("reload", new InputAction[] { new KeyInputAction(KeyboardKey.R) });
|
Input.AddInputMapping("reload", new InputAction[] { new KeyInputAction(KeyboardKey.R) });
|
||||||
_particleSimStopwatch = new Stopwatch();
|
|
||||||
|
|
||||||
_emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect);
|
_emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void Update(double deltaTime)
|
protected override void Update(double deltaTime)
|
||||||
{
|
{
|
||||||
_particleSimStopwatch = Stopwatch.StartNew();
|
|
||||||
_particleSystem!.Update(deltaTime);
|
|
||||||
_particleSimStopwatch.Stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Render(double deltaTime)
|
protected override void Render(double deltaTime)
|
||||||
@@ -70,18 +78,16 @@ public class TestGame : BaseGame
|
|||||||
}
|
}
|
||||||
|
|
||||||
Renderer.ResetTransform();
|
Renderer.ResetTransform();
|
||||||
Renderer.DrawText(_font, $"Particle Sim: {_particleSimStopwatch.Elapsed.TotalMilliseconds} ms", Color.White);
|
|
||||||
|
|
||||||
Renderer.SetTransform(new Vector2(0.0f, 16.0f), Vector2.Zero);
|
|
||||||
Renderer.DrawText(_font, $"Render: {RenderFrameTime.TotalMilliseconds:F1} ms", Color.White);
|
Renderer.DrawText(_font, $"Render: {RenderFrameTime.TotalMilliseconds:F1} ms", Color.White);
|
||||||
|
|
||||||
Renderer.SetTransform(new Vector2(0.0f, 32.0f), Vector2.Zero);
|
Renderer.SetTransform(new Vector2(0.0f, 16.0f), Vector2.Zero);
|
||||||
Renderer.DrawText(_font, $"Update: {UpdateTimeStep * 1000:F1} ms", Color.White);
|
Renderer.DrawText(_font, $"Update: {UpdateTimeStep * 1000:F1} ms", Color.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawEmitter(ParticleEmitter emitter)
|
private void DrawEmitter(ParticleEmitter emitter)
|
||||||
{
|
{
|
||||||
Renderer.BeginBlended(Voile.Rendering.BlendMode.BlendAlpha);
|
Renderer.BeginBlended(BlendMode.BlendAlpha);
|
||||||
|
|
||||||
var maxParticles = emitter.Settings.MaxParticles;
|
var maxParticles = emitter.Settings.MaxParticles;
|
||||||
var particleSize = new Vector2(16.0f, 16.0f);
|
var particleSize = new Vector2(16.0f, 16.0f);
|
||||||
@@ -99,11 +105,8 @@ public class TestGame : BaseGame
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NotNull] private ParticleSystem _particleSystem;
|
[NotNull] private ParticleSystem _particleSystem;
|
||||||
|
|
||||||
private Stopwatch _particleSimStopwatch;
|
|
||||||
private int _emitterId;
|
private int _emitterId;
|
||||||
private ResourceRef<ParticleEmitterSettingsResource> _fireEffect;
|
private ResourceRef<ParticleEmitterSettingsResource> _fireEffect;
|
||||||
private ResourceRef<Font> _font;
|
private ResourceRef<Font> _font;
|
||||||
private ResourceRef<Texture2d> _icon;
|
private ResourceRef<Texture2d> _icon;
|
||||||
private Logger _logger = new(nameof(TestGame));
|
|
||||||
}
|
}
|
||||||
@@ -1,43 +1,51 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Voile.Input;
|
using Voile.Input;
|
||||||
using Voile.Rendering;
|
using Voile.Rendering;
|
||||||
using Voile.Resources;
|
using Voile.Resources;
|
||||||
|
|
||||||
namespace Voile
|
namespace Voile
|
||||||
{
|
{
|
||||||
|
public interface IGame
|
||||||
|
{
|
||||||
|
string Name { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Resource root path for this game.
|
||||||
|
/// </summary>
|
||||||
|
string ResourceRoot { get; }
|
||||||
|
void Start();
|
||||||
|
void Run();
|
||||||
|
void Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Entry point for the Voile game.
|
/// Entry point for the Voile game.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Game
|
public abstract class Game : IGame
|
||||||
{
|
{
|
||||||
|
public double UpdateTimeStep { get; set; } = 1.0 / 60.0;
|
||||||
|
public TimeSpan UpdateFrameTime { get; private set; }
|
||||||
|
public TimeSpan RenderFrameTime { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ResourceManager associated with this game.
|
/// The ResourceManager associated with this game.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ResourceManager ResourceManager { get; private set; }
|
protected ResourceManager ResourceManager { get; private set; } = new();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The InputHandler associated with this game. Uses <see cref="RaylibInputSystem"/> by default.
|
/// The InputHandler associated with this game. Uses <see cref="RaylibInputSystem"/> by default.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected InputSystem Input { get; private set; }
|
protected InputSystem? Input { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Renderer associated with this game. Uses <see cref="RaylibRenderSystem"/> by default.
|
/// The Renderer associated with this game. Uses <see cref="RaylibRenderSystem"/> by default.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected RenderSystem Renderer { get; private set; }
|
protected RenderSystem? Renderer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resource root path for this game.
|
|
||||||
/// </summary>
|
|
||||||
public virtual string ResourceRoot => "Resources/";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Path to the engine configuration file.
|
|
||||||
/// </summary>
|
|
||||||
public virtual string EngineConfigPath => "engine.config";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of this game. Also used as a default window title.
|
/// Name of this game. Also used as a default window title.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual string Name => "";
|
public virtual string Name => "Voile Game";
|
||||||
|
public virtual string ResourceRoot => "Resources/";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default game constructor.
|
/// Default game constructor.
|
||||||
@@ -45,19 +53,16 @@ namespace Voile
|
|||||||
public Game()
|
public Game()
|
||||||
{
|
{
|
||||||
ResourceManager = new ResourceManager();
|
ResourceManager = new ResourceManager();
|
||||||
Input = new RaylibInputSystem();
|
Initialize();
|
||||||
Renderer = new RaylibRenderSystem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Game constructor with custom systems.
|
/// Game constructor with custom systems.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="resourceManager"></param>
|
|
||||||
/// <param name="inputSystem"></param>
|
/// <param name="inputSystem"></param>
|
||||||
/// <param name="renderSystem"></param>
|
/// <param name="renderSystem"></param>
|
||||||
public Game(ResourceManager resourceManager, InputSystem inputSystem, RenderSystem renderSystem)
|
public Game(InputSystem inputSystem, RenderSystem renderSystem)
|
||||||
{
|
{
|
||||||
ResourceManager = resourceManager;
|
|
||||||
Input = inputSystem;
|
Input = inputSystem;
|
||||||
Renderer = renderSystem;
|
Renderer = renderSystem;
|
||||||
}
|
}
|
||||||
@@ -83,83 +88,77 @@ namespace Voile
|
|||||||
throw new NullReferenceException("No ResourceManager provided.");
|
throw new NullReferenceException("No ResourceManager provided.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Initialize();
|
LoadResources();
|
||||||
Ready();
|
Ready();
|
||||||
Run();
|
Run();
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes subsystems using default types and settings.
|
/// Initializes systems using default types and settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void InitializeDefault()
|
public void InitializeSystemsDefault()
|
||||||
{
|
{
|
||||||
ResourceManager.ResourceRoot = ResourceRoot;
|
ResourceManager.ResourceRoot = ResourceRoot;
|
||||||
|
|
||||||
Input = new RaylibInputSystem();
|
if (Renderer is null)
|
||||||
|
{
|
||||||
Renderer = new RaylibRenderSystem();
|
Renderer = new RaylibRenderSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input is null)
|
||||||
|
{
|
||||||
|
Input = new RaylibInputSystem();
|
||||||
|
}
|
||||||
|
|
||||||
Input.Start();
|
Input.Start();
|
||||||
|
|
||||||
InitializeRenderer();
|
InitializeRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShutdownDefault()
|
public void ShutdownDefault()
|
||||||
{
|
{
|
||||||
Input.Dispose();
|
Input?.Dispose();
|
||||||
Renderer.Dispose();
|
Renderer?.Dispose();
|
||||||
ResourceManager.Dispose();
|
ResourceManager.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when it's time to initialize the subsystems, or modify default game settings or system settings.
|
/// Adds a system that will start together with the game.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void Initialize();
|
/// <param name="system"></param>
|
||||||
|
public void AddSystem([DisallowNull] IStartableSystem system)
|
||||||
|
{
|
||||||
|
_startableSystems.Add(system);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when it's safe to manipulate the resources or/and systems.
|
/// Adds a system to the Update step.
|
||||||
/// You can safely create game objects, scenes, etc. in this method.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract void Ready();
|
/// <param name="system"></param>
|
||||||
|
public void AddSystemToUpdate([DisallowNull] IUpdatableSystem system)
|
||||||
|
{
|
||||||
|
_updatableSystems.Add(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a system to the render step.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="system"></param>
|
||||||
|
public void AddSystemToRender([DisallowNull] IUpdatableSystem system)
|
||||||
|
{
|
||||||
|
_renderableSystems.Add(system);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when everything has been readied to start the main loop.
|
/// Called when everything has been readied to start the main loop.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract void Run();
|
public void Run()
|
||||||
/// <summary>
|
|
||||||
/// Called when the application quits and it's safe to clean up.
|
|
||||||
/// </summary>
|
|
||||||
public abstract void Shutdown();
|
|
||||||
|
|
||||||
private void InitializeRenderer()
|
|
||||||
{
|
{
|
||||||
var windowSettings = WindowSettings.Default;
|
if (Renderer is null)
|
||||||
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(Name))
|
throw new NullReferenceException("No renderer provided.");
|
||||||
windowSettings.Title = Name;
|
|
||||||
|
|
||||||
Renderer.Start(RendererSettings.Default);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class BaseGame : Game
|
|
||||||
{
|
|
||||||
public double UpdateTimeStep { get; set; } = 1.0 / 60.0;
|
|
||||||
public TimeSpan UpdateFrameTime { get; private set; }
|
|
||||||
public TimeSpan RenderFrameTime { get; private set; }
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
LoadResources();
|
|
||||||
InitializeDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Shutdown() => ShutdownDefault();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when it's time to load the game's resources, such as images or sounds.
|
|
||||||
/// </summary>
|
|
||||||
protected abstract void LoadResources();
|
|
||||||
|
|
||||||
protected override void Run()
|
|
||||||
{
|
|
||||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||||
double previousTime = stopwatch.Elapsed.TotalSeconds;
|
double previousTime = stopwatch.Elapsed.TotalSeconds;
|
||||||
|
|
||||||
@@ -173,11 +172,22 @@ namespace Voile
|
|||||||
|
|
||||||
while (_accumulator >= UpdateTimeStep)
|
while (_accumulator >= UpdateTimeStep)
|
||||||
{
|
{
|
||||||
|
foreach (var system in _updatableSystems)
|
||||||
|
{
|
||||||
|
system.Update(UpdateTimeStep);
|
||||||
|
}
|
||||||
|
|
||||||
Update(UpdateTimeStep);
|
Update(UpdateTimeStep);
|
||||||
_accumulator -= UpdateTimeStep;
|
_accumulator -= UpdateTimeStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer.BeginFrame();
|
Renderer.BeginFrame();
|
||||||
|
|
||||||
|
foreach (var system in _renderableSystems)
|
||||||
|
{
|
||||||
|
system.Update(Renderer.FrameTime);
|
||||||
|
}
|
||||||
|
|
||||||
Render(Renderer.FrameTime);
|
Render(Renderer.FrameTime);
|
||||||
Renderer.EndFrame();
|
Renderer.EndFrame();
|
||||||
|
|
||||||
@@ -185,6 +195,21 @@ namespace Voile
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when it's time to initialize the subsystems, or modify default game settings or system settings.
|
||||||
|
/// </summary>
|
||||||
|
public abstract void Initialize();
|
||||||
|
/// <summary>
|
||||||
|
/// Called when it's safe to manipulate the resources or/and systems.
|
||||||
|
/// You can safely create game objects, scenes, etc. in this method.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract void Ready();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when it's time to load the game's resources, such as images or sounds.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract void LoadResources();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggered on each fixed timestep. Update your game's state here.
|
/// Triggered on each fixed timestep. Update your game's state here.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -196,6 +221,28 @@ namespace Voile
|
|||||||
/// <param name="deltaTime"></param>
|
/// <param name="deltaTime"></param>
|
||||||
protected abstract void Render(double deltaTime);
|
protected abstract void Render(double deltaTime);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the application quits and it's safe to clean up.
|
||||||
|
/// </summary>
|
||||||
|
public abstract void Shutdown();
|
||||||
|
|
||||||
|
private void InitializeRenderer()
|
||||||
|
{
|
||||||
|
var windowSettings = WindowSettings.Default;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(Name))
|
||||||
|
windowSettings.Title = Name;
|
||||||
|
|
||||||
|
var renderSettings = RendererSettings.Default;
|
||||||
|
renderSettings.WindowSettings = windowSettings;
|
||||||
|
|
||||||
|
Renderer?.Start(renderSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IStartableSystem> _startableSystems = new();
|
||||||
|
private List<IUpdatableSystem> _updatableSystems = new();
|
||||||
|
private List<IUpdatableSystem> _renderableSystems = new();
|
||||||
|
|
||||||
private double _accumulator;
|
private double _accumulator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user