diff options
author | chai <215380520@qq.com> | 2024-06-03 10:15:45 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2024-06-03 10:15:45 +0800 |
commit | acea7b2e728787a0d83bbf83c8c1f042d2c32e7e (patch) | |
tree | 0bfec05c1ca2d71be2c337bcd110a0421f19318b /Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/EntityManager.cs | |
parent | 88febcb02bf127d961c6471d9e846c0e1315f5c3 (diff) |
+ plugins project
Diffstat (limited to 'Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/EntityManager.cs')
-rw-r--r-- | Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/EntityManager.cs | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/EntityManager.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/EntityManager.cs new file mode 100644 index 0000000..5e1d28a --- /dev/null +++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/EntityManager.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Linq; +using Microsoft.Xna.Framework; +using MonoGame.Extended.Collections; +using MonoGame.Extended.Entities.Systems; + +namespace MonoGame.Extended.Entities +{ + public class EntityManager : UpdateSystem + { + private const int _defaultBagSize = 128; + + public EntityManager(ComponentManager componentManager) + { + _componentManager = componentManager; + _addedEntities = new Bag<int>(_defaultBagSize); + _removedEntities = new Bag<int>(_defaultBagSize); + _changedEntities = new Bag<int>(_defaultBagSize); + _entityToComponentBits = new Bag<BitVector32>(_defaultBagSize); + _componentManager.ComponentsChanged += OnComponentsChanged; + + _entityBag = new Bag<Entity>(_defaultBagSize); + _entityPool = new Pool<Entity>(() => new Entity(_nextId++, this, _componentManager), _defaultBagSize); + } + + private readonly ComponentManager _componentManager; + private int _nextId; + + public int Capacity => _entityBag.Capacity; + public IEnumerable<int> Entities => _entityBag.Where(e => e != null).Select(e => e.Id); + public int ActiveCount { get; private set; } + + private readonly Bag<Entity> _entityBag; + private readonly Pool<Entity> _entityPool; + private readonly Bag<int> _addedEntities; + private readonly Bag<int> _removedEntities; + private readonly Bag<int> _changedEntities; + private readonly Bag<BitVector32> _entityToComponentBits; + + public event Action<int> EntityAdded; + public event Action<int> EntityRemoved; + public event Action<int> EntityChanged; + + public Entity Create() + { + var entity = _entityPool.Obtain(); + var id = entity.Id; + Debug.Assert(_entityBag[id] == null); + _entityBag[id] = entity; + _addedEntities.Add(id); + _entityToComponentBits[id] = new BitVector32(0); + return entity; + } + + public void Destroy(int entityId) + { + if (!_removedEntities.Contains(entityId)) + _removedEntities.Add(entityId); + } + + public void Destroy(Entity entity) + { + Destroy(entity.Id); + } + + public Entity Get(int entityId) + { + return _entityBag[entityId]; + } + + public BitVector32 GetComponentBits(int entityId) + { + return _entityToComponentBits[entityId]; + } + + private void OnComponentsChanged(int entityId) + { + _changedEntities.Add(entityId); + _entityToComponentBits[entityId] = _componentManager.CreateComponentBits(entityId); + EntityChanged?.Invoke(entityId); + } + + public override void Update(GameTime gameTime) + { + foreach (var entityId in _addedEntities) + { + _entityToComponentBits[entityId] = _componentManager.CreateComponentBits(entityId); + ActiveCount++; + EntityAdded?.Invoke(entityId); + } + + foreach (var entityId in _changedEntities) + { + _entityToComponentBits[entityId] = _componentManager.CreateComponentBits(entityId); + EntityChanged?.Invoke(entityId); + } + + foreach (var entityId in _removedEntities) + { + // we must notify subscribers before removing it from the pool + // otherwise an entity system could still be using the entity when the same id is obtained. + EntityRemoved?.Invoke(entityId); + + var entity = _entityBag[entityId]; + _entityBag[entityId] = null; + _componentManager.Destroy(entityId); + _entityToComponentBits[entityId] = default(BitVector32); + ActiveCount--; + _entityPool.Free(entity); + } + + _addedEntities.Clear(); + _removedEntities.Clear(); + _changedEntities.Clear(); + } + } +} |