Improvement: Make manual creation of Mappers obsolete
Marty opened this issue · 1 comments
I made the manual creation of Mapper
s in my project obsolete.
It works nicely for me that way but it would be better suited in the library itself.
The MapperSystem
holds a Map
with the mappers by type.
This does not need to be a system and could be integrated in World
.
class MapperSystem extends VoidEntitySystem {
final Map<Type, Mapper> _mappers = {};
Mapper<T> mapper<T extends Component>() {
return _mappers.putIfAbsent(T, () => Mapper<T>(world)) as Mapper<T>;
}
@override
void initialize() {
}
@override
void processSystem() {
}
}
To access this conveniently, I have two extensions:
extension MapperSystemExtension on EntitySystem {
T? getComponent<T extends Component>(int entity) {
return world.mapper<T>().getSafe(entity);
}
bool hasComponent<T extends Component>(int entity) {
return world.mapper<T>().has(entity);
}
}
extension MapperWorldExtension on World {
Mapper<T> mapper<T extends Component>() {
return getSystem<MapperSystem>().mapper<T>();
}
T? getComponent<T extends Component>(int entity) {
return mapper<T>().getSafe(entity);
}
}
It can then be used like this:
var position = getComponent<Position>(entity)!;
A nice sideeffect that I did not think of prior is, that you can easily navigate to the Component
in question (in this case Position
) without jumping to the definition of the mapper first. I find myself using that quite often.
Do you see any downsides to this?
I'd be happy to create a PR :)
Hot damn. That looks great.
If you can get the tests to work despite #60 then go ahead with your PR.
Though I would prefer it if the getComponent
method returns a T
instead of a T?
and used the []
operator instead of getSafe
. And return T?
with a getOptionalComponent
that uses OptionalMapper
. Or is there a reason you are doing it your way?
The only downsides I can think of at the moment (but they are negligible because you can still use the manual/generated way depending on your personal preferences):
- it could be a (very low key) performance issue in
EntityComponentSystem
s when iterating over a lot of entities and each time getting all required mappers by accessing a map, especially in systems that don't do much else (but overall it should be very minuscule and ignorable because you usually do a lot more) - it's a bit more typing when accessing a component (with IDE and content assist)
pos ctrl+space enter [entity];
vsgetC ctrl+space enter <Position>(entity);
but that's just lazy me and I've removed that part for me a different way.
I am so used to dartemis_builder
I never create my mappers manually anyway. I don't know if you have looked at it, but with it a MovementSystem
would look like this, and there would be no need to create or access mappers:
@Generate(
EntityProcessingSystem,
allOf: [
Position,
Velocity,
],
)
class SimpleMovementSystem extends _$SimpleMovementSystem {
@override
void processEntity(int entity, Position position, Velocity velocity) {
position
..x += velocity.x * world.delta
..y += velocity.y * world.delta;
}
}
EDIT: Oh, I see I need to update the dartemis readme with this example.