Rewrite
Implement the sparse set and entity registry that entt uses/describes
This commit is contained in:
parent
239ddd1b18
commit
9bf9452cbe
6 changed files with 150 additions and 94 deletions
31
src/Entity.bf
Normal file
31
src/Entity.bf
Normal file
|
@ -0,0 +1,31 @@
|
|||
namespace Theater_ECS;
|
||||
|
||||
using System;
|
||||
|
||||
public struct Entity : uint32
|
||||
{
|
||||
public static readonly Entity Null => 0x000FFFFF;
|
||||
public static readonly uint32 VersionMask => 0xFFF00000;
|
||||
public static readonly uint32 IndexMask => 0x000FFFFF;
|
||||
public static readonly uint8 VersionOffset => 20;
|
||||
|
||||
public uint32 Index => (.)this & IndexMask;
|
||||
public uint32 Version => (.)(this & VersionMask) >> VersionOffset
|
||||
public Entity Next => .(Index, Version + 1);
|
||||
|
||||
public this()
|
||||
{
|
||||
this = Entity.Null;
|
||||
};
|
||||
|
||||
public this(uint32 index, uint32 version)
|
||||
{
|
||||
this = (index & IndexMask) | ((version << VersionOffset) & VersionMask);
|
||||
|
||||
}
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
strBuffer.Append(scope $"{Index}:{Version}");
|
||||
}
|
||||
}
|
|
@ -3,35 +3,6 @@ namespace Theater_ECS;
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
static
|
||||
{
|
||||
|
||||
public struct Entity : uint32
|
||||
{
|
||||
public static readonly Entity Null => 0xFFFFF;
|
||||
public static readonly uint32 VersionMask => 0xFFF00000;
|
||||
public static readonly uint32 IndexMask => 0x000FFFFF;
|
||||
public static readonly uint8 VersionOffset => 20;
|
||||
|
||||
public uint32 Index => (.)this & IndexMask;
|
||||
public uint32 Version => (.)(this & VersionMask) >> VersionOffset
|
||||
public Entity Next => .(Index, Version + 1);
|
||||
|
||||
public this() {};
|
||||
|
||||
public this(uint32 index, uint32 version)
|
||||
{
|
||||
this = (index & IndexMask) | ((version << VersionOffset) & VersionMask);
|
||||
|
||||
}
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
strBuffer.Append(scope $"{Index}:{Version}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EntityRegister
|
||||
{
|
||||
private List<Entity> _entities = new .() ~ delete _;
|
||||
|
@ -39,7 +10,7 @@ class EntityRegister
|
|||
private Entity _next = .Null;
|
||||
|
||||
|
||||
public Entity CreateEntity()
|
||||
public Entity Create()
|
||||
{
|
||||
if(_available == 0)
|
||||
{
|
||||
|
@ -59,7 +30,7 @@ class EntityRegister
|
|||
}
|
||||
}
|
||||
|
||||
public void RemoveEntity(Entity e)
|
||||
public void Remove(Entity e)
|
||||
{
|
||||
let temp = _next;
|
||||
_next = .(e.Index, 255);
|
||||
|
|
|
@ -7,7 +7,7 @@ class MoverSystem : System
|
|||
[SystemMethod("MoveItems", typeof(Velocity), typeof(Position))]
|
||||
public void MoveItems(ref Velocity v,ref Position p)
|
||||
{
|
||||
//p.x = v.x + p.x;
|
||||
//p.y = v.y = p.y;
|
||||
p.x = v.x + p.x;
|
||||
p.y = v.y = p.y;
|
||||
}
|
||||
}
|
|
@ -11,68 +11,38 @@ class Program
|
|||
|
||||
public static void Main()
|
||||
{
|
||||
/*
|
||||
Entity e = Entity(45454, 797979790);
|
||||
Console.WriteLine(e);
|
||||
Console.Read();
|
||||
|
||||
EntityRegister r = scope .();
|
||||
while(true)
|
||||
{
|
||||
Console.WriteLine(scope $"Next: {r.[Friend]_next}");
|
||||
for(var i in r.[Friend]_entities)
|
||||
Console.WriteLine(i);
|
||||
var l = Console.ReadLine(.. scope .());
|
||||
|
||||
Console.Clear();
|
||||
|
||||
if(l == "c")
|
||||
Console.WriteLine(r.CreateEntity());
|
||||
else if(l == "d")
|
||||
r.RemoveEntity(.((.)gRand.Next(0 , r.[Friend]_entities.Count), 0));
|
||||
Console.WriteLine();
|
||||
}
|
||||
*/
|
||||
|
||||
ECS ecs = scope .();
|
||||
var pos = ecs.RegisterComponent<Position>(100);
|
||||
//var waste = ecs.RegisterComponent<waste>(100);
|
||||
var vel = ecs.RegisterComponent<Velocity>(100);
|
||||
|
||||
|
||||
List<Entity> entities = scope .();
|
||||
for(int i < 500000)
|
||||
entities.Add(ecs.CreateEntity());
|
||||
|
||||
for(var i in entities)
|
||||
*(Position*)ecs.AddComponentToEntity(i, pos).Value = .();
|
||||
|
||||
for(var i in entities)
|
||||
*(Velocity*)ecs.AddComponentToEntity(i, vel).Value = .();
|
||||
|
||||
/*
|
||||
for(var i in entities)
|
||||
if(gRand.NextI32() % 2 == 1)
|
||||
*(waste*)ecs.AddComponentToEntity(i, waste).Value = .();
|
||||
*/
|
||||
|
||||
MoverSystem s = scope .();
|
||||
s.IntializeSystem(ecs);
|
||||
|
||||
System.Diagnostics.Stopwatch watch = scope .();
|
||||
for(int a < 10)
|
||||
{
|
||||
watch.Start();
|
||||
for(int i < 10)
|
||||
EntityRegister e = scope .();
|
||||
PagedSparseSet<Position> p = scope .();
|
||||
PagedSparseSet<Velocity> v =scope .();
|
||||
List<Entity> es = new .();
|
||||
defer delete es;
|
||||
for(int i < 1000000)
|
||||
{
|
||||
|
||||
s.RunSystem(ecs);
|
||||
|
||||
var ent = e.Create();
|
||||
p.Add(ent, .());
|
||||
v.Add(ent, .());
|
||||
es.Add(ent);
|
||||
}
|
||||
|
||||
System.Diagnostics.Stopwatch watch = scope .();
|
||||
for(int a < 10)
|
||||
{
|
||||
watch.Start();
|
||||
for(int i < 10)
|
||||
{
|
||||
var pos = p.GetAll();
|
||||
var vel = v.GetAll();
|
||||
|
||||
for(var ps in pos)
|
||||
{
|
||||
ps.1.x += vel[@ps.Index].1.x;
|
||||
ps.1.y += vel[@ps.Index].1.y;
|
||||
}
|
||||
}
|
||||
Console.WriteLine(scope $"{watch.ElapsedMilliseconds}ms");
|
||||
watch.Stop();
|
||||
watch.Reset();
|
||||
}
|
||||
Console.WriteLine(scope $"{watch.ElapsedMilliseconds}ms");
|
||||
watch.Stop();
|
||||
watch.Reset();
|
||||
}
|
||||
Console.Read();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,77 @@
|
|||
namespace Theater_ECS;
|
||||
|
||||
class PagedSparseSet<T>
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
class PagedSparseSet<T> where T : struct
|
||||
{
|
||||
public const uint32 PageSize = 4096;
|
||||
|
||||
private List<List<Entity>> _sparse = new .()~ DeleteContainerAndItems!(_);
|
||||
private List<(Entity, T)> _packed = new .() ~ delete _;
|
||||
private List<T> _packedEntities = new .() ~ delete _;
|
||||
|
||||
public (Entity, T) this[Entity e]
|
||||
{
|
||||
public get => _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index];
|
||||
}
|
||||
|
||||
public bool Contains(Entity e)
|
||||
{
|
||||
return _sparse[e.Index/PageSize][e.Index % PageSize] != Entity.Null;
|
||||
}
|
||||
|
||||
public void Add(Entity e, T toAdd)
|
||||
{
|
||||
EnsureLoadedPage(e.Index/PageSize);
|
||||
_packed.Add((e, toAdd));
|
||||
_sparse[e.Index/PageSize][e.Index % PageSize] = (.)_packed.Count-1;
|
||||
}
|
||||
|
||||
public void Remove(Entity e)
|
||||
{
|
||||
EnsurePage(e.Index/PageSize);
|
||||
if(_sparse[e.Index/PageSize] == null)
|
||||
return;
|
||||
|
||||
let toRm = _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index];
|
||||
let b = _packed.Back;
|
||||
_packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index] = b;
|
||||
_packed.Back = toRm;
|
||||
|
||||
_sparse[b.0.Index/PageSize][b.0.Index % PageSize] = Entity(e.Index, b.0.Version);
|
||||
_sparse[e.Index/PageSize][e.Index % PageSize] = Entity.Null;
|
||||
|
||||
_packed.PopBack();
|
||||
}
|
||||
|
||||
public T* Get(Entity e)
|
||||
{
|
||||
return &_packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index].1;
|
||||
}
|
||||
|
||||
public Span<(Entity, T)> GetAll()
|
||||
{
|
||||
return _packed;
|
||||
}
|
||||
|
||||
///Ensure that a page exist and is loaded
|
||||
public void EnsureLoadedPage(uint32 page)
|
||||
{
|
||||
EnsurePage(page);
|
||||
if(_sparse[page] == null)
|
||||
{
|
||||
_sparse[page] = new List<Entity>(PageSize);
|
||||
_sparse[page].[Friend]Count = 4096;
|
||||
_sparse[page].SetAll(Entity.Null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
///Ensure that a page exists, it might be null though
|
||||
private void EnsurePage(uint32 page)
|
||||
{
|
||||
while(_sparse.Count < page+1)
|
||||
_sparse.Add(null);
|
||||
}
|
||||
}
|
12
src/World.bf
Normal file
12
src/World.bf
Normal file
|
@ -0,0 +1,12 @@
|
|||
namespace Theater_ECS;
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
class World
|
||||
{
|
||||
EntityRegister Registry = new .() ~ delete _;
|
||||
|
||||
private Dictionary<Type, uint32> _components = new .() ~ delete _;
|
||||
private List<Variant> _componentStorage = new .() ~ DeleteContainerAndDisposeItems!(_);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue