mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-24 12:06:37 +00:00
149 lines
4.5 KiB
C#
149 lines
4.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Microsoft.Xna.Framework;
|
|
using MonoGame.Extended.Entities.Components;
|
|
using MonoGame.Extended.Entities.Systems;
|
|
|
|
namespace MonoGame.Extended.Entities
|
|
{
|
|
public class EntityComponentSystem
|
|
{
|
|
private readonly List<EntityComponent> _components;
|
|
private readonly List<DyingEntity> _dyingEntities;
|
|
private readonly List<Entity> _entities;
|
|
private readonly Dictionary<string, Entity> _entitiesByName;
|
|
|
|
private readonly List<ComponentSystem> _systems;
|
|
private long _nextEntityId;
|
|
|
|
public EntityComponentSystem()
|
|
{
|
|
_entities = new List<Entity>();
|
|
_entitiesByName = new Dictionary<string, Entity>();
|
|
_dyingEntities = new List<DyingEntity>();
|
|
_components = new List<EntityComponent>();
|
|
_systems = new List<ComponentSystem>();
|
|
_nextEntityId = 1;
|
|
}
|
|
|
|
internal event EventHandler<EntityComponent> ComponentAttached;
|
|
internal event EventHandler<EntityComponent> ComponentDetached;
|
|
internal event EventHandler<Entity> EntityCreated;
|
|
internal event EventHandler<Entity> EntityDestroyed;
|
|
|
|
public void RegisterSystem(ComponentSystem system)
|
|
{
|
|
if (system.Parent != null)
|
|
throw new InvalidOperationException("Component system already registered");
|
|
|
|
system.Parent = this;
|
|
_systems.Add(system);
|
|
}
|
|
|
|
public Entity CreateEntity()
|
|
{
|
|
return CreateEntity(null);
|
|
}
|
|
|
|
public Entity CreateEntity(Vector2 position, float rotation = 0)
|
|
{
|
|
return CreateEntity(null, position, rotation);
|
|
}
|
|
|
|
public Entity CreateEntity(string name, Vector2 position, float rotation = 0)
|
|
{
|
|
var entity = CreateEntity(name);
|
|
entity.Position = position;
|
|
entity.Rotation = rotation;
|
|
return entity;
|
|
}
|
|
|
|
public Entity CreateEntity(string name)
|
|
{
|
|
var entity = new Entity(this, _nextEntityId, name);
|
|
|
|
_entities.Add(entity);
|
|
|
|
if (name != null)
|
|
_entitiesByName.Add(name, entity);
|
|
|
|
EntityCreated?.Invoke(this, entity);
|
|
_nextEntityId++;
|
|
return entity;
|
|
}
|
|
|
|
public void DestroyEntity(Entity entity, float delaySeconds)
|
|
{
|
|
if (delaySeconds.Equals(0f))
|
|
DestroyEntity(entity);
|
|
else
|
|
_dyingEntities.Add(new DyingEntity {Entity = entity, SecondsUntilDeath = delaySeconds});
|
|
}
|
|
|
|
public void DestroyEntity(Entity entity)
|
|
{
|
|
foreach (var component in _components.Where(c => c.Entity == entity).ToArray())
|
|
DetachComponent(component);
|
|
|
|
if (entity.Name != null)
|
|
_entitiesByName.Remove(entity.Name);
|
|
|
|
_entities.Remove(entity);
|
|
EntityDestroyed?.Invoke(this, entity);
|
|
}
|
|
|
|
public Entity GetEntity(string name)
|
|
{
|
|
Entity entity;
|
|
return _entitiesByName.TryGetValue(name, out entity) ? entity : null;
|
|
}
|
|
|
|
internal void AttachComponent(EntityComponent component)
|
|
{
|
|
_components.Add(component);
|
|
ComponentAttached?.Invoke(this, component);
|
|
}
|
|
|
|
internal void DetachComponent(EntityComponent component)
|
|
{
|
|
_components.Remove(component);
|
|
(component as IDisposable)?.Dispose();
|
|
ComponentDetached?.Invoke(this, component);
|
|
}
|
|
|
|
internal IEnumerable<T> GetComponents<T>() where T : EntityComponent
|
|
{
|
|
return _components.OfType<T>();
|
|
}
|
|
|
|
public void Update(GameTime gameTime)
|
|
{
|
|
foreach (var componentSystem in _systems)
|
|
componentSystem.Update(gameTime);
|
|
|
|
for (var i = 0; i < _dyingEntities.Count; i++)
|
|
{
|
|
_dyingEntities[i].SecondsUntilDeath -= gameTime.GetElapsedSeconds();
|
|
|
|
if (_dyingEntities[i].SecondsUntilDeath <= 0)
|
|
{
|
|
DestroyEntity(_dyingEntities[i].Entity);
|
|
_dyingEntities.Remove(_dyingEntities[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Draw(GameTime gameTime)
|
|
{
|
|
foreach (var componentSystem in _systems)
|
|
componentSystem.Draw(gameTime);
|
|
}
|
|
|
|
public class DyingEntity
|
|
{
|
|
public Entity Entity;
|
|
public float SecondsUntilDeath;
|
|
}
|
|
}
|
|
} |