Created
July 23, 2021 17:48
-
-
Save rossimo/d967d84ea5cfddcc48939696ae56aeb8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Godot; | |
using Leopotam.EcsLite; | |
public class Game : Godot.YSort | |
{ | |
public EcsWorld world; | |
public EcsSystems systems; | |
public override void _Ready() | |
{ | |
world = new EcsWorld(); | |
systems = new EcsSystems(world, this) | |
.Add(new Renderer(world)); | |
var sprites = world.GetPool<Sprite>(); | |
var positions = world.GetPool<Position>(); | |
{ | |
var player = world.NewEntity(); | |
ref var sprite = ref sprites.Create(world, player); | |
sprite.Image = "res://resources/tiles/tile072.png"; | |
ref var position = ref positions.Create(world, player); | |
position.X = 50; | |
position.Y = 50; | |
} | |
} | |
public override void _PhysicsProcess(float delta) | |
{ | |
systems.Run(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Godot; | |
using Leopotam.EcsLite; | |
public struct Sprite | |
{ | |
public string Image; | |
} | |
public struct Position | |
{ | |
public float X; | |
public float Y; | |
} | |
public class Renderer : IEcsRunSystem | |
{ | |
private UpdateQueue<Sprite> _spriteUpdates; | |
private UpdateQueue<Position> _positionUpdates; | |
public Renderer(EcsWorld world) | |
{ | |
_spriteUpdates = new UpdateQueue<Sprite>(world); | |
_positionUpdates = new UpdateQueue<Position>(world); | |
} | |
public void Run(EcsSystems systems) | |
{ | |
var game = systems.GetShared<Game>(); | |
foreach (int entity in _spriteUpdates) | |
{ | |
ref var sprite = ref _spriteUpdates.Get(entity); | |
game.AddChild(new Godot.Sprite() | |
{ | |
Name = $"{entity}", | |
Texture = GD.Load<Texture>(sprite.Image) | |
}); | |
} | |
foreach (int entity in _positionUpdates) | |
{ | |
ref var position = ref _positionUpdates.Get(entity); | |
var node = game.GetNodeOrNull<Godot.Sprite>($"{entity}"); | |
node.Position = new Vector2(position.X, position.Y); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Leopotam.EcsLite; | |
using System.Runtime.CompilerServices; | |
public struct Update<T> | |
{ | |
public EcsPackedEntity Entity; | |
} | |
public class UpdateQueue<C> | |
where C : struct | |
{ | |
private EcsWorld World; | |
private EcsFilter Filter; | |
private EcsPool<C> ComponentsPool; | |
private EcsPool<Update<C>> UpdatePool; | |
public UpdateQueue(EcsWorld world) | |
{ | |
World = world; | |
ComponentsPool = World.GetPool<C>(); | |
UpdatePool = World.GetPool<Update<C>>(); | |
Filter = World.Filter<C>().Inc<Update<C>>().End(); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public Enumerator<C> GetEnumerator() | |
{ | |
return new Enumerator<C>(Filter.GetEnumerator(), World, UpdatePool); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public ref C Get(int entity) | |
{ | |
return ref ComponentsPool.Get(entity); | |
} | |
public struct Enumerator<X> : IDisposable | |
where X : struct | |
{ | |
EcsFilter.Enumerator _enumerator; | |
int _current; | |
readonly EcsPool<Update<X>> _updatePool; | |
readonly EcsWorld _world; | |
public Enumerator(EcsFilter.Enumerator enumerator, EcsWorld world, EcsPool<Update<X>> updatePool) | |
{ | |
_enumerator = enumerator; | |
_updatePool = updatePool; | |
_world = world; | |
_current = -1; | |
} | |
public int Current | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
get => _current; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public bool MoveNext() | |
{ | |
while (_enumerator.MoveNext()) | |
{ | |
var current = _enumerator.Current; | |
var update = _updatePool.Get(current); | |
_updatePool.Del(current); | |
if (update.Entity.Unpack(_world, out var entity)) | |
{ | |
_current = entity; | |
return true; | |
} | |
} | |
return false; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public void Dispose() | |
{ | |
_enumerator.Dispose(); | |
} | |
} | |
} | |
public static class UpdateUtils | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static ref C Create<C>(this EcsPool<C> pool, EcsWorld world, int entity) | |
where C : struct | |
{ | |
ref var component = ref pool.Add(entity); | |
Update(pool, world, entity); | |
return ref component; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static void Update<C>(this EcsPool<C> pool, EcsWorld world, int entity) | |
where C : struct | |
{ | |
ref var update = ref world.GetPool<Update<C>>().Add(entity); | |
update.Entity = world.PackEntity(entity); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment