How we used Entity Component System (ECS) approach at Gemserk - 2/2

So, after our first attempt on using ECS, when we started to develop mobile games and moved to the LibGDX framework, we decided to abandon our ComponentsEngine and start over.

We were still reading about ECS while we were creating our set of tools and code over LibGDX. At some point in time, some of the Java community developers started Artemis, a lightweight ECS, and we decided to give it a try.

Artemis

This is a simplified core architecture diagram:

Note: we used a modified version of Artemis with some additions like enable/disable an Entity.

In this pure approach, Entities and Components are just data, and they are related by identifiers, like these tables in a relational database:

Where we have two entities, both with a PositionComponent and only one of them with MovementComponent.

An example of this components in code:

public class PositionComponent : Component {
    public float x, y;
}

public class MovementComponent: Component {
    public float speed;
}

EntitySystems perform the game logic. They normally work on a subset of Components from an Entity but they could need it in order to enable/disable/destroy it (if it is part of its logic).

An example of a System is LimitLinearVelocitySystem, used in multiple of our games to limit the physics velocity of an Entity with PhysicsComponent and LimitVelocityLimitComponent:

public void process(Entity e) {
    PhysicsComponent physicsComponent = 
                     Components.getPhysicsComponent(e);
    Body body = physicsComponent.getPhysics().getBody();

    LinearVelocityLimitComponent limitComponent = 
             e.getComponent(LinearVelocityLimitComponent.class);
    Vector2 linearVelocity = body.getLinearVelocity();

    float speed = linearVelocity.len();
    float maxSpeed = limitComponent.getLimit();

    if (speed > maxSpeed) {
        float factor = maxSpeed / speed;
        linearVelocity.mul(factor);
        body.setLinearVelocity(linearVelocity);
    }
}

There are some extra classes like the TagManager which allows assigning a unique string identifier to an Entity in order to find it, and the GroupManager which allows adding entities to groups identified by a name, which is more like how tags are used everywhere else.

Even though it could look similar to our ComponentsEngine where the Properties in that engine correspond to the Components in this one, and Components to Systems, there is an important difference: Systems are not part of an Entity and work horizontally over all entities with specific Components (data). So, in this approach, changing only data from entities indeed change their behaviour in the game, so it is really data driven.

Since Entities and Components are just data, their instances in memory are easier to reuse. An Entity is just an id, so it is obvious. A Component is a set of data that doesn't care too much which Entity it belongs to. So, after the Entity doesn't need it anymore, it could be reused elsewhere, improving a lot memory usage and garbage collection.

Artemis, and other pure ECS implementations, are really lightweight and performant frameworks. The real power comes from the Systems and Components built over them. In our case, we created a lot of Systems that we started to reuse between games, from SuperFlyingThing to VampireRunner and even in Clash of the Olympians.

Scripting

One of the most interesting ones is the Scripting framework we created over Artemis. It was really useful and gave us a lot of power to overcome some of the limitations we were facing with the pure approach when we need to create a specific logic for a specific moment during the game and (probably) never again and we didn't want a System for that.

They work similar to Unity MonoBehaviours and our logic Components from ComponentsEngine, and they also belong to the Entity lifecycle. One difference, however, is that they try to avoid storing data in their instances as much as possible and instead try to store and read data from Components, like Systems do.

Here is an example Script from one of our games:

public class MovementScript extends ScriptJavaImpl {
	
  @Override
  public void update(World world, Entity e) {

    MovementComponent movementComponent = Components.getMovementComponent(e);
    SpatialComponent spatialComponent = Components.getSpatialComponent(e);
    ControllerComponent controllerComponent = Components.getControllerComponent(e);
		
    Controller controller = controllerComponent.controller;
    Movement movement = movementComponent.getMovement();
    Spatial spatial = spatialComponent.getSpatial();
		
    float rotationAngle = controllerComponent.rotationSpeed * GlobalTime.getDelta();
		
    Vector2 linearVelocity = movement.getLinearVelocity();
		
    if (controller.left) {
        spatial.setAngle(spatial.getAngle() + rotationAngle);
        linearVelocity.rotate(rotationAngle);
    } else if (controller.right) {
        spatial.setAngle(spatial.getAngle() - rotationAngle);
        linearVelocity.rotate(-rotationAngle);
    }
		
  }
	
}

Note: GlobalTime.getDelta() is similar to Unity's Time API.

One problem about the Scripting framework is that it is not always clear when some logic should be in a Script or a System, and that made reusability a bit harder. In the case of the example above, it is obvious it should be moved to a System.

Templates

Another useful thing we did over Artemis was using templates to build entities in a specific way, similar to what we had in ComponentsEngine.

We used also a concept of Parameters in templates in order to customize parts of them. Similar to ComponentsEngine, templates could apply other templates and different templates could be applied to the same Entity.

Here is an example of an Entity template:

public void apply(Entity entity) {

    String id = parameters.get("id");
    String targetPortalId = parameters.get("targetPortalId");
    String spriteId = parameters.get("sprite", "PortalSprite");
    Spatial spatial = parameters.get("spatial");
    Script script = parameters.get("script", new PortalScript());

    Sprite sprite = resourceManager.getResourceValue(spriteId);

    entity.addComponent(new TagComponent(id));
    entity.addComponent(new SpriteComponent(sprite, Colors.darkBlue));
    entity.addComponent(new Components.PortalComponent(targetPortalId, spatial.getAngle()));
    entity.addComponent(new RenderableComponent(-5));
    entity.addComponent(new SpatialComponent(spatial));
    entity.addComponent(new ScriptComponent(script));

    Body body = bodyBuilder //
            .fixture(bodyBuilder.fixtureDefBuilder() //
                    .circleShape(spatial.getWidth() * 0.35f) //
                    .categoryBits(CategoryBits.ObstacleCategoryBits) //
                    .maskBits((short) (CategoryBits.AllCategoryBits & ~CategoryBits.ObstacleCategoryBits)) //
                    .sensor()) //
            .position(spatial.getX(), spatial.getY()) //
            .mass(1f) //
            .type(BodyType.StaticBody) //
            .userData(entity) //
            .build();

    entity.addComponent(new PhysicsComponent(new PhysicsImpl(body)));

}

That template configures a Portal entity in SuperFlyingThing which teleports the main ship from one place to another. Click here for the list of templates used in that game.

Interacting with other systems

Sometimes you already have a solution for something, like the physics engine, and you want to integrate it with the ECS. The way we found was to create a way to synchronize data from that system to the ECS and vice versa, sometimes having to replicate a bit of data in order to have it easier for the game to use it.

Finally

Even though we had to do some modifications and we know it could still be improved, we loved using a pure ECS in the way we did.

It was used to build different kind of games/prototypes and even a full game like the Clash of the Olympians for mobile devices, and it worked pretty well.

What about now?

Right now we are not using any of this in Unity. However we never lost interest nor feith in ECS, and there are starting to appear new solutions over Unity in the last years that caught our attention. Entitas is one of them. The Unity team is working towards this path too as shown in this video. Someone who din't want to wait started implementing that solution in his own way. We've also watched some Unite and GDC talks about using this approach in big games and some of them even have a Scripting layer too, which is awesome since, in some way, it validates we weren't so wrong ;).

I am exited to try ECS approach again in the near future. I believe it could be a really good foundation for multiplayer games and that is something I'm really interested in doing at some point in my life.

Thanks for reading.

References

 

 

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

How we used Entity Component System (ECS) approach at Gemserk - 1/2

When we started Gemserk eight years ago, we didn't know which was the best way to make games. So before starting, we did some research. After reading some articles and presentations we were really interested in trying an Entity Component System (ECS) approach for our games. However, since we didn't find a clear guide or implementation at that point we had to create our own solution while exploring and understanding it. We named our engine ComponentsEngine.

Components Engine

The following image shows a simplified core architecture diagram:

Note: part of the design was inspired by a Flash ECS engine named PushButtonEngine.

An Entity is just a holder of state and logic. In an ECS, anything can be an Entity, from an enemy ship to the concept of a player or even a file path to a level definition. It depends a lot on the game you are making and how you want to structure it.

A Property is part of the state of an Entity, like the health or the position in the world, anything that means something for the state of the game. It can be accessed and modified from outside.

Components perform logic updating one or more Properties to change the Entity state. A component could for example change the position of an Entity given a speed and a moving direction.

They normally communicate with each other either by modifying common Properties (when on the same Entity) or by sending and receiving Messages through a MessageDispatcher (when on the same or on different Entities). They just have to register a method to handle a message. In some way, this is pretty similar to using SendMessage() method in Unity and having the proper methods in the MonoBehaviours that need to react to those messages.

EntityTemplates are an easy way to define and build specific game entities, they just add Properties and Components (and more stuff) to make an Entity behave in one way or another.

For example, a ShipTemplate could add position, velocity and health properties and some components to perform movement and to process damage from bullet hits:

public void build() {
        // ... more stuff 
        property("position", new Vector2f(0, 0));
        property("direction", new Vector2f(1, 0));

        property("speed", 5.0f);

        property("currentHealth", 100.0f);
        property("maxHealth", 100.0f);

        component(new MovementComponent());
        component(new HealthComponent());
}

An example of the MovementComponent:

public class MovementComponent() {

   @EntityProperty
   Vector2f position;

   @EntityProperty
   Vector2f direction;

   @EntityProperty
   Float speed;

   @Handles
   public void update(Message message) {
      Property<Float> dt = message.getProperty("deltaTime");
      position += direction * speed * dt.get();
   }

}

In some way, EntityTemplates are similar to Unity Prefabs or Unreal Engine Blueprints, represeting in some way a (not pure) Prototype pattern.

Some interesting stuff of our engine:

  • Since templates are applied to Entities, we can apply multiple templates to the same one. In this way, we could have common templates to add generic features like motion for example. So we could do something like OrcTemplate.apply(e) to add the orc properties and components and then MovableTemplate.apply(e), so now we have an Orc that moves.
  • Templates can apply other templates inside them. So we could do the same as before but inside OrcTemplate, we could apply MovableTemplate there. Or even use this to create specific templates, like OrcBossTemplate which is an Orc with a special ability.
  • Entities have also tags which are defined when applying a template too and are used to quickly identify entities of interest. For example, if we want to identify all bullets in the game, we could add the tag "Bullet" during the Entity creation and then, when processing a special power, we get all the bullets in the scene and make them explode. Note: in some ECS a "flag" component is used for this purpose.
  • The Property abstraction is really powerful, it can be implemented in any way, for example, an expression property like "my current health is my speed * 2". We used that while prototyping.

Some bad stuff:

  • Execution speed wasn't good, we had a lot of layers in the middle, a lot of reflection, send and receive messages (even for the update method), a lot of boxing and unboxing, etc. It worked ok in desktop but wasn't a viable solution for mobile devices.
  • The logic started to be distributed all around and it wasn't easy to reuse, and we started to have tons of special cases, when we couldn't reuse something we simply copy-pasted and changed it.
  • There was a lot of code in the Components to get/set properties instead of just doing the important logic.
  • Indirection in Properties code was powerful but we end up with stuff like this (and we didn't like it since it was too much code overhead):
e.getProperty("key").value = e.getProperty("key").value + 1.
  • We didn't manage to have a good data driven approach which is one of the best points of ECS. In order to have different behaviours we were forced to add both properties, components and even tags instead of just changing data.

Note: Some of these points can be improved but we never worked on that.

Even though we don't think the achitecture is bad, it guided us to do stuff in a way we didn't like it and didn't scale. We feel that Unity does the same thing with its GameObjects and MonoBehaviours, all the examples in their documentation go in that direction.

That was our first try to the ECS approach. In case you are interested, ComponentsEngine and all the games we did with it are on Github and even though they are probably not compiling, they could be used as reference.

This post will continue with how we later transitioned to use a more pure approach with Artemis, when we were more dedicated to mobile games.

References

Evolve your hierarchy - Classic article about Entity Component System.

PushButtonEngine - Flash Entity Component System we used as reference when developing our ComponentsEngine.

Game architecture is different - A quick transformation from normal game architecture to ECS.

Slick2D - The game library we were using during ComponentsEngine development.

 

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

A Simple Selection History Window For Unity

This is a small blog post about a Unity editor window we made at work to simplify our lives when using Unity.

In Unity, when you select a reference to an asset, it is focused in the Project window, losing the current selection and probably the folder you were working on. Since there is no navigation history, most of the time having to search the previous selection is a pain in the ass.

As we were doing some stuff today at work, we were inspired (after two million times we lost our selection) so I decided to do a simple Editor Window to store and show a history of selected objects. It took me like 30 minutes to make it (plus one more hour at home).

Here are the results:

In case you are interested in using and/or improving it, here is the github project:

https://github.com/acoppes/unity-history-window

As always, hope you like it.

Guardar

Guardar

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

The story of the non deterministic Replay

This is the story of how I discovered my simplified replay system wasn’t so deterministic as I believed because I had an ugly bug, but read the post if you want to know where exactly.

While integrating the lockstep engine on the game I am working on, I decided to do something to save and load replays to be able to easily reproduce some bugs I was experimenting. After I had that done and working, it was pretty awesome to see I can replay the same game multiple times (food for another blog post by the way), however, I thought it could be fun and easy to play them faster, why not.

Since I have a fixed time step logic, it should should be pretty straightforward, simply use a multiplied time and then the fixed timestep logic would do all the work and the game logic shouldn't notice the change. I decided to give it a try and it worked…. almost, when playing the replays at higher speeds I noticed some visual differences but I wasn’t totally sure (it could be interpolation code).

To verify, I went back to the test project, where I had the moving box, and test it there, but I needed some way to be sure. Since I have already a way to calculate checksums of the game state, I used that to verify the game states when playing replays at different speeds (from 2x to 16x).

It failed, even though it only failed to validate some frames, following frames were not necessarily invalid (this is something important to consider).

invalid-state Image 1: It shows one of the best tools in the world to check game states when replaying a game.

So, I was right, I saw some differences, I could be sure that something was happening. The thing was, with only the checksums I couldn't know what the real difference was. Next step, making something to detect it.

In order to do that, I had to change to start saving (at least for debug) the game state, not only the checksum, and to check differences between stored game states in the replay and the current game state (when replaying the game) when checksum validation fails. It worked too, now I have the exact place where the differences are.

invalidstate_realdiff

Image 2: It shows why serializing all the game state in one string is the best thing to do in your life.

After testing it a bit, I noticed another curious thing, the game validation wasn’t always failing given the same replay and the same speed. That gave me a hint that the problem was probably not related with the game code itself (the moving box).

So, if I played the replay at 1x, it was validated properly. If I played the replay at 8x, it failed, most of the time, but not always. So, it seems there is something related with speed I don’t understand yet.

I decided to test the same replay but with Unity timescale modified, my first test was using 1x for replay but 5x for the timescale, validation failed, then the opposite, 10x for replay but 0.1x for timescale, and it worked well. So the problem seems to be related with my accumulator logic inside the fixed timestep logic?

Some test cycles later, it turns out that, it was indeed a bug in one of the core classes of the engine!

The problem was on my class LockstepFixedUpdate, the first version was overriding the Update() method and performing lockstep logic, it worked ok if only at most one fixed update is processed, but in the case a big delta time arrives, it only process lockstep logic once for the first fixed update and never again.

That means that, in case replay commands were to be processed in frame 3, we are in frame 1 and a big dt of 10 frames arrives, then lockstep logic checks only in frame one and never again until all 10 frames were processed. This bug even bypass the lockstep!

Since I made a test to replicate the bug, it was really easy to fix it, I changed to process the lockstep logic with each fixed step updates and it works fine now, I have high speed replays!! YEAH!!

Conclusion

In the process of finding this bug I started to expand the engine support and create better tools, this is really important if I want to build something solid over it.

The only way to detect issues as soon as possible is to iterate over the engine as soon as possible and to do that, use cases are needed and games provide the best use cases. In my case, I am using not only the game I am trying to make but also other similar games as references when deciding what I want and how I want to test it, for example, having replays, being able to play the replay at different speeds, being able to save the replays, etc. Also, being able to replicate a bug in a small test case where you can iterate quickly to fix it is super useful.

Detecting (and having) problems like this in a small and simple game gives the idea of the complexity of a medium to big game, all the variables and the difficulties, it is not something to underestimate, so when developers say they couldn't add multiplayer features to their game because it was really hard to do it, it is not a lie.

I love all of this stuff, even though I understand it is not an easy path.

To complete this post, here is a video showing a prototype of how I load and play a replay which was created by playing with two players in LAN, one was my computer and the other was my phone:

The quote of the day is 'Fail as much as possible, as soon as possible to avoid failing when it is too late'.

Hope you enjoyed the journey.

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

Lockstep multiplayer first steps

In this Gamasutra article, Tundra developers explain their approach to minimize problems when developing a lockstep multiplayer platform used for their game Rapture - World Conquest. Based on that, my first approach was to create and understand a deterministic lockstep logic without even considering networking yet, to focus on one problem at a time.

My objective is to have a reproducible game that given the start state and all the players actions during time, the game can be played again and the final state will be the same.

Lockstep logic

The first step was start by creating a logic to encapsulate the fixed game state for physics and game logic, and a lockstep to perform player actions. As I started without considering networking yet, all the player actions are directly enqueued locally by the user input or by a saved replay.

A lockstep logic means that there are some conditions that, if not met, the game should pause the simulation and wait for them. In the case of multiplayer games this is when the game have to wait for other players actions that didn't arrive in time (and where the waiting for other players dialog is shown in some games).

My code looks something like this pseudo code:

update(dt) {
    if (lockstepLogic.IsLockstepTurn()) {
        if (!lockstepLogic.IsReady())
            return;
        lockstepLogic.Process();
    }
    // normal accumulator logic for the fixed gamestep
}

Since I create all player actions locally, the lockstep never happens right now but it is a good practice to simulate and test it anyways.

Testing it

My first prototype using this logic is a box that moves over the screen. When the right mouse button is pressed, the game enqueues a player action to move the box to the specified position, then when the lockstep logic is processed the box receives the command and start moving to that position.

Interpolation

The moving logic was pretty simple, based on start and destination positions and a speed, the box moves itself to the destination in a straight line. Since that logic is performed in each fixed gamestep, the player see the box jumping between positions, it works but it doesn't look so good. To improve that and make the movement smoother I created a simple interpolation code.

Interpolation depends a lot on what you are trying to interpolate, in some cases could be a simple as the code I used there but there are other cases like the bouncing ball which need more data to create a better interpolation.

Note: adding interpolation means we have now a delay of one fixed gamestep between the box position being rendered and the real position in the game since we are using previous and current positions info for the interpolation.

My first replays

By recording all the player actions with the fixed gamestep frame they were executed, I created a basic way to replay the "game" by just reseting the game state to the initial state and start enqueing all the recorded actions in each corresponding frame.

Here is a video of the progress so far:

Yeah, I know, it's not a great thing, but at least I am starting to understand some of the challenges of making multiplayer games.

Validating simulation

To validate the game is always performing the same simulation given the same input, I added a checksum calculation based on the game state (for now just the moving box state) which is saved from time to time to use later as validation when simulating the game again. The idea was to start defining an API to get the important game state to consider when validating the simulation, and also to start testing game state validation. The code looks like this:

update(frame) {
    if (IsChecksumFrame(frame)) {
        if (recording) {
            checksumRecorder.RecordState(frame, CalculateChecksum());
        } else {
            if (!checksumValidator.IsValid(frame, 
                   checksumRecorder.SavedChecksums, CalculateChecksum())) {
               throw Exception("current game state is not valid!");
            }
        }
    }
}

In my first tests I wasn't reseting the game to the initial state properly so my game was producing different checksums when reproducing the saved player actions, checksums validation started to work after that was fixed.

How am I calculating the Checksum? Right now I am not sure exactly what algorithm to use nor which game state should I consider for the checksum, so what I did was to encapsulate that in some interfaces and implemented a basic way to get both. For the checksum I am using a simple MD5 over a string, and for the game state, well..., a string with all important values concatenated (the moving box position, destination, if it is moving or not, etc).

string CalculateChecksum() {
    string gameStateValue = game.GetGameState();
    return MD5.CalculateHash(gameStateValue);
}

string GetGameState() {
    string gameState = "";
    foreach (object in gameObjects)
        gameState += object.GetGameState();
    return gameState;
}

For a future implementation what I know is that the game state should be composed with important values that can affect the simulation, so I shouldn't care about about audiovisual stuff like particles, effects and sounds.

Also, the game state concept could be used to reset to the initial game state or even for saved game states (to easily replicate some bug for example), and finally, it could be used to synchronize and validate state if for some reason I end up using a client/server architecture.

Next frontier: Determinism?

For now I didn't explore determinism realm because the solution really depends on the game logic but at the same time I must have it clear before starting the game code. One of the next steps is probably start testing with fixed point math, not sure yet, the idea is try to follow an approach similar to the gamasutra article's of reducing non determinism problem to the minimum before going multiplayer.

If you want to take a look all the code used for this blog post, here is the link.

Other links

Example of a dynamic lockstep implementation for Unity

Lockstep Framework for Unity

Reddit post about that Lockstep Framework

Another framework named lockstep.io

Developing your own Replay System

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

LWJGL on Maven central

Hi we are happy to announce that LWJGL is available in Maven central. We worked hard with the @LWJGL people to make this possible.

Why was it important to get LWJGL into central?

Well, one of the biggest pains when using maven is having your dependencies available from central, if they are, you just need to add a little snippet of XML and you are done, if they aren't, then you need to install them manually to your local repo or to a private maven repo.
This is a problem in itself but this also means that projects that depend on something that isn't available in central, can't get into central themselves, making the work needed to use it grow exponentially.

Previous work

In order to get LWJGL into central we had to work first with @Endolf to get JInput into central so a huge thanks to him as well.

Future plans

Now that we got LWJGL into maven central, we can start thinking about trying to convince the authors of other useful libs that use LWJGL like Slick2D, libGDX, nifty-gui, etc to make their libs also available on central (of course we would love to help make this a reality as well).

If you use LWJGL with maven, we would love to hear from you and feel free to ask us anything.

More information:

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

Second attempt at Highscores for games

Some time ago we started a web application on github named datastore-server which allows us to store data for our games in a remote server hosted on Google App Engine. Since the first data we needed to store was game scores, and we required more specific queries for them, datastore-server end up being a high scores server, at least for now.

We made an introduction of some of the requirements we wanted for the scores server in a previous post, we made some modifications to the basic concepts.

Profile

First of all, we added a new structure which identifies the player and has the following fields:

Profile {
    privateKey : String - a unique private key owned by the player on the client application, used to submit scores
    publicKey : String - a unique public key used to identify scores
    name : String - the player name
    guest : Boolean - if the profile is guest or not
    }

Score

Score structure has been modified to have a profile reference, and also some extra data required for scores filtering improvement (filter by date range):

Score {
    .... (previous data)
    profilePublicKey : String - a reference to the profile owner of the score 
    year : Integer - the year the score was submitted (calculated in the server)
    month : Integer - the month of the year the score was submitted (calculated in the server)
    week : Integer - the week of the year the score was submitted (calculated in the server)
    day : Integer - the day of the year the score was submitted (calculated in the server)
    }

The server now provides the following features:

  • create guest and non-guest profiles for score submission
  • submit a score for a game given a profile
  • request scores given a criteria

Creating and updating profiles

To create profiles datastore-server provides a query named /newProfile with two parameters:

  • name : String - represents the name of the profile
  • guest : Boolean - if the profile is guest or not

The query returns the profile structure as JSON so that the client can save the private and public keys that are generated on the server.

We also provide a way to change a guest profile name and to make it be non-guest using the /updateProfile query:

  • privateKey : String - identifies the profile
  • name : String - the new name we want for the profile

Submitting a new score

To submit a new score we now need a guest or non-guest profile, it still uses the same query /submit with the same parameters plus the profile privateKey.

Requesting scores

To ask for the scores of a game we have the /scores query with the addition now of two new parameters:

  • distincts : Boolean - if scores should be filtered to return only one score per player (optional, true by default)
  • range : enum { day, week, month, all } - filter best scores by today, this week or this month respectively (optional, all by default)

So, for example, if you want the 50 best scores of the week for a game, you will query /scores?gameKey=something&limit=50&range=week.

Datastore Java client

Finally, to communicate in an easy way with datastore-server we created a Java library named datastore, also on github, which abstracts all communication stuff using apache http-client and also provide classes for score and profile concepts.

If you want to see high scores in action, you could play Face Hunt on PC here or on Android here, also you could take a look at the source code here.

Both projects datastore and datastore-server will probably change in order to incorporate other data storage beside scores.

Hope you like it.

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

Getdown

Getdown is a deployment library like Java Web Start, which provides also an integrated update process for your game. It was started to replace Java Web Start based on the premise that using Java Web Start has a lot of downsides. Getdown is mainly designed to launch games in the desktop like Java Web Start does, aditionally, it creates an installation folder structure and a launch icon on your desktop if you want.

We've talked about it a bit on our deployment ways blog post, but now we are making a deeper article based on the experience from testing it a bit with one of our games.

Getdown library is used as a game's launcher, which updates your game by downloading all required specified resources before the game starts.

You could use the getdown applet to perform all download and installation process from a web browser or you could create a platform specific installer and, after the game's launcher is installed as a desktop application, derive to it the rest of the process.

It uses a text file named getdown.txt to configure all your application needed resources, natives, custom jvm parameters, etc, and a digest.txt file to check integrity of all downloaded resources before launching the game. If you deploy it as the getdown applet, then you need to sign the digest.txt file with the same certificate used to sign the getdown.jar in order to run the applet with privileges. Here is the getdown.txt of Puzzle Pirates as an example.

Pros

  • It uses a single file to configure the application in a similar fashion Java Web Start does with the JNLP file, with some extra options. This is good because it is independent from the deployment option used, you can use the installer or the browser applet and use the same configuration file.
  • Provides a way to specify platform specific resources to be downloaded only if you run the game on that platform.
  • The loading screen is customizable like the LWJGL Applet Loader. Java Web Start provides a way to customize loading screen but you need at least Java update 18 (haven't tried it yet).
  • It validates all dependencies using the signed digest file. This is very interesting because you only need to sign one file with all the resources digests, without having to sign each file.
  • It provides a way to update your game by downloading a patch and applying it in the client machine. It requires you work with versions to use that feature (docs about versions are not ready yet).
  • Open source project with good documentation.
  • It is being used by professional games.

Cons

  • It only uses RSA for the certificate private key, so if you already own another type of private key it will not work.
  • Doesn't handle pack200-gzip encoding and stuff. It doesn't even have a way to force to download a .pack.gz either, like the LWJGL Applet Loader does.
  • It is very slow for checking files to download info, like the LWJGL Applet Loader it is not using concurrent HTTP requests for that. Java Web Start and New Generation Plug-in Applets does and it starts faster.

Note: we don't know exactly how it is doing all the cache stuff, from the wiki page it seems like it doesn't use Java Web Start cache, but from the practice it seems it is using it. It seems to be a bug, for that reason we didn't want to comment the cache stuff in the pros/cons section.

The Getdown developers have a lot of other useful libraries for Games development, take a look at them at Three Rings code page. Some games using Getdown are Pets Vs. Monsters from Sweet Robot, Puzzle Pirates, Bang! Howdy, Spiral Knights from Three Rings and Tribal Trouble 2 from Oddlabs.

We have one game deployed using getdown to test it, however if you accepted our certificate before, it will ask to accept again as it is using a new one because the second cons we mentioned before. If you want to test it, click here.

Conclusion

The user experience when playing a game deployed using Getdown with a customized loading screen is really professional and it feels like you are playing a non Java Game (hate to say that, but we can't avoid bad Java preconceptions).

References

UPDATE: added a new entry in the pros section about an update game feature by applying a patch

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

LWJGL Applet Loader

In a previous post we talked about Java Games deployment options, in this post we want to talk about one custom solution provided by the LWJGL: the LWJGL Applet Loader.

The LWJGL Applet Loader is an Applet which performs a lot of common deployment tasks:

  • It shows a nice and customizable loading screen when deployment is being processed, with detailed messages for each task: downloading file.jar, extracting file.jar.gz, etc.
  • It downloads all required dependencies. If they are compressed using gzip, LZMA or Pack200, it extracts them.
  • It has a cache for all your dependencies so if one dependency is not modified on the server, then it is not downloaded again.
  • It configures the Java library path to load all your native dependencies.
  • Finally, it runs your game's applet.

A feature in mind when developing the LWJGL Applet Loader is that it should start as fast as possible, for that, the jar of the Applet Loader should be really small. The idea is to speed up all the Java loading screen so it can show quickly your custom loading screen.

It provides a lot of parameters in order to let you customize deployment stuff, like which natives dependencies you need for a specific platform, the logo and progress bar, etc. Full documentation of the parameters is on the API docs and you also have a great tutorial at LWJGL Wiki.

This is how it looks when loading an Applet using the LWJGL Applet Loader with the default loading screen:

note: Even without customization, it looks much nicer than Java default loading screen.

Pros

  • It lets you customize loading screen, and create Applet using natives support in an easy way.
  • It starts fast. This avoids some browser freeze bug when starting a Java Applet, like Firefox on Linux platforms.
  • It handles different compression options like gzip and LZMA, it also handles Pack200 jars.
  • It works on Mac OS, that is a big difference versus running New Generation Plug-In Java Applets, because they are disabled on Mac OS.
  • It is open source and the guys maintaining it are always open to receive patches and improvement ideas.

Cons

  • Pack200 and compression stuff is not done automatically, you have to specify exactly which file you want to download (example: you have to specify that you want to download somedependency.jar.pack.gz instead of having the Applet Loader to detect automatically which version to download by receiving the content encoding from the server).
  • Assumes you need native dependencies, so you need to fill some Applet parameters even if you don't need them. (we want to add an RFE for that)
  • It doesn't use the same cache other Java Applets or Java Web Start use. That means you have to download twice one Applet distributed using LWJGL Applet loader and Java Web Start, and it will cost you double space.

To see LWJGL Applet Loader working you can try one of our games here (warning: link could be broken in the future) or you can try a working and stable version of a game using LWJGL Applet Loader here, its name is Minecraft, don't know if you know about it.

In one of the next posts we want to talk in detail about another deployment option we mentioned before, now that we have some experience using it: getdown.

References

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

Games as Applets 3

Following our Games as Applets series, we want to talk about the Wordrpess Page Template we are using in order to deploy our games as Java Applets inside the Blog.

WordPress Custom Fields

When creating a new blog post or page, the creator can add metadata using WordPress Custom Fields, to be processed later by the PHP templates associated. In our case, we are using the following custom fields:

  • applet_height - height of the applet.
  • applet_width - width of the applet.
  • applet_screenshot - URL to a screenshot of the game
  • jnlp_url - URL to the JNLP for launching the game.

WordPress Page Templates

After adding metadata to our posts or pages, we need to make a WordPress Page Template in order to process it. In our case, we created a PHP template for our games deployed as Java Applets using the structure explained in our last post about Games as Applets. Our games template looks like this file.

Note: I didn't want to put all the PHP file code directly in the post because it is too large.

This is how we get the post metadata:

<?php 
	$jnlp_href = get_post_meta($post->ID, "jnlp_url", true);
	$applet_width = get_post_meta($post->ID, "applet_width", true); 
	$applet_height = get_post_meta($post->ID, "applet_height", true);  
	$applet_screenshot = get_post_meta($post->ID, "applet_screenshot", true);  
?>

And this is how we pass the values to the javascript:

<?php echo '

' ?>

Once the page template is created, if we want to add a new page for a game, we only have to select it from the templates list and voilá.

Conclusion

Using WordPress Page Templates and Custom Fields, we can reduce the information of the game's page to game's related information only, and move all common logic and information between game pages to the page template.

This is how it looks to edit a game page:
Game Page being Edited

Note: there is no applet tag or javascript in the page.

Also, if we modify the page template, we have all game pages updated, that could be really useful if you need to fix a bug or make an improvement to the page but could be a problem in case we introduce a new bug.

One problem not resolved yet is if you want to change the WordPress Theme, you will have to migrate the page template. I don't know exactly if you can create a page template theme independent.

References

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