Blog

Ten Second Sketch is coming to Android(and iOS)!

Our ludum dare entry this time around has had quite some overwhelming feedback! For this reason, we’ve decided to continue development of our game. This means that we’re bringing Ten Second Sketch to mobile devices! The game is going to be free of charge, aswell as free of adds!

Ten Second Sketch

In order to enhance the experiance for our users, we’ve taken multiple actions:

1. We’ve optimized the game rendering and collision detection.
Optimized rendering was achieved by batching all obstacles. We also added scaling of blocks, allowing us to use just one scaled block with repeating texture coordinates instead of multiple small. A huge performance boost compared to our old naive approach! On some levels we managed to cut down the amount of floats needed for our vertices from ~200k to ~5k! Adding this scaling of blocks also had a huge impact on collision detection. We’ve always been using first a broad phase where the obstacles at a nearby Z coordinate are found, and a narrow check where these objects are checked for collision. Now everytime you’re close to a wall, you’ll be checking collision against one block instead of the previous 100!

2. We’ve fixed bugs with the collision detection from our previous entry. It should, for example, no longer be possible to fall through the ground at level 8.

3. Garbage Collection removal
All unnecessary garbage collecting has been removed. This means that the game runs much more fluently on mobile devices. Pooling all obstacles before removing them from the current level was one of the major improvements that we did. We also had a lot of lazy additions of ”new Vector3″:s in our code. All of these have been replaced with static references to computation vectors.

4. Level polishing and additions.We’ve removed levels that we considered too boring, and replaced them (it) with multiple new and exciting levels! We’re still making new levels on a daily basis, and the game is going to contain some very difficult levels for the most dedicated!

5. New features!
We’ve added some new features to the game! Examples: Bouncy blocks and boost blocks! A bouncy block will cause you to bounce in the opposite direction of the one you’re heading – landing or driving on top of one will cause you to jump, rotating into it will cause you to rotate in the opposite direction for a moment. Boost blocks will cause you to travel at increased speed for a while after colliding with them (very similar to how the user controlled boost works). These two new block types allow us to create some very interesting and smooth levels – prepare to feel like a god while racing the pipe of Ten Second Sketch!

 

If you would like to look at our entry for LD27, visit Ludum Dare
If you would like to stay updated and be notified of the release of our game, please follow us on twitter: https://twitter.com/daggergamedev
Ten Second Sketch was made with the help of the amazing game framework libGDX.

Ten Second Sketch

Our second attempt on Ludum dare has just ended. The theme this time was 10 seconds. We were somewhat disappointed as we would have preferred a more original theme. While discussing the theme, we thought that there were going to be a lot of similar games and we wanted to stand out! For quite a while we struggled to come up with a unique idea fitting to this theme. We then remembered an idea we actually had talked about just the previous week.
The discussion started when we found a sketch of a game Edvard and Gustav were involved in during their bachelor's thesis. We sometimes do friendly harassing of each others and I jokingly told them that their sketch were much better looking then their final product, and that they should have made a game with those graphics instead. Then we thought about it, agreeing that it would actually be pretty cool!

We recalled that moment and decided to try it out! After our project was set up and we had a frame displaying a black sun with a long rod piercing through it, it was definite!
Last time we had a really talented artist with us, André, who unfortunately were too busy to join us this time. As none of us know any real modelling, we decided to proceed with simple quads, textures, and imagination.
My head nearly exploded trying to draw a 2D ship from that point of view.

Once again, we are impressed with what you can achieve in such a short time frame, and we are very proud to have completed yet another game.

The game can be played in the browser (Google Chrome preferred) over at http://www.dagger.se/LDAug or downloaded as a .jar file at http://www.dagger.se/ludum/ldaug.jar. If you would like to visit and rate our game over at ludum dare, here's a link to that too: http://www.ludumdare.com/compo/ludum-dare-27/?action=preview&uid=13074

We would love to hear what you think about the game. Feel free to leave a comment below!

Explosions with animated billboards

It’s been a while, but we’ve kept busy! Most of our recent work has been with the engine of our game, as well as the server. However, we recently started working on making the spells of our game look better – and this post is going to explain how we did explosions!

The Idea
So, the idea here is that we use a system very similiar to how the particles of our game work. This means that we’re batching a whole lot of quads, and rendering them each frame with just one drawcall. In order to keep the system dynamic and allow for the actual animation, we need to recalculate the vertices of the mesh each frame.

To do the animation, we provide a textureatlas containing (in our case) 8 rows and 8 columns. Each cell represents the state of the animation at a given time, and we set a variable called ”textureVal” to tell our system which cell it should use at any given time.

Below you can see what our Billboard and Billboard system classes look like:

Billboard Show

BillboardSystem Show

Rendering of the billboards
Rendering of the billboards is pretty simple. The rendering code looks like this:

Rendering code: Show

The shaders too are quite simple, and we use the very same shader for our particle system.

Vertex Shader: Show

Fragment Shader: Show

So, the approach we used was quite simple and it took less than an hour to get the system running. However, if you have any questions – don’t be afraid to ask them here or find us on #libgdx over at freenode!

Here’s a video to demonstrate the result of our implementation:

New website

The website is starting to look good enough to replace the old one. This will allow us to use much better indentation for the code we post on our blog, as well as offer us a lot of other cool features that we previously did not have.

So, I guess all that remains is to welcome you to our new home!

GPU skinned animations in libgdx

(Without using modelbatch)

We’ve been using the old libgdx 3d api for about 7 months now, in order to develop our game. We recently (last week or so) decided to make the transition to the new 3d API to keep our libgdx versions up to date with the nightlies. The transition itself was rather simple, and we’re still keeping things at a level very near what we used in the old API. For example, we’re not using the modelBatch class nor any of the shaders provided to us.

The main thing that we’ve been missing graphically has been animated 3d objects. We did have a keyframed animation system that we developed ourself to animate between two static states of an obj-model, but the downsides were just too many for us to bother adding it to the actual game.

So, we finally sat down trying to implement animations today. After a few hours of reading through the source files of modelbatch, skeletontest and defaultshader – we finally understood what was going on and could start implementing our own version.

This blogpost will go through how we handle and render our animations, and hopefully others that would like to stick to a lower level of opengl can benefit from it.

The first thing we do is ofcourse to load the file. We do this using the libgdx class AssetManager:

assets.load("data/model/charModelAnim.g3dj",Model.class);

The file can be loaded either as g3db (binary) or as g3dj (json). You can convert the most used file formats to either of these two using the fbx-converter (https://github.com/libgdx/fbx-conv), we used fbx files that our artist created for us.

When the file has been loaded, its time to create the actual objects. We create modelInstances in the constructor of our characters:

Model characterModel = assets.get("data/model/charModelAnim.g3dj");
charInstance = new ModelInstance(characterModel);
animationController = new AnimationController(charInstance);
animationController.animate(charInstance.animations.get(0).id, -1, 1f, null, 0.2f); // Starts the animaton

Now we have our animation set up, and all that remains is for the character to call:

 animationController.update(deltaTime);

during its update method.

This is all the logic that we need to do the actual updating of the animation, and it’s time to start thinking about how to render it. In order to render our animated objects, we do the following:

charShader.begin();
// Bind whatever uniforms / textures you need
for (GameCharacter ch : g.characters){
    Array<Renderable> renderables = new Array<Renderable>();
    final Pool<Renderable> pool = new Pool<Renderable>() {
        @Override
        protected Renderable newObject () {
            return new Renderable();
        }
        @Override
        public Renderable obtain () {
            Renderable renderable = super.obtain();
            renderable.lights = null;
            renderable.material = null;
            renderable.mesh = null;
            renderable.shader = null;
            return renderable;
        }
    };
    ch.charInstance.getRenderables(renderables, pool);
    Matrix4 idtMatrix = new Matrix().idt();
    float[] bones = new float[12*16];
    for (int i = 0; i < bones.length; i++)
    bones[i] = idtMatrix.val[i%16];
    for (Renderable render : renderables) {
        mvpMatrix.set(g.cam.combined);
        mvpMatrix.mul(render.worldTransform);
        charShader.setUniformMatrix("u_mvpMatrix", mvpMatrix);
        nMatrix.set(g.cam.view);
        nMatrix.mul(render.worldTransform);
        charShader.setUniformMatrix("u_modelViewMatrix", nMatrix);
        nMatrix.inv();
        nMatrix.tra();
        charShader.setUniformMatrix("u_normalMatrix", nMatrix);
        StaticVariables.tempMatrix.idt();
        for (int i = 0; i < bones.length; i++) {
            final int idx = i/16;
            bones[i] = (render.bones == null || idx >= render.bones.length || render.bones[idx] == null) ?
            idtMatrix.val[i%16] : render.bones[idx].val[i%16];
        }
        charShader.setUniformMatrix4fv("u_bones", bones, 0, bones.length);
        render.mesh.render(charShader, render.primitiveType, render.meshPartOffset, render.meshPartSize);
    }
}
charShader.end();

So basically what happends is, we loop all characters that we want to render. We create an array of renderables, aswell as a pool of renderables. These are needed in order to collect the renderables from the modelInstance (via instance.getRenderables(array, pool)). We also need to create and initiate an array of floats to represent each bone matrix. We have 12 bone matrixes, and each matrix contains 16 floats. Now, we loop all renderables that we have collected, and set the matrixes that we need as usual. We also need to loop and fill the float array with the data from the matrices, if there is such data to be found.

(Also, please note that you should not be creating new objects each rendercall, as in the code above, but instead create them once and reuse them.)

So, there’s all the code we call at the CPU in order to initiate the rendering. Now all that is left is to show our shader code! All the skinning occurs in the vertex shader, and that is why we will only share that this time (Our fragment shader can be found in the normalmap source as linked from another blogpost).

//Firstly, we need to define loads of new attributes, one for each bone.
attribute vec2 a_boneWeight0;
attribute vec2 a_boneWeight1;
....
attribute vec2 a_boneWeight11;
//We also need to take the bonematrices
uniform mat4 u_bones[12];
void main() {
    // Calculate skinning for each vertex
    mat4 skinning = mat4(0.0);
    skinning += (a_boneWeight0.y) * u_bones[int(a_boneWeight0.x)];
    skinning += (a_boneWeight1.y) * u_bones[int(a_boneWeight1.x)];
    ...
    skinning += (a_boneWeight11.y) * u_bones[int(a_boneWeight11.x)];
    //Include skinning into the modelspace position
    vec4 pos = skinning * vec4(a_position,1.0);
    // Rest of code is justlike usual
    v = vec3((u_modelViewMatrix * pos).xyz);
    vsN = normalize(vec3(u_normalMatrix * skinning * vec4(a_normal, 0.0)).xyz); //viewspaceNormal
    gl_Position = u_mvpMatrix * pos;
    v_texCoord = a_texCoord0;
}

So thats basically it, and we got away without having to rewrite our entire render engine to be able to use the new 3d API!