implementation of time dilation system for engines
parent
471117f4f4
commit
fc50bf9b81
|
@ -0,0 +1,7 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class IgnoresTimeDilation : Attribute { }
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class TimeDilationPriority : Attribute
|
||||||
|
{
|
||||||
|
public int timeDilationPriority;
|
||||||
|
|
||||||
|
public TimeDilationPriority(int timeDilationPriority)
|
||||||
|
{
|
||||||
|
this.timeDilationPriority = timeDilationPriority;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,10 +19,21 @@ namespace Encompass
|
||||||
internal readonly HashSet<Type> receiveTypes = new HashSet<Type>();
|
internal readonly HashSet<Type> receiveTypes = new HashSet<Type>();
|
||||||
internal readonly Dictionary<Type, int> writePriorities = new Dictionary<Type, int>();
|
internal readonly Dictionary<Type, int> writePriorities = new Dictionary<Type, int>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If false, the Engine will ignore time dilation.
|
||||||
|
/// </summary>
|
||||||
|
internal bool usesTimeDilation = true;
|
||||||
|
public bool TimeDilationActive { get => usesTimeDilation && timeManager.TimeDilationActive; }
|
||||||
|
/// <summary>
|
||||||
|
/// Used when activating time dilation. Lower priority overrides higher priority.
|
||||||
|
/// </summary>
|
||||||
|
internal int? timeDilationPriority = null;
|
||||||
|
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
private MessageManager messageManager;
|
private MessageManager messageManager;
|
||||||
private ComponentManager componentManager;
|
private ComponentManager componentManager;
|
||||||
private ComponentMessageManager componentMessageManager;
|
private ComponentMessageManager componentMessageManager;
|
||||||
|
private TimeManager timeManager;
|
||||||
|
|
||||||
protected Engine()
|
protected Engine()
|
||||||
{
|
{
|
||||||
|
@ -106,6 +117,11 @@ namespace Encompass
|
||||||
this.componentMessageManager = componentMessageManager;
|
this.componentMessageManager = componentMessageManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void AssignTimeManager(TimeManager timeManager)
|
||||||
|
{
|
||||||
|
this.timeManager = timeManager;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs once per World update with the calculated delta-time.
|
/// Runs once per World update with the calculated delta-time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -673,5 +689,34 @@ namespace Encompass
|
||||||
{
|
{
|
||||||
componentManager.MarkForRemoval(componentID);
|
componentManager.MarkForRemoval(componentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CheckTimeDilationPriorityExists()
|
||||||
|
{
|
||||||
|
if (!timeDilationPriority.HasValue) { throw new TimeDilationPriorityUndefinedException("Engines that activate time dilation must use the TimeDilationPriority attribute."); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime)
|
||||||
|
{
|
||||||
|
CheckTimeDilationPriorityExists();
|
||||||
|
timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, timeDilationPriority.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime)
|
||||||
|
{
|
||||||
|
CheckTimeDilationPriorityExists();
|
||||||
|
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, timeDilationPriority.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
|
||||||
|
{
|
||||||
|
CheckTimeDilationPriorityExists();
|
||||||
|
timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, easeOutFunction, timeDilationPriority.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
|
||||||
|
{
|
||||||
|
CheckTimeDilationPriorityExists();
|
||||||
|
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction, timeDilationPriority.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using System.Reflection;
|
namespace Encompass
|
||||||
|
|
||||||
namespace Encompass.Engines
|
|
||||||
{
|
{
|
||||||
internal class ComponentMessageEmitter<TComponent> : Engine where TComponent : struct, IComponent
|
internal class ComponentMessageEmitter<TComponent> : Engine where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Encompass.Engines
|
namespace Encompass
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Spawner is a special type of Engine that runs a Spawn method in response to each Message it receives.
|
/// A Spawner is a special type of Engine that runs a Spawn method in response to each Message it receives.
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Encompass.Exceptions
|
||||||
|
{
|
||||||
|
public class TimeDilationPriorityConflictException : Exception
|
||||||
|
{
|
||||||
|
public TimeDilationPriorityConflictException(
|
||||||
|
string format,
|
||||||
|
params object[] args
|
||||||
|
) : base(string.Format(format, args)) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Encompass.Exceptions
|
||||||
|
{
|
||||||
|
public class TimeDilationPriorityUndefinedException : Exception
|
||||||
|
{
|
||||||
|
public TimeDilationPriorityUndefinedException(
|
||||||
|
string format,
|
||||||
|
params object[] args
|
||||||
|
) : base(string.Format(format, args)) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
internal struct TimeDilationData
|
||||||
|
{
|
||||||
|
public double elapsedTime;
|
||||||
|
public double easeInTime;
|
||||||
|
public System.Func<double, double, double, double, double> easeInFunction;
|
||||||
|
public double activeTime;
|
||||||
|
public double easeOutTime;
|
||||||
|
public System.Func<double, double, double, double, double> easeOutFunction;
|
||||||
|
public double factor;
|
||||||
|
|
||||||
|
public double Factor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
double calculatedFactor = 1;
|
||||||
|
|
||||||
|
if (elapsedTime < easeInTime)
|
||||||
|
{
|
||||||
|
calculatedFactor = easeInFunction(elapsedTime, 1, factor - 1, easeInTime);
|
||||||
|
}
|
||||||
|
else if (elapsedTime < easeInTime + activeTime)
|
||||||
|
{
|
||||||
|
calculatedFactor = factor;
|
||||||
|
}
|
||||||
|
else if (elapsedTime < easeInTime + activeTime + easeOutTime)
|
||||||
|
{
|
||||||
|
var elapsedOutTime = elapsedTime - easeInTime - activeTime;
|
||||||
|
calculatedFactor = easeOutFunction(elapsedOutTime, factor, 1 - factor, easeOutTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculatedFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
internal class TimeManager
|
||||||
|
{
|
||||||
|
private TimeDilationData timeDilationData = new TimeDilationData { factor = 1 };
|
||||||
|
private bool newTimeDilationData = false;
|
||||||
|
private TimeDilationData nextFrameTimeDilationData = new TimeDilationData { factor = 1 };
|
||||||
|
|
||||||
|
private double Linear(double t, double b, double c, double d)
|
||||||
|
{
|
||||||
|
return c * t / d + b;
|
||||||
|
}
|
||||||
|
private int minPriority = int.MaxValue;
|
||||||
|
|
||||||
|
public double TimeDilationFactor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return timeDilationData.Factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TimeDilationActive
|
||||||
|
{
|
||||||
|
get => TimeDilationFactor != 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(double dt)
|
||||||
|
{
|
||||||
|
if (newTimeDilationData)
|
||||||
|
{
|
||||||
|
timeDilationData = nextFrameTimeDilationData;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeDilationData.elapsedTime += dt;
|
||||||
|
newTimeDilationData = false;
|
||||||
|
minPriority = int.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, int priority)
|
||||||
|
{
|
||||||
|
ActivateTimeDilation(factor, easeInTime, Linear, activeTime, easeOutTime, Linear, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, int priority)
|
||||||
|
{
|
||||||
|
ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, Linear, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction, int priority)
|
||||||
|
{
|
||||||
|
ActivateTimeDilation(factor, easeInTime, Linear, activeTime, easeOutTime, easeOutFunction, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction, int priority)
|
||||||
|
{
|
||||||
|
if (priority <= minPriority)
|
||||||
|
{
|
||||||
|
newTimeDilationData = true;
|
||||||
|
nextFrameTimeDilationData = new TimeDilationData
|
||||||
|
{
|
||||||
|
elapsedTime = 0,
|
||||||
|
easeInTime = easeInTime,
|
||||||
|
easeInFunction = easeInFunction,
|
||||||
|
activeTime = activeTime,
|
||||||
|
easeOutTime = easeOutTime,
|
||||||
|
easeOutFunction = easeOutFunction,
|
||||||
|
factor = factor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ namespace Encompass
|
||||||
private readonly ComponentManager componentManager;
|
private readonly ComponentManager componentManager;
|
||||||
private readonly MessageManager messageManager;
|
private readonly MessageManager messageManager;
|
||||||
private readonly ComponentMessageManager componentMessageManager;
|
private readonly ComponentMessageManager componentMessageManager;
|
||||||
|
private readonly TimeManager timeManager;
|
||||||
private readonly RenderManager renderManager;
|
private readonly RenderManager renderManager;
|
||||||
|
|
||||||
internal World(
|
internal World(
|
||||||
|
@ -20,6 +21,7 @@ namespace Encompass
|
||||||
ComponentManager componentManager,
|
ComponentManager componentManager,
|
||||||
MessageManager messageManager,
|
MessageManager messageManager,
|
||||||
ComponentMessageManager componentMessageManager,
|
ComponentMessageManager componentMessageManager,
|
||||||
|
TimeManager timeManager,
|
||||||
RenderManager renderManager
|
RenderManager renderManager
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +30,7 @@ namespace Encompass
|
||||||
this.componentManager = componentManager;
|
this.componentManager = componentManager;
|
||||||
this.messageManager = messageManager;
|
this.messageManager = messageManager;
|
||||||
this.componentMessageManager = componentMessageManager;
|
this.componentMessageManager = componentMessageManager;
|
||||||
|
this.timeManager = timeManager;
|
||||||
this.renderManager = renderManager;
|
this.renderManager = renderManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,11 +41,19 @@ namespace Encompass
|
||||||
public void Update(double dt)
|
public void Update(double dt)
|
||||||
{
|
{
|
||||||
messageManager.ProcessDelayedMessages(dt);
|
messageManager.ProcessDelayedMessages(dt);
|
||||||
|
timeManager.Update(dt);
|
||||||
|
|
||||||
foreach (var engine in enginesInOrder)
|
foreach (var engine in enginesInOrder)
|
||||||
|
{
|
||||||
|
if (engine.usesTimeDilation)
|
||||||
|
{
|
||||||
|
engine.Update(dt * timeManager.TimeDilationFactor);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
engine.Update(dt);
|
engine.Update(dt);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
messageManager.ClearMessages();
|
messageManager.ClearMessages();
|
||||||
componentMessageManager.ClearMessages();
|
componentMessageManager.ClearMessages();
|
||||||
|
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Encompass.Exceptions;
|
using Encompass.Exceptions;
|
||||||
using Encompass.Engines;
|
|
||||||
using MoonTools.Core.Graph;
|
using MoonTools.Core.Graph;
|
||||||
using MoonTools.Core.Graph.Extensions;
|
using MoonTools.Core.Graph.Extensions;
|
||||||
|
|
||||||
|
@ -26,6 +25,7 @@ namespace Encompass
|
||||||
private readonly EntityManager entityManager;
|
private readonly EntityManager entityManager;
|
||||||
private readonly MessageManager messageManager;
|
private readonly MessageManager messageManager;
|
||||||
private readonly ComponentMessageManager componentMessageManager;
|
private readonly ComponentMessageManager componentMessageManager;
|
||||||
|
private readonly TimeManager timeManager;
|
||||||
private readonly DrawLayerManager drawLayerManager;
|
private readonly DrawLayerManager drawLayerManager;
|
||||||
private readonly RenderManager renderManager;
|
private readonly RenderManager renderManager;
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ namespace Encompass
|
||||||
messageManager = new MessageManager();
|
messageManager = new MessageManager();
|
||||||
componentMessageManager = new ComponentMessageManager();
|
componentMessageManager = new ComponentMessageManager();
|
||||||
entityManager = new EntityManager(componentManager, componentMessageManager);
|
entityManager = new EntityManager(componentManager, componentMessageManager);
|
||||||
|
timeManager = new TimeManager();
|
||||||
renderManager = new RenderManager(componentManager, drawLayerManager, entityManager);
|
renderManager = new RenderManager(componentManager, drawLayerManager, entityManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ namespace Encompass
|
||||||
engine.AssignComponentManager(componentManager);
|
engine.AssignComponentManager(componentManager);
|
||||||
engine.AssignMessageManager(messageManager);
|
engine.AssignMessageManager(messageManager);
|
||||||
engine.AssignComponentMessageManager(componentMessageManager);
|
engine.AssignComponentMessageManager(componentMessageManager);
|
||||||
|
engine.AssignTimeManager(timeManager);
|
||||||
|
|
||||||
engines.Add(engine);
|
engines.Add(engine);
|
||||||
engineGraph.AddNode(engine);
|
engineGraph.AddNode(engine);
|
||||||
|
@ -232,8 +234,27 @@ namespace Encompass
|
||||||
var writePriorities = new Dictionary<Type, HashSet<int>>();
|
var writePriorities = new Dictionary<Type, HashSet<int>>();
|
||||||
var writeMessageToEngines = new Dictionary<Type, List<Engine>>();
|
var writeMessageToEngines = new Dictionary<Type, List<Engine>>();
|
||||||
|
|
||||||
|
var timeDilationPriorities = new Dictionary<int, HashSet<Engine>>();
|
||||||
|
|
||||||
foreach (var engine in engines)
|
foreach (var engine in engines)
|
||||||
{
|
{
|
||||||
|
var timeDilationPriorityAttribute = engine.GetType().GetCustomAttribute<TimeDilationPriority>();
|
||||||
|
|
||||||
|
if (timeDilationPriorityAttribute != null)
|
||||||
|
{
|
||||||
|
engine.timeDilationPriority = timeDilationPriorityAttribute.timeDilationPriority;
|
||||||
|
if (!timeDilationPriorities.ContainsKey(timeDilationPriorityAttribute.timeDilationPriority))
|
||||||
|
{
|
||||||
|
timeDilationPriorities.Add(timeDilationPriorityAttribute.timeDilationPriority, new HashSet<Engine>());
|
||||||
|
}
|
||||||
|
timeDilationPriorities[timeDilationPriorityAttribute.timeDilationPriority].Add(engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (engine.GetType().GetCustomAttribute<IgnoresTimeDilation>() != null)
|
||||||
|
{
|
||||||
|
engine.usesTimeDilation = false;
|
||||||
|
}
|
||||||
|
|
||||||
var defaultWritePriorityAttribute = engine.GetType().GetCustomAttribute<DefaultWritePriority>(false);
|
var defaultWritePriorityAttribute = engine.GetType().GetCustomAttribute<DefaultWritePriority>(false);
|
||||||
|
|
||||||
var writeTypes = engine.sendTypes.Where((type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ComponentWriteMessage<>));
|
var writeTypes = engine.sendTypes.Where((type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ComponentWriteMessage<>));
|
||||||
|
@ -323,6 +344,18 @@ namespace Encompass
|
||||||
throw new EngineWriteConflictException(errorString);
|
throw new EngineWriteConflictException(errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var timeDilationEngines in timeDilationPriorities)
|
||||||
|
{
|
||||||
|
var priority = timeDilationEngines.Key;
|
||||||
|
var engines = timeDilationEngines.Value;
|
||||||
|
if (engines.Count > 1)
|
||||||
|
{
|
||||||
|
var errorString = "Multiple Engines have the same Time Dilation Priority value: ";
|
||||||
|
errorString += string.Join(", ", engines);
|
||||||
|
throw new TimeDilationPriorityConflictException(errorString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var engineOrder = new List<Engine>();
|
var engineOrder = new List<Engine>();
|
||||||
foreach (var engine in engineGraph.TopologicalSort())
|
foreach (var engine in engineGraph.TopologicalSort())
|
||||||
{
|
{
|
||||||
|
@ -335,6 +368,7 @@ namespace Encompass
|
||||||
componentManager,
|
componentManager,
|
||||||
messageManager,
|
messageManager,
|
||||||
componentMessageManager,
|
componentMessageManager,
|
||||||
|
timeManager,
|
||||||
renderManager
|
renderManager
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -910,5 +910,152 @@ namespace Tests
|
||||||
|
|
||||||
resultComponents.Should().BeEmpty();
|
resultComponents.Should().BeEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double dilatedDeltaTime;
|
||||||
|
|
||||||
|
[TimeDilationPriority(0)]
|
||||||
|
class ActivateTimeDilationEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
if (!TimeDilationActive)
|
||||||
|
{
|
||||||
|
ActivateTimeDilation(0.2, 1, 1, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dilatedDeltaTime = dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActivateTimeDilation()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine(new ActivateTimeDilationEngine());
|
||||||
|
|
||||||
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
|
world.Update(0.01); // activate time dilation
|
||||||
|
|
||||||
|
world.Update(0.5);
|
||||||
|
|
||||||
|
dilatedDeltaTime.Should().BeApproximately(0.3, 0.01);
|
||||||
|
|
||||||
|
world.Update(0.5);
|
||||||
|
|
||||||
|
dilatedDeltaTime.Should().BeApproximately(0.1, 0.01);
|
||||||
|
|
||||||
|
world.Update(1);
|
||||||
|
|
||||||
|
world.Update(0.5);
|
||||||
|
|
||||||
|
dilatedDeltaTime.Should().BeApproximately(0.3, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActivateTimeDilationWithoutPriorityEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
ActivateTimeDilation(0.2, 1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActivateTimeDilationWithoutPriorityThrows()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine(new ActivateTimeDilationWithoutPriorityEngine());
|
||||||
|
|
||||||
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
|
Assert.Throws<TimeDilationPriorityUndefinedException>(() => world.Update(0.01));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TimeDilationPriority(0)]
|
||||||
|
class ActivateTimeDilationLowerPriorityEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
if (!TimeDilationActive)
|
||||||
|
{
|
||||||
|
ActivateTimeDilation(0.2, 1, 1, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dilatedDeltaTime = dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TimeDilationPriority(1)]
|
||||||
|
class ActivateTimeDilationHigherPriorityEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
if (!TimeDilationActive)
|
||||||
|
{
|
||||||
|
ActivateTimeDilation(0.5, 1, 1, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dilatedDeltaTime = dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MultipleActivateTimeDilation()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine(new ActivateTimeDilationLowerPriorityEngine());
|
||||||
|
worldBuilder.AddEngine(new ActivateTimeDilationHigherPriorityEngine());
|
||||||
|
|
||||||
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
|
world.Update(0.01); // activate time dilation
|
||||||
|
|
||||||
|
world.Update(0.5);
|
||||||
|
|
||||||
|
dilatedDeltaTime.Should().BeApproximately(0.3, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MultipleActivateTimeDilationWithDuplicatePriority()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine(new ActivateTimeDilationEngine());
|
||||||
|
worldBuilder.AddEngine(new ActivateTimeDilationLowerPriorityEngine());
|
||||||
|
|
||||||
|
Assert.Throws<TimeDilationPriorityConflictException>(() => worldBuilder.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
static double undilatedDeltaTime;
|
||||||
|
|
||||||
|
[IgnoresTimeDilation]
|
||||||
|
class IgnoresTimeDilationEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
undilatedDeltaTime = dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void IgnoresTimeDilation()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine(new ActivateTimeDilationEngine());
|
||||||
|
worldBuilder.AddEngine(new IgnoresTimeDilationEngine());
|
||||||
|
|
||||||
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
|
world.Update(0.01); // activate time dilation
|
||||||
|
|
||||||
|
world.Update(0.5);
|
||||||
|
|
||||||
|
undilatedDeltaTime.Should().Be(0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
using System;
|
using Encompass;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using Encompass;
|
|
||||||
using Encompass.Engines;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Tests
|
namespace Tests
|
||||||
|
|
Loading…
Reference in New Issue