What is it?
Artemis is a high performance Entity System framework for games, written in Java, and is a framework to manage entities in a game world. It is inspired by
Entity Systems are the future of MMORPG articles by Adam Martin on
t-machine.org. We also borrowed ideas from Ted Brown who implemented a
simple high-performance Entity System in Processing.
Artemis library is only 26 KB in size, it has no dependencies and can be used with any game framework or library, 2D or 3D.
Disclaimer
Although Artemis is currently being used in games in development it is still considered experimental. Use in your projects at your own risk.
Support & forums
If you have any questions you can get answers on the Slick forum:
-
Slick forums
If you need help or get in contact with us, post there. If you find bugs, please report them there.
Mini guide/about
So, how does it work? While we cannot explain entity/component paradigm here (there are other better articles out there) we can explain how you use Artemis to accomplish separation of data and logic, including rendering.
The main concepts in Artemis are: Entities, Components and Systems. There are other things in there as well, but they are mainly meant to facilitate those three things and make things "go".
Entities
Entities are very raw and basic, think of them as a identifier for an entity. An instance of Entity is meant to identify that entity throughout the system. The most important aspect of Entity is the entityId, which no other living entity has in the system.
Components
Components are pure data classes, they do not have any logic in them other than that for setting/getting the data. An example component would be Position, containing only X and Y coordinate values, and an allowed set method would be setPosition(x,y).
All components extend Component, which is meant to identify the components in the framework.
Systems
These are really the most important aspect of the framework. Entity systems are meant to process certain aspects of entities. An entity aspect means that a entity possessing certain components that enable it to be processed in a certain manner but one or more systems. One system processes only one aspect.
An example aspect be Movement, which would process an entity aspect consisting of Position and Velocity. The system that would process such an aspect could be called MovementAspect and would contain the logic necessery to move entities around according to their Position and Velocity, setting and getting whatever data it requires.
Entities do not communicate between themselves, but systems can communicate with other systems. Use the SystemManager to retrieve a system within another. Systems can provide whatever API necessery for inter-system communication.
The framework bundles a few EntitySystem implementations that can be extended, depending on the usage, be sure to read the JavaDoc description on all EntitySystem implementations and be sure to understand them, because choosing the right EntitySystem can provide a significant performance boost.
Further read
Review article on PieMaster.net
Mini tutorial
Creating and running
The first thing that needs to be done is to instantiate a new World.
world = new World();
Next, you need to add your own systems to the world, and then finally initialize the world. This can be done in the initialization method for your game.
SystemManager systemManager = world.getSystemManager();
movementSystem = systemManager.setSystem(new MovementSystem());
renderSystem = systemManager.setSystem(new RenderSystem());
//add more systems as needed
systemManager.initializeAll();
Then usually the game has both update and render methods. For update you'd invoke logic specific systems, and you also need to call framework specific methods to indicate that the loop as started.
update(int delta) {
world.loopStart(); // signals loop start
world.setDelta(delta); // sets delta for systems to use
movementSystem.process();
}
render() {
renderSystem.process();
}
Assembling entities
To add entities to your world you can do something like:
Entity e = world.createEntity();
e.addComponent(new Position(200,400));
e.addComponent(new Velocity(2.4f,0.9f));
e.refresh(); // very important, see below
Entity.refresh()
It is very important to call Entity.refresh() after adding or removing components from a entity. Refresh will notify all systems of changes to this entity, and the systems will either add or remove the entity from itself if needed.
EntitySystem
A typical entity system would be something like MovementSystem.
public class MovementSystem extends EntityProcessingSystem {
private ComponentMapper velocityMapper;
private ComponentMapper positionMapper;
public MovementSystem() {
super(Transform.class, Velocity.class); // Components represent the aspect
}
@Override
public void initialize() {
// Use these to be able to retrieve components from entities fast.
velocityMapper = new ComponentMapper(Velocity.class, world.getEntityManager());
positionMapper = new ComponentMapper(Position.class, world.getEntityManager());
}
@Override
protected void process(Entity e) {
// Get the components from entity.
Position position = positionMapper.get(e);
Velocity velocity = velocityMapper.get(e);
// Calculate new position.
float newX = position.getX() + (world.getDelta()*velocity.getVelocityX());
float newY = position.getY() + (world.getDelta()*velocity.getVelocityY());
// Set the new position.
position.setPosition(newX, newY);
}
}
A good rule of thumb when deciding on a new system is to think in terms of what "it can do". E.g. a system can move entities around, a system can damage entities, a system can spawn new entities, a system can play audio.
While this does not provide a complete coverage of all the frameworks capabilities, it should, alongside the demo game, provide a sufficient understanding how to get things going. The JavaDoc does also contain more description, where description is needed, so be sure to look there as well.
Caveat
Because each system and component has it's own bit identifier, and Java's long is only 64 bit, which means there's a built-in limit of 64 to the number of systems and components. It's actually quite easy to change this to Java's BitSet which supports virtually unlimited bits, but it will require slight more nanoseconds than simple long bit calculation. We chose not to add it because we don't think there's real need for it since most games use far less distinct systems and components than 64. However, if you need it you know about this.
License
As of June 21st, 2011, the Artemis Project is now BSD licensed (Simplified BSD License).
Contact information
Framework created by Arni Arent and Tiago Costa.
You can contact us at: arniarent (at) gmail (dot) com