How to instantiate artemis-odb entities with components

Some time ago I played around with the Artemis framework. Artemis is an ECS, short for Entity-Component System. It’s a system in which you favor composition over inheritance. The components are data containers tied to a very light-weight entity and the game logic goes into the systems. That’s a very brief overview of what ECS is and does. Artemis is a well known one for Java and it was easy to use. Now coming back to it after a few years, things have changed. There’s a few spin-offs, among which artemis-odb.

Artemis-odb seemed the most interesting and I dove right in. And I instantiated entities and set up systems without issue. But what I couldn’t find was how to attach components to an entity without being in a system. The documentation is rather unclear about this and kept telling me to put component creation in a system, while I didn’t want to do that. Turns out it’s very easy to do, just not documented very well:

public class Health extends Component {
public int current;
public int maximum;
}

You just use world.getComponentMapper(Class) to retrieve the mapper:

final int playerId = world.create();
final ComponentMapper<Health> healthComponentMapper = world.getMapper(Health.class);
final Health health = healthComponentMapper.create(playerId);
health.maximum = HEALTH;
health.current = HEALTH;

It’s that easy!

LibGDX’s Scene2D and TiledMap

Posting a short tutorial because I had some trouble finding the right resources for this and I hope that my post will help others should they come across the same difficulties.

I wanted to use LibGDX’s Scene2D API with a TiledMap. Before I used Tiled I just had a simple image as a “map” and that worked to figure out how to move the camera and basic collision detection (based on other actors in the stage), but it is rather lengthy  and a hassle to maintain/extend.

How to use Scene2D with TiledMap

tiledMap = new TmxMapLoader().load("maps/island.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(tiledMap, 1);

First we load the TiledMap into our program and instantiate our renderer.

mapRenderer.setView((OrthographicCamera) stage.getCamera());

We then bind set the view of the TiledMap to the stage’s camera. This is one thing I forgot and I saw nothing (aside from my debugging bounding boxes).

mapRenderer.render();
stage.act();
stage.draw();

To conclude with drawing the map and the stage. The order is important, unless you want to only see your map…

Of course, this is only rendering, so let me move on to:

Collision Detection

Before I added a TiledMap, my collision detection was just my game looping through the actors and if it had a bounding box overlap, it would detect a collision. Combining this method with the use of an objectlayer in Tiled which has rectangles defining bounding boxes for solid things resulted in the following code:

public boolean collision(Actor movingObject) {
Rectangle rectangleMovingObject = new Rectangle(movingObject.getX(), movingObject.getY(), movingObject.getWidth(), movingObject.getHeight());
for (Actor actor : world.getChildren()) {
if (actor == movingObject) {
continue;
}
if (actor instanceof Image) {
continue;
}
Rectangle rectangle = new Rectangle(actor.getX(), actor.getY(), actor.getWidth(), actor.getHeight());
if (Intersector.overlaps(rectangle, rectangleMovingObject)) {
return true;
}
}

MapObjects layerObjects = layer.getObjects();
for (RectangleMapObject rectangleObject : layerObjects.getByType(RectangleMapObject.class)) {

Rectangle rectangle = rectangleObject.getRectangle();
if (Intersector.overlaps(rectangle, new Rectangle(movingObject.getX(), movingObject.getY(),16,16))) {
Log.d(rectangle + " " + movingObject.getX() + " " + movingObject.getY());
return true;
}
}

return false;
}

As you can see, this code constantly asks the layer for its objects. I’m leaving it in this quick and dirty way because my game only has one map (and one other actor) as of yet, but you should clean that code up if you plan on using it.

Conclusion

As said, a simple tutorial. Probably a bit unnecessary, but I wanted to see it spelled out this clearly so that I won’t waste another hour or three on this.

Resources used

  • libgdx version 0.9.9
  • Tiled version 0.9.1

I wrote a Google+ Library

Because of a project, I have been trying out several Google+ Libraries. The following libraries were the ones I tried:

The first being made by Google and the second by… Not Google.

I cannot say I was satisfied with any of those two. The first one required what seemed like a thousand dependencies while the second one refused to work due to a JSON exception that seemed to have no documentation on-line. So, I decided I’d do myself a favor and make something that works the way I want it to work: with as few dependencies as possible and very easy to use.

I used three dependencies:

I picked these three (well, two actually, commons-codec was required by scribe) because they are easy in use and do not require other dependencies.

And this is the result: My very own Google+ library

I designed it with a few guidelines in mind:

 1. Easy to get it working

GooglePlus gPlus = new GooglePlus(apiKey, secret);
 Desktop.getDesktop().browse(new URI(gPlus.getAuthorizationUrl()));
 gPlus.verifyUser(new Scanner(System.in).next()); 

Three lines and we’re connected to the G+ api.

 2. Cope with calls that weren’t predefined

 private static final String apiUrl = "https://www.googleapis.com/plus/v1/";

public Response getResponse(String apiCall) {
 OAuthRequest request = new OAuthRequest(Verb.GET, apiUrl + apiCall);
 oAuthService.signRequest(accessToken, request);
 Response response = request.send();
 return response;
}

The library provides predefined calls to the api, such as “findUser(String query)”. Normally the inner workings would be shielded from external use, but if you need to make your own calls to G+, you can call the above method in net.mymilkedeek.social.gplus.core.Manager with your custom api call.

This will come in handy if Google updates its G+ api and this library doesn’t get updated. No need to wait, just put in the new api calls and process the Json response.

3. Easy to expand

This is awesomely achieved. To add the functionality for Comments I needed to:

  1. Create a Comment class (with fields)
  2. Create CommentManager (extends Manager<Comment>)
  3. Create CommentJsonParser (implement JsonParser<Comment>)
  4. Parse the Json to the Comment object
  5. Write one line functions in the Manager

The to-do’s

  • Add optional parameters.
  • Write more comments.
  • Better exception handling.

Download it, browse the source code, don’t download it. Do with it as you please. As long as you report bugs/notify me of things that could have been better.

  Some Example

import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Scanner;

import net.mymilkedeek.social.gplus.GooglePlus;
import net.mymilkedeek.social.gplus.activity.Activity;
import net.mymilkedeek.social.gplus.activity.ActivityManager;
import net.mymilkedeek.social.gplus.comment.Comment;
import net.mymilkedeek.social.gplus.comment.CommentManager;
import net.mymilkedeek.social.gplus.person.Person;
import net.mymilkedeek.social.gplus.person.PersonManager;

import org.json.JSONException;

public class Main {

private static final String apiKey = &quot;XXX&quot;;
private static final String secret = &quot;XXX&quot;;

 public static void main(String[] args) throws JSONException, IOException,
 URISyntaxException {
 GooglePlus gPlus = new GooglePlus(apiKey, secret);
 Desktop.getDesktop().browse(new URI(gPlus.getAuthorizationUrl()));
 gPlus.verifyUser(new Scanner(System.in).next());

 ActivityManager activityManager = gPlus.getActivityManager();
 List&lt;Activity&gt; activities = activityManager
.getActivitiesFromUser(&quot;111486046861792612952&quot;); // that's me!

 for (Activity a : activities) {
 System.out.println(a.getId());
 PersonManager personManager = gPlus.getPersonManager();
 List&lt;Person&gt; persons = personManager.findByActivityId(a.getId(),
 PersonManager.PLUSONERS);

 for (Person p : persons) {
 System.out.println(p);
 }

 persons = personManager.findByActivityId(a.getId(),
 PersonManager.RESHARERS);

 for (Person p : persons) {
 System.out.println(p);
 }
 }
 }
}

This piece of code gets all of my activities (or posts) and then gets all the users who +1’d my post or shared it. Easy peasy.