Add door interaction system with state management and event publishing
This commit is contained in:
59
GameCore/Interaction/DoorSystem.cs
Normal file
59
GameCore/Interaction/DoorSystem.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using GameCore.ECS;
|
||||
using GameCore.ECS.Interfaces;
|
||||
using GameCore.Events;
|
||||
|
||||
namespace GameCore.Interaction;
|
||||
|
||||
public class DoorSystem : ISystem
|
||||
{
|
||||
public void Update(World world, float deltaTime)
|
||||
{
|
||||
var doors = world.GetEntitiesWith<DoorComponent>();
|
||||
foreach (var entity in doors)
|
||||
{
|
||||
var door = world.GetComponent<DoorComponent>(entity);
|
||||
if (door == null) continue;
|
||||
|
||||
switch (door.CurrentState)
|
||||
{
|
||||
case DoorComponent.DoorState.Opening:
|
||||
ApplyMovement(entity, door, world, deltaTime, DoorComponent.DoorState.Open,
|
||||
System.Math.Max(door.OpenSpeed, 0f));
|
||||
break;
|
||||
|
||||
case DoorComponent.DoorState.Closing:
|
||||
ApplyMovement(entity, door, world, -deltaTime, DoorComponent.DoorState.Closed, 0f);
|
||||
break;
|
||||
|
||||
case DoorComponent.DoorState.Open:
|
||||
door.Timer = System.Math.Max(door.OpenSpeed, 0f);
|
||||
door.OpenProgress = 1f;
|
||||
break;
|
||||
|
||||
case DoorComponent.DoorState.Closed:
|
||||
case DoorComponent.DoorState.Locked:
|
||||
door.Timer = 0f;
|
||||
door.OpenProgress = 0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyMovement(Entity entity, DoorComponent door, World world, float delta,
|
||||
DoorComponent.DoorState targetState, float targetBoundary)
|
||||
{
|
||||
var effectiveSpeed = System.Math.Max(door.OpenSpeed, 0f);
|
||||
door.Timer = System.Math.Clamp(door.Timer + delta, 0f, effectiveSpeed);
|
||||
|
||||
if (effectiveSpeed > 0f)
|
||||
door.OpenProgress = System.Math.Clamp(door.Timer / effectiveSpeed, 0f, 1f);
|
||||
else
|
||||
door.OpenProgress = door.Timer > 0f ? 1f : 0f;
|
||||
|
||||
if ((!(delta > 0f) || !(door.Timer >= targetBoundary)) &&
|
||||
(!(delta < 0f) || !(door.Timer <= targetBoundary))) return;
|
||||
|
||||
door.CurrentState = targetState;
|
||||
world.PublishEvent(new DoorStateChangedEvent(entity, door.CurrentState));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user