Artemis-odb, how to initialize components?

Hey, everyone.

I recently tried out Artemis a bit, and boy has it changed since I last used it.

Basically, I’m having trouble initializing a component after creating an entity. I’m doing this:

Archetype archetype = new ArchetypeBuilder().add(Position.class).build(world);
int entity = world.create(archetype);

At this point, I want to initialize the Position component to the initial position of the entity. However, this seems to be impossible to do cleanly.

  • ComponentMapper doesn’t work since I’m not inside a System.
  • If I use an Entity object, I can use entity.getComponent(Position.class), but that function delegates to a protected function in ComponentManager which I can’t call directly with an int entity.

Literally the only way I’ve managed to get the Position component is to use this monstrosity:

Position p = (Position) world.getComponentManager().getComponentsFor(entity, new Bag<>()).get(0);

Am I approaching this wrong? Am I supposed to do this in some other way? Am I missing something obvious?

I think you are supposed to work with Entities in Systems only.
You could cheat tho by creating a BaseSystem that leaks the needed ComponentMappers to some static class and then grab the mappers from there, but that’s far from a nice solution :stuck_out_tongue:

I do not use Mappers outside of systems, i have some initialization stuff too though:

	public static int createGroundTile(String name, Vector3 position) {

                [...]
		
		final int e = world.create();
		
		world.edit(e)
		.add(new AbsolutePosition(position.x, position.y, position.z))
		.add(new SpriteID(spriteID))
		.add(new SpriteLayer(SpriteLayer.GROUND0))
		.add(new CullDistance(Metrics.sssm));

		return e;
	}

That’s plenty fast already, rendering is way heavier than adding/initializing components like this.

Hmm, that looks a bit cleaner I guess. I just wanted that extra performance from the Archetypes… I got a response on their GitHub. Apparently you can get the injected ComponentMappers from World, and those are usable.

Oh yeah, i totally forget world.getMapper() :emo:
That was how you get the mappers without injection anyway…

When I created Artemis originally I had two goals, create a data oriented entity system (as I understood from Adam Martin) and make it sane for the programmer (and performant as well).
I always tried to leave a “backdoor” to do things easily, such as getting a component from an entity, an entity from the world, without much consequence on performance.

I don’t know Archetype but I initially assembled and initialized entities via a factory method. I left it to the programmer to create the components, and the entity, and add it to the world, because I know that’s the kind of power programmers want.

And yes, mappers are only really to be used inside systems, they’re for retrieval purposes only for the entity. If you’re using mappers outside systems then I’d like to hear about it.

[quote=“appel,post:5,topic:57764”]
archetypes are mostly used internally, to precalculate composition vs aspects. archetypes explicitly deal with newly created entities; all components are allocated but not parameterized.

[quote=“appel,post:5,topic:57764”]
in artemis-odb, you can the inject the fields of any object using:

world.inject(obj)

Most of my supporting editor/tooling stuff is usually done with custom scene2d widgets; it’s pretty useful to have access to mappers, systems and other injectables in those widgets. same goes for input processors; they usually references mappers and systems. Past couple of projects have used artemis as a generic DI framework - @Wire is pretty versatile without carrying too much overhead/configuration.

Hey, man, sorry about the late reply. I just finished my massive exam yesterday, so now I’m free to start looking into this stuff. I knew I would’ve gotten stuck messing with Artemis for a day if I dived into this discussion again. x___x

Thanks for the info everyone.

@junkrat
I’m currently looking into integrating Artemis into our threading system, allowing systems to update and run in parallel, with each system possibly running on multiple threads too (processing individual entities in parallel). I already have a fancy system for setting up dependencies between tasks, so by simply turning each system into a task it can be run in parallel. I bet you’re probably screaming right now from thinking about all the things I’m about to break with my threading, but for now I really only want to process entities within a system in parallel.

It would be cool if we could possibly work together to write some clear threading rules/documentation, AKA which functions are thread safe and which aren’t so that I can expand my threading integration. Also, so far the InvocationStrategy system is enough to provide all the features I need, except some dependencies between systems for synchronization. Still haven’t actually tested anything yet.