diff --git a/Source/Demos/Sandbox/GameMain.cs b/Source/Demos/Sandbox/GameMain.cs index 67e0e886..dfa3a037 100644 --- a/Source/Demos/Sandbox/GameMain.cs +++ b/Source/Demos/Sandbox/GameMain.cs @@ -31,11 +31,11 @@ namespace Sandbox var random = new FastRandom(); - for(var i = 0; i < 50000; i++) + for(var i = 0; i < 2000; i++) { var entity = _world.CreateEntity(); entity.Attach(new Transform2(random.NextSingle(0, 800), random.NextSingle(-480, 480))); - entity.Attach(new Raindrop { Velocity = new Vector2(random.Next(-3, 3), random.Next(-100)) }); + entity.Attach(new Raindrop { Velocity = new Vector2(random.Next(-3, 3), random.Next(-10, 10)) }); } } diff --git a/Source/MonoGame.Extended.Entities/ComponentManager.cs b/Source/MonoGame.Extended.Entities/ComponentManager.cs index a2c64921..ea2877ee 100644 --- a/Source/MonoGame.Extended.Entities/ComponentManager.cs +++ b/Source/MonoGame.Extended.Entities/ComponentManager.cs @@ -26,8 +26,11 @@ namespace MonoGame.Extended.Entities public Action ComponentsChanged; private ComponentMapper CreateMapperForType(int componentTypeId) - where T : class + where T : class { + if (componentTypeId >= 32) + throw new InvalidOperationException("Component type limit exceeded. We currently only allow 32 component types for performance reasons."); + var mapper = new ComponentMapper(componentTypeId, ComponentsChanged); _componentMappers[componentTypeId] = mapper; return mapper; @@ -59,7 +62,7 @@ namespace MonoGame.Extended.Entities return id; } - public BitVector32 GetComponentBits(int entityId) + public BitVector32 CreateComponentBits(int entityId) { var componentBits = new BitVector32(); var mask = BitVector32.CreateMask(); diff --git a/Source/MonoGame.Extended.Entities/Entity.cs b/Source/MonoGame.Extended.Entities/Entity.cs index 4be7eafe..036ab290 100644 --- a/Source/MonoGame.Extended.Entities/Entity.cs +++ b/Source/MonoGame.Extended.Entities/Entity.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Specialized; namespace MonoGame.Extended.Entities diff --git a/Source/MonoGame.Extended.Entities/EntityManager.cs b/Source/MonoGame.Extended.Entities/EntityManager.cs index 6e69ed4c..04a28f0d 100644 --- a/Source/MonoGame.Extended.Entities/EntityManager.cs +++ b/Source/MonoGame.Extended.Entities/EntityManager.cs @@ -49,9 +49,10 @@ namespace MonoGame.Extended.Entities public void DestroyEntity(int entityId) { + _removedEntities.Add(entityId); + _entityToComponentBits[entityId] = default(BitVector32); + Entities[entityId] = null; EntityRemoved?.Invoke(entityId); - throw new NotImplementedException(); - //Entities[entityId] = null; } public void DestroyEntity(Entity entity) @@ -73,22 +74,22 @@ namespace MonoGame.Extended.Entities { foreach (var entity in _addedEntities) { - _entityToComponentBits[entity] = _componentManager.GetComponentBits(entity); + _entityToComponentBits[entity] = _componentManager.CreateComponentBits(entity); EntityAdded?.Invoke(entity); } + foreach (var entity in _changedEntities) + { + _entityToComponentBits[entity] = _componentManager.CreateComponentBits(entity); + EntityChanged?.Invoke(entity); + } + foreach (var entity in _removedEntities) { _entityToComponentBits[entity] = default(BitVector32); EntityRemoved?.Invoke(entity); } - foreach (var entity in _changedEntities) - { - _entityToComponentBits[entity] = _componentManager.GetComponentBits(entity); - EntityChanged?.Invoke(entity); - } - _addedEntities.Clear(); _removedEntities.Clear(); _changedEntities.Clear(); diff --git a/Source/MonoGame.Extended.Entities/EntitySubscription.cs b/Source/MonoGame.Extended.Entities/EntitySubscription.cs index ce694105..3a2e98ac 100644 --- a/Source/MonoGame.Extended.Entities/EntitySubscription.cs +++ b/Source/MonoGame.Extended.Entities/EntitySubscription.cs @@ -3,12 +3,12 @@ using MonoGame.Extended.Collections; namespace MonoGame.Extended.Entities { - public class EntitySubscription : IDisposable + internal class EntitySubscription : IDisposable { private readonly Bag _activeEntities; private readonly EntityManager _entityManager; private readonly Aspect _aspect; - private readonly bool _rebuildActives; + private bool _rebuildActives; internal EntitySubscription(EntityManager entityManager, Aspect aspect) { @@ -19,10 +19,17 @@ namespace MonoGame.Extended.Entities _entityManager.EntityAdded += OnEntityAdded; _entityManager.EntityRemoved += OnEntityRemoved; + _entityManager.EntityChanged += OnEntityChanged; } - private void OnEntityAdded(int id) => _activeEntities.Add(id); - private void OnEntityRemoved(int id) => _activeEntities.Remove(id); + private void OnEntityAdded(int entityId) + { + if (_aspect.IsInterested(_entityManager.GetComponentBits(entityId))) + _activeEntities.Add(entityId); + } + + private void OnEntityRemoved(int entityId) => _rebuildActives = true; + private void OnEntityChanged(int entityId) => _rebuildActives = true; public void Dispose() { @@ -43,17 +50,12 @@ namespace MonoGame.Extended.Entities private void RebuildActives() { - var count = 0; _activeEntities.Clear(); foreach (var entity in _entityManager.Entities) - { - if (_aspect.IsInterested(entity.ComponentBits)) - { - _activeEntities[count] = entity.Id; - count++; - } - } + OnEntityAdded(entity.Id); + + _rebuildActives = false; } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Systems/EntityUpdateSystem.cs b/Source/MonoGame.Extended.Entities/Systems/EntityUpdateSystem.cs index a7c64f2b..e08cd738 100644 --- a/Source/MonoGame.Extended.Entities/Systems/EntityUpdateSystem.cs +++ b/Source/MonoGame.Extended.Entities/Systems/EntityUpdateSystem.cs @@ -9,6 +9,17 @@ namespace MonoGame.Extended.Entities.Systems _aspectBuilder = aspectBuilder; } + public override void Dispose() + { + if (_world != null) + { + _world.EntityManager.EntityAdded -= OnEntityAdded; + _world.EntityManager.EntityRemoved -= OnEntityRemoved; + } + + base.Dispose(); + } + private readonly AspectBuilder _aspectBuilder; private EntitySubscription _subscription; @@ -20,8 +31,6 @@ namespace MonoGame.Extended.Entities.Systems { _world = value; _subscription = new EntitySubscription(_world.EntityManager, _aspectBuilder.Build(_world.ComponentManager)); - - // TODO: Undisposed events. _world.EntityManager.EntityAdded += OnEntityAdded; _world.EntityManager.EntityRemoved += OnEntityRemoved; } diff --git a/Source/MonoGame.Extended/Collections/Deque.cs b/Source/MonoGame.Extended/Collections/Deque.cs index a03b1105..14e6a8fe 100644 --- a/Source/MonoGame.Extended/Collections/Deque.cs +++ b/Source/MonoGame.Extended/Collections/Deque.cs @@ -131,8 +131,8 @@ namespace MonoGame.Extended.Collections /// public Func ResizeFunction { - get { return _resizeFunction; } - set { _resizeFunction = value ?? Deque.DefaultResizeFunction; } + get => _resizeFunction; + set => _resizeFunction = value ?? Deque.DefaultResizeFunction; } /// @@ -148,7 +148,7 @@ namespace MonoGame.Extended.Collections /// public int Capacity { - get { return _items.Length; } + get => _items.Length; set { if (value < Count) @@ -274,14 +274,17 @@ namespace MonoGame.Extended.Collections public int IndexOf(T item) { var comparer = EqualityComparer.Default; - T checkFrontBackItem; - if (Get(0, out checkFrontBackItem) && comparer.Equals(checkFrontBackItem, item)) + + if (Get(0, out var checkFrontBackItem) && comparer.Equals(checkFrontBackItem, item)) return 0; + var backIndex = Count - 1; + if (Get(backIndex, out checkFrontBackItem) && comparer.Equals(checkFrontBackItem, item)) return backIndex; int index; + if (Count <= _items.Length - _frontArrayIndex) index = Array.IndexOf(_items, item, _frontArrayIndex, Count); else