implemented aspect filtering builder

This commit is contained in:
Dylan Wilson
2018-06-10 23:49:35 +10:00
parent 30f852253f
commit a9ec00a21f
16 changed files with 397 additions and 30 deletions
+108
View File
@@ -0,0 +1,108 @@
using System;
using System.Collections;
using MonoGame.Extended.Collections;
namespace MonoGame.Extended.Entities
{
public class Aspect
{
private Aspect()
{
AllSet = new BitArray(32);
ExclusionSet = new BitArray(32);
OneSet = new BitArray(32);
}
public BitArray AllSet { get; }
public BitArray ExclusionSet { get; }
public BitArray OneSet { get; }
public static Builder All(params Type[] types)
{
return new Builder().All(types);
}
public static Builder One(params Type[] types)
{
return new Builder().One(types);
}
public static Builder Exclude(params Type[] types)
{
return new Builder().Exclude(types);
}
public bool IsInterested(BitArray componentBits)
{
if (!AllSet.IsEmpty() && !componentBits.ContainsAll(AllSet))
return false;
if (!ExclusionSet.IsEmpty() && ExclusionSet.Intersects(componentBits))
return false;
if (!OneSet.IsEmpty() && !OneSet.Intersects(componentBits))
return false;
return true;
}
public class Builder
{
public Builder()
{
AllTypes = new Bag<Type>();
ExclusionTypes = new Bag<Type>();
OneTypes = new Bag<Type>();
}
public Bag<Type> AllTypes { get; }
public Bag<Type> ExclusionTypes { get; }
public Bag<Type> OneTypes { get; }
public Builder All(params Type[] types)
{
foreach (var type in types)
AllTypes.Add(type);
return this;
}
public Builder One(params Type[] types)
{
foreach (var type in types)
OneTypes.Add(type);
return this;
}
public Builder Exclude(params Type[] types)
{
foreach (var type in types)
ExclusionTypes.Add(type);
return this;
}
public Aspect Build(ComponentManager componentManager)
{
var aspect = new Aspect();
Associate(componentManager, AllTypes, aspect.AllSet);
Associate(componentManager, OneTypes, aspect.OneSet);
Associate(componentManager, ExclusionTypes, aspect.ExclusionSet);
return aspect;
}
// ReSharper disable once ParameterTypeCanBeEnumerable.Local
private static void Associate(ComponentManager componentManager, Bag<Type> types, BitArray bitArray)
{
foreach (var type in types)
{
var id = componentManager.GetComponentTypeId(type);
bitArray.Set(id, true);
}
}
}
}
}
@@ -0,0 +1,54 @@
using System;
using System.Collections;
namespace MonoGame.Extended.Entities
{
public static class BitArrayExtensions
{
public static bool IsEmpty(this BitArray bitArray)
{
for (var i = 0; i < bitArray.Length; i++)
{
if (bitArray[i])
return false;
}
return true;
}
public static bool ContainsAll(this BitArray bitArray, BitArray other)
{
var otherBitsLength = other.Length;
var bitsLength = bitArray.Length;
for (var i = bitsLength; i < otherBitsLength; i++)
{
if (other[i])
return false;
}
var s = Math.Min(bitsLength, otherBitsLength);
for (var i = 0; s > i; i++)
{
if ((bitArray[i] & other[i]) != other[i])
return false;
}
return true;
}
public static bool Intersects(this BitArray bitArray, BitArray other)
{
var s = Math.Min(bitArray.Length, other.Length);
for (var i = 0; s > i; i++)
{
if (bitArray[i] & other[i])
return true;
}
return false;
}
}
}
@@ -9,6 +9,7 @@ namespace MonoGame.Extended.Entities
public class ComponentManager : UpdateSystem
{
public ComponentManager()
: base(Aspect.All())
{
_mappers = new Bag<ComponentMapper>();
_componentTypes = new Dictionary<Type, int>();
@@ -17,10 +18,9 @@ namespace MonoGame.Extended.Entities
private readonly Bag<ComponentMapper> _mappers;
private readonly Dictionary<Type, int> _componentTypes;
private ComponentMapper<T> CreateMapperForType<T>()
private ComponentMapper<T> CreateMapperForType<T>(int id)
where T : class
{
var id = _mappers.Count;
var mapper = new ComponentMapper<T>(id);
_mappers[id] = mapper;
return mapper;
@@ -29,12 +29,22 @@ namespace MonoGame.Extended.Entities
public ComponentMapper<T> GetMapper<T>()
where T : class
{
if (_componentTypes.TryGetValue(typeof(T), out var id))
var id = GetComponentTypeId(typeof(T));
if (_mappers[id] != null)
return _mappers[id] as ComponentMapper<T>;
var mapper = CreateMapperForType<T>();
_componentTypes.Add(typeof(T), mapper.Id);
return mapper;
return CreateMapperForType<T>(id);
}
public int GetComponentTypeId(Type type)
{
if (_componentTypes.TryGetValue(type, out var id))
return id;
id = _componentTypes.Count;
_componentTypes.Add(type, id);
return id;
}
public override void Initialize(ComponentManager componentManager)
@@ -24,7 +24,6 @@ namespace MonoGame.Extended.Entities
Components = new Bag<T>();
}
public int Id { get; }
public Bag<T> Components { get; }
public void CreateComponent(int entityId, T component)
@@ -7,6 +7,7 @@ namespace MonoGame.Extended.Entities
public class EntityManager : UpdateSystem
{
public EntityManager(ComponentManager componentManager)
: base(Aspect.All())
{
_componentManager = componentManager;
Entities = new Bag<Entity>(128);
@@ -1,5 +1,4 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using MonoGame.Extended.Collections;
using MonoGame.Extended.Entities.Systems;
@@ -1,8 +1,26 @@
namespace MonoGame.Extended.Entities.Systems
using MonoGame.Extended.Collections;
namespace MonoGame.Extended.Entities.Systems
{
public abstract class BaseSystem
{
private readonly Aspect.Builder _aspectBuilder;
protected BaseSystem(Aspect.Builder aspect)
{
_aspectBuilder = aspect;
}
protected Aspect Aspect { get; private set; }
public EntityWorld World { get; internal set; }
public abstract void Initialize(ComponentManager componentManager);
protected Bag<Entity> GetEntities()
{
var aspect = _aspectBuilder.Build(World.ComponentManager);
return World.EntityManager.Entities;
}
}
}
@@ -4,7 +4,8 @@ namespace MonoGame.Extended.Entities.Systems
{
public abstract class DrawSystem : BaseSystem
{
protected DrawSystem()
protected DrawSystem(Aspect.Builder aspect)
: base(aspect)
{
}
@@ -4,7 +4,8 @@ namespace MonoGame.Extended.Entities.Systems
{
public abstract class UpdateSystem : BaseSystem
{
protected UpdateSystem()
protected UpdateSystem(Aspect.Builder aspect)
: base(aspect)
{
}