Posts Tagged ‘artemis’

Area triggers using Box2D, Artemis and SVG paths

Thursday, March 22nd, 2012

As we explained in previous posts, we are using Inkscape to design the levels of some of our games, in particular, our current project. In this post we want to share how we are making area triggers using Box2D sensor bodies, Artemis and SVG paths.

What is an area trigger

When we say area trigger we mean something that should be triggered, an event for example, when an entity/game object enters the area, to perform custom logic, for example, ending the game or showing a message. Some game engines provides this kind of stuff, for example Unity3d with its Collider class and different events like OnTriggerEnter.

Building an area trigger in Inkscape

Basically, we use SVG paths with custom XML data to define the area trigger to later parse it by the game level loader to create the corresponding game entities. The following screen shot shows an example of an area defined using Inkscape:

Right now, we are exporting two values with the SVG path, the event we want to fire identified by the XML attribute named eventId, and extra data for that event identified by the XML attribute eventData. For example, for our current game we use the eventId showTutorial with a text we want to share with the player on eventData attribute like "Welcome to the training grounds". The following example shows the XML data added to the SVG path:

  

The exported data may depend on your framework or game, so you should export whatever data you need instead.

Defining the area trigger inside the game

Inside the game, we have to define a entity/game object for the area trigger. In the case of our current game, that entity is composed by a Box2D sensor body with a shape built using the SVG path and a Script with logic to perform when the main character collides it.

We use sensor bodies because they are mainly used to detect collisions but not to react to them by changing their angular and linear velocities. As we explained in a previous post, we are using our custom builders to help when building Box2D bodies and fixtures. Our current body declaration looks like this:

  
Body body = bodyBuilder //
	.fixture(bodyBuilder.fixtureDefBuilder() //
		.polygonShape(vertices) // the vertices from the SVG path
		.categoryBits(Collisions.Triggers) // the collision category of this body
		.maskBits(Collisions.MainCharacter) // the collision mask
		.sensor() //
	) //
	.position(0f, 0f) //
	.type(BodyType.StaticBody) //
	.angle(0f) //
	.userData(entity) //
	.build();

The previous code depends on specific stuff of the current game but it could be modified to be reused in other projects.

As we explained in another previous post, we are using a basic scripting framework over Artemis. Our current script to detect the collision looks like this:

 
public static class TriggerWhenShipOverScript extends ScriptJavaImpl {
	
	private final String eventId;
	private final String eventData;
	
	EventManager eventManager;

	public TriggerWhenShipOverScript(String eventId, String eventData) {
		this.eventId = eventId;
		this.eventData = eventData;
	}

	@Override
	public void update(World world, Entity e) {
		PhysicsComponent physicsComponent = Components.getPhysicsComponent(e);
		Contacts contacts = physicsComponent.getContact();
		
		if (contacts.isInContact()) {
			eventManager.submit(eventId, eventData);
			e.delete();
		}
	}
}

For the current game, we are testing this stuff for a way to communicate with the player by showing messages from time to time, for example, in a basic tutorial implementation. The next video shows an example of that working inside the game:

Conclusion

The idea of the post is to share a common technique of triggering events when a game object enters an area, which is not framework dependent. So you could use the same technique using your own framework instead Box2D and Artemis, a custom level file format instead SVG and the editor of your choice instead Inkscape.

References

VN:F [1.9.22_1171]
Rating: 4.3/5 (4 votes cast)

How we use Box2D with Artemis

Thursday, February 2nd, 2012

As you may know from our previous posts or from your personal knowledge (obviously), Box2D is a 2D physics engine and Artemis is an Entity System Framework. Box2D is used to add physics behavior to games however it could be used only to detect collisions if you want (that means no dynamic behavior). In this post, we want to share a bit how we are using both frameworks together.

Introduction

The main idea is to react to physics events, like two bodies colliding, to perform some game logic. For example, whenever the main character ship touches an asteroid, it explodes.

When you use Artemis, the game logic is done in an Artemis System or a Script (custom), if you use our customization. The ideal situation would be if you could check in your game logic which entities are in contact or not. In order to make that work, you have to find a way to link a Box2D contact with an Artemis Entity and vice versa.

Our solution

The first thing we do is, to each Artemis Entity we want to have a physics behavior, we add a PhysicsComponent the Box2D Body of the Entity and a Contacts instance where all the Box2D contacts for that Body are stored. Also, in order to get the Entity from the Body, we set the its userData pointing to the Entity.

The Contacts concept gives us useful methods to get information about contacts and the API looks like this:

    getContactsCount() : int - returns the contacts quantity
    getContact(index: int) : Contact - returns the contact information

And our Contact concept API, returned by the Contacts getContact() method, looks like this:

    getMyFixture() : Fixture - returns the fixture in contact of the Contacts owner Entity.
    getOtherFixture() : Fixture - returns the fixture of the other Entity.
    getNormal() : Vector2 - returns the normal of the contact.

(note: we decided to make a deep copy of the contacts information since it is recommended in the Box2D manual if you use a ContactsListener)

Then, we have a ContactsListener (named PhysicsListener) which, whenever a contact is reported (begin or end), it gets the bodies from the contact and gets the entities from each body userData and then adds or removes the contact data to/from each Entity's PhysicsComponent using its Contacts instance.

(note: we decided to use a custom ContactListener since it is recommended in the Box2D manual)

Finally, in each Artemis System or Script, we use the Entity's PhysicsComponent to get the contacts data and we proceed to do the logic we want, for example, destroy the character or enable some special ability, etc.

Here is an example of how we use it inside a Script from our Leave me Alone game:

public void update(World world, Entity e) {
	PhysicsComponent physicsComponent = Components.getPhysicsComponent(e);
	
	Contacts contacts = physicsComponent.getContact();
	
	if (!contacts.isInContact())
		return;
	
	boolean shouldExplode = false;
	
	for (int i = 0; i < contacts.getContactCount(); i++) {
		
		Contact contact = contacts.getContact(i);
		Entity otherEntity = (Entity) contact.getOtherFixture().getBody().getUserData();
		
		GroupComponent groupComponent = Components.getGroupComponent(otherEntity);
		
		if (groupComponent == null)
			continue;
		
		if (groupComponent.group.equals(Groups.EnemyCharacter)) {
			shouldExplode= true;
			break;
		}
		
	}
	
	if (shouldExplode)
		eventManager.dispatch(Events.MainExploded, e);
}

If you use Box2D and you are starting to use Artemis or vice versa, hope this post could help you. Otherwise, I hope you like it.

Also, if you use Artemis with Box2D in another way, would be great to have your point of view.

Thanks.

VN:F [1.9.22_1171]
Rating: 3.5/5 (11 votes cast)

Reusing Artemis entities by enabling, disabling and storing them

Tuesday, January 3rd, 2012

As we mentioned on a previous post, we were having some performance issues in Vampire Runner and we were trying different approaches to improve its performance.

Introduction

One limitation of Android when making games is you have to avoid generating garbage whenever you can since the garbage collection would generate pauses on your games and that leads to a bad user experience. Then, we should try to reuse already created object instead of creating new ones.

In Vampire Runner, one problem we were having was that we were creating a lot of entities at a specific moment of the game, when we detected a new obstacle should be created, and that was making some pauses on the Android version.

As we use Artemis, we should try to reuse some entities when we can. For example, if we make a shooting game (like the Jetpac prototype I made) it seems a good idea to reuse bullets since their life cycle is really short. Ziggy made two blog posts about this topic some weeks ago here and here, however we followed a slightly different approach and we will explain it in this post.

Storing entities to reuse them

We created a concept named Store (similar to LibGDX Pool class) which let us easily store objects, in this case entities of one kind (for example bullets).

	free(T t) // returns an entity to the Store to be reused later

	get() : t // returns an entity from the Store, it reuses an object from the free 
			collection if there is one or creates a new object otherwise.

The idea is to, for example, instead of creating a new bullet when a weapon is fired, calling store.get() and set the component values as they should be, and when the bullet collides with something call the store.free(e) instead of deleting the entity, so we can reuse it later.

This is a generic approach and we can use different stores to reuse different kind of entities but it has a big problem, those entities keep being in Artemis world, that means they keep being processed (collisions, render, etc). A basic solution to this problem was adding a new state to the entity, and we explain that in the following section.

Enabling and disabling Artemis entities

Artemis supports reuse of entities by internally caching created entities inside the World class, however their state (which components their have) is not easily reused, and that was one of the big problems when creating a new entity, we wanted to reuse their state.

Our current solution to the problem was adding a new state to the entities, if they are enabled or not. Being enabled means the entity is processed by all interested EntitySystems, being disabled means the entity is still in the Artemis world but it is not processed by any system.

So, in our customization of Artemis we added three new methods to Entity to be called whenever you want to enable or disable an entity:

	disable() : disables an entity to avoid it to be processed on EntitySystems

	enable() : enables again an entity to let it be processed on EntitySystems

	isEnabled() :  returns true if the entity is enabled, false otherwise.

Then, we added new methods to EntitySystem API to let each EntitySystem to be aware an entity of interest was enabled or disabled:

	disabled(Entity e) : called whenever an entity of this EntitySystem was disabled

	enabled(Entity e) : called whenever an entity of this EntitySystem was disabled

In our case, we are using them to enable and disable Box2D bodies in our PhysicsSystem, and also to remove them from our render layers in our RenderSystem.

As an example, we have a nice video of Vampire Runner we made by changing the zoom of the camera to see the behind the scenes:

As you can see, when entities like wall, fire and Christmas stuff are behind the main character, they disappear. That is because they are disabled and moved again to their stores so they stop being processed by Artemis, in particular, stop being rendered.

Conclusion

By combining both solutions, we have an easy way to reuse created entities of one kind, like our obstacles tiles in Vampire Runner, while at the same time we can disable them when they are on a store to avoid them being processed.

In case of Vampire Runner, this solution improved Vampire Runner performance since we now pre create a lot of entities we need during the game and then disable them and enable them only when needed, in this way, we could avoid creating a lot of entities in one update after the game was started.

This is a first approach solution to the problem and seems good for our current games but it may not fit other type of games or bigger games, we don't know that yet.

If you use Artemis and you had this problem too, hope this blog post is helpful to you.

VN:F [1.9.22_1171]
Rating: 3.0/5 (4 votes cast)

Basic frustum culling to avoid rendering entities outside screen

Monday, January 2nd, 2012

As we were having some performance issues with Vampire Runner and we didn't have a clear idea of what was happening, we started trying some improvement techniques. The first one we implemented was a basic frustum culling technique to avoid trying to render objects outside of the screen.

Basic implementation

First, we created an Artemis component named FrustumCullingComponent with a Rectangle representing the bounds of that entity to easily detect if the entity is inside the screen or not. For now, as it is a basic implementation, the rectangle was only modified when the entity was created. So, for example, if we know an entity was able to rotate during the game, then we create a bigger bounding box using box diagonal.

Then, we added a method to our custom 2d Camera implementation to get the camera frustum (by making the corresponding transformations).

Finally, we modified our Artemis render system to check before rendering if an entity has or not a FrustumCullingComponent, if it hasn't one, then we perform the render logic as we always did. If it has one, then we check if the bounds of that entity overlaps with the camera frustum, if it does, then we render as we always did, if it doesn't, then we avoid rendering that entity.

Here is an example of the bounds and the frustum of the camera:

In the image, the element (a) and (b) are rendered because their bounds overlaps with the camera frustum. The element (c) is not rendered because its bounds are totally outside the camera frustum.

Conclusion

For Vampire Runner, we didn't notice the difference of having this technique enabled or not since the game always render fast (on our devices) and we had no metrics of the render process time. However, as it was really easy to implement this basic version of the technique, we believe it should help to maintain render performance, and we can reuse the logic for all of our games.

As always, hope you like it.

VN:F [1.9.22_1171]
Rating: 4.5/5 (2 votes cast)

Scripting with Artemis Entity System Framework

Sunday, November 13th, 2011

Artemis is a component based entity system framework made in Java by Arni Arent (appel) and Tiago Costa (spiegel).

The core of Artemis is small and it is based on four main concepts. The Component, where all information about an Entity is stored. The Entity, which represents a game object. The EntitySystem, where custom logic, for entities with one or more component, is processed. And finally the World, where Entities and EntitySystems live. The idea is to grow over those concepts by making your own Components and EntitySystems.

The problem

There are some cases where it depends a lot how are you using Artemis, to feel it is helping you or not. For example, when you want an Entity to have some custom behavior on a specific level you could follow the next approach.

First, create an SpecificBehaviorForLevelComponent to declare that an Entity with that component will have that custom behavior and then create the SpecificBehaviorForLevelSystem which performs the logic.

The problem with this approach is that you will have an empty Component used only as a mark to let the EntitySystem work over it. Also, you will have an EntitySystem that will perform logic only in a specific moment of the game and then it will be useless.

If you have to create more than just one custom behavior, then you are a bit doomed and you will hate Artemis. However, it is not Artemis, or any component based entity framework, fault.

Script Framework, a possible solution

To simplify working with cases like the one mentioned before, we created a scripting framework over Artemis, composed by three main concepts: the Script, the ScriptComponent and the ScriptSystem.

Script

This is an interface which provides the following three methods:

  • init(world, entity) : called once when the entity enters the world.
  • update(world, entity) : called in each world update
  • dispose(world, entity) : called once when the entity leaves the world.

It should be implemented and added to the ScriptComponent of an Entity in order to perform the behavior.

ScriptComponent

This is an Artemis Component which contains a collection of Scripts and it is used by the ScriptSystem in order to know which Scripts to process on each Entity.

ScriptSystem

This is an Artemis EntitySystem responsible of calling, for each Entity, the init/update/dispose methods of each Script declared in the ScriptComponent of that Entity.

For the previous example, where we wanted a specific behavior for an entity in one level, we could create a SpecificBehaviorForLevelScript and, when loading that level, add that script to the ScriptComponent. So, instead creating Components and EntitySystems, we can create only Scripts.

Pros

  • Clear and simple API.
  • Easy to add/remove a Script vs add/remove a System.
  • Scripts are easily reusable (when you want two or more entities with a custom behavior).
  • Logic localized in one place.
  • Allow different implementations of the Script interface, for example, a Groovy implementation.

Cons

  • Not good for global stuff like rendering, an EntitySystem keeps being better for those cases.
  • Hard to know the right balance between which code should be on Scripts and which one on Systems.

Conclusion

The Script Framework is some point in the middle between Entities with no logic at all and Entities with all the logic. It should be used with care, learning to balance which code should be on Scripts and which code on Systems is not easy.

Artemis is only a small core, a foundation of classes to work with. The real power comes from the custom Components and Systems you create over it. For example, in our case we created several Systems that we reuse between games, some of them are the RenderSystem responsible of rendering the entities with the RenderComponent using libGDX and the PhysicsSystem responsible of processing the Box2d world.

References

There are a lot of resources about components based entity systems, however the best/correct solution between all these references is not so clear.

Hope you like it.

VN:F [1.9.22_1171]
Rating: 4.2/5 (5 votes cast)