Splodey!

Mark Neil was one of the first people to use libgdx and its box2D wrapper earlier this year. He developed an original Android game called Splodey and is now preparing to release it to the market. Go checkout his site at http://www.pointergames.com/ to find out more about Mark’s company and games.

  • Share/Bookmark
 

libgdx release 0.6

It’s been a while since the last libgdx release. Today we celebrate the release of libgdx version 0.6. Lots of bug fixing, especially with respect to the box2d wrapper which seems to be quite robust now.

One new feature is a simple to use AudioRecorder which you can instantiate via the Audio interface.

Another new feature are some changes in the Box2D API. Fear, i only added new stuff and didn’t change old stuff. The most notable additions here are the Box2DDebugRenderer, which allows you to easily visualize your box2d world as well as the implementation of the Body.getTransform() method which is needed if you want to get the position and orientation of a fixture attached to a body. Check out the Box2DDebugRenderer on how that can be used for this purpose. Of course the Transform class is also properly implemented. The rest of the changes are mainly bug fixes.

What’s maybe interesting for many of you out there are the extensive examples for box2d with libgdx that you can now find in the test project. I talked about them in the last post, so i won’t do it again here.

What’s next? libgdx 0.7 will get multi-touch support (which frankly is nothing anyone sane would use at this point in time given the lack of proper multi-touch devices apart from the Samsung Galaxy S and DroidX). Xavier already started on TMX tile map support, i have yet to look into that. Finally the MD2 loader will get included in stock libgdx.

  • Share/Bookmark
 

Libgdx Box2D testbed

I found an hour today to continue working on porting over the original Box2D testbed tests. The ported testbed is very similar to the original one in it’s design. There’s a Box2DTest abstract class which handles things like creating all the rendering resources, mouse input and so on. All tests derive from this class and most often only implement the createWorld() method that populates the world with objects.

The class TestCollection ties all tests together and allows cycling through the tests by pressing the space bar.

Both things are pretty unexciting, porting the tests is also not really that impressive but rather tedious. The last piece in the puzzle is a renderer which can render the physics world. For this i wrote the Box2DDebugRenderer class, located in the main API so you can also use it when trying to debug your games. It uses an ImmediateModeRenderer internally so don’t expect the performance to be stellar.

Here’s a video of the tests ported so far. I could iron out a bug in the PrismaticJoint and a few other things along the way and all seems to work well. Richard of Rokon fame reported a bug in the default CollisionListener which i couldn’t reproduce. The CollisionFilters test also proves that my implementation of that is indeed correct. I could imagine that not being careful with your shorts (16-bit integer you pervert…) might be a problem in Java, so watch out for that.

Video footage taken on my trusty netbook with software OpenGL so the performance sucks a little :)

Libgdx 0.6 will be released on sunday with all those nice fixes. I hope to be able to port the rest of the tests over (won’t port raycasting and presolve tests yet though, that has to wait).

  • Share/Bookmark
 

I signed a contract today with Handmark, partner of a lot of OEMs and carriers, mainly in the U.S. from what i could gather. They will likely bundle it in some form with future Android devices, or publish it on their own market targeted at Sprint customers. No real details where given. In any case, any publicity is good publicity.

I know i’ve been kinda slow with additions to libgdx lately. Rest assured, i still work on it, albeit i only iron out some bugs and slowly but steadily increase the test coverage of Box2D. The next release (0.6) is scheduled for next sunday, it adds some small but important modifications to the Box2D wrapper along with a debug renderer for testing (which should only be used on the desktop! it’s slow on devices! TAKE NOTE!).

The future of libgdx looks as follows: i’ll add the mod player capability available in Andengine (yes, i too can “steal” code :) ), add support for the TMX tile map format, clean up some dirty interfaces/classes (camera classes, i’m looking at you!), include the MD2 loader i wrote back in January for the tutorial (with fixes from Moritz, thanks!) and try my hands on a wrapper for Bullet. I’ll also stop being lazy and add a multitouch handler for Android so the pointer parameter of the InputListener methods are of actual use. Don’t expect any miracles on devices such as the N1 or Droid though, their touch screens still suck!

All this (expect the bullet wrapper) should be done by the end of august if all goes well and my work load at my day job decreases a little. I’d love to get some other people on the board which could help me out, but i guess the libgdx community is more or less non existant at this point :)

  • Share/Bookmark
 

Nicolas send me a his benchmark suite for libgdx, AndEngine and Rokon. Each engine renders a scene of 32×32 pixel sprites in a grid, a total of 336 sprites, filling up nearly all of the screen. I performed the tests on 2 devices, a Hero with 1.5 and a Nexus One with 2.2

Rokon didn’t start on neither my Hero nor my Nexus one.

AndEngine:
- Hero: ~17fps
- Nexus One: ~41fps

Libgdx:
- Hero: ~51fps
- Nexus One: ~51fps

Yes, you read that right, the libgdx version, which uses the SpriteBatch class for rendering, performs equally well on both devices. Now, in my opinion the test is not entirely fair as AndEngine has to perform a lot of other stuff besides the rendering. However, the main reason why it sucks so much on the Hero is that each sprite rendering issues a lot of glTranslate/glPushMatrix/glPopMatrix commands as well as rendering each quad seperately (the VBO containing the vertices is bound only once though).

You can find the source for the benchmark here.
An apk can be found here.

The more i see these semi-scene graph engines like Rokon, AndEngine or Cocos2D on Android the more i believe that they are not the way to go. You can’t please every genre with these engines and if you have to get better performance you’ll have to dive deep into the source of these engines and modify it. Simple puzzle games or your average Snake clone are a no brainer with those engines. However, something like Replica Island is pretty much out of reach when using these libs at the moment.

I still believe that especially beginners in Android game programming should start out with AndEngine & co. Their nice APIs are much easier to use than the down to the metal approach of libgdx (altough it has nice helper classes in the math and graphics package which should ease your programming pain a lot).

  • Share/Bookmark
 

Box2D bug hunting in libgdx

It’s been a while since i’ve coded anything significant for libgdx. Well, today i found an hour to start actually working on the Box2D test bed port. It went pretty smooth so far. I found a couple of bugs in the JNI Wrapper (nothing concerning the motor or joint stuff though), implemented a base class for all tests, much like in the original testbed and included a Box2DDebugRenderer which you can also use in your projects. The renderer is nearly done, i only need to implement two functions (rendering the joints and contacts) which are probably about 15 lines of code. I’ll add them as soon as i start implementing the joint related tests. Note: the debug renderer is not intended to be used for production. You also shouldn’t expect decent performance from it on an Android device. It’s a quick and dirty way to render the world and by no means optimized (uses IntermediateModeRenderer which itself is a slow bitch but is incredibly easy to use).

In any case, the thing is not finished yet but porting a test takes around 2 minutes so i should have all of the tests done by tomorrow. If there are any bugs in the joint wrappers i’ll find them :) . Note that so far only the shared library for Windows is up to date, if you want to try the fixed wrapper out on your device you’ll have to compile the native parts yourself in the mean time. Once i have ported all the tests and fixed any potential bug i’ll release libgdx 0.6 and all should be well.

Side note: i’ll tweak the performance of the World.getFixtures(), World.getBodies() and World.getContacts() methods a little. As it is the first two return a collection so this will change to a List in the near future as it avoids instantiating iterators. The later will have some internal tuning. I also plan on finally getting rid of the java.util.HashMap used to track fixtures and bodies and replace it with a Trove like primitive type map implementation.

Since i haven’t posted code in a while, here’s the libgdx port of the pyramid example from the original Box2D testbed:

package com.badlogic.gdx.tests.box2d;
 
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
 
public class Pyramid extends Box2DTest
{
        @Override
        protected void createWorld(World world) 
        {       
                {
                        BodyDef bd = new BodyDef( );
                        Body ground = world.createBody(bd);
 
                        PolygonShape shape = new PolygonShape( );
                        shape.setAsEdge( new Vector2( -40, 0), new Vector2( 40, 0 ) );
                        ground.createFixture( shape, 0.0f );
                        shape.dispose();
                }
 
                {
                        float a = 0.5f;
                        PolygonShape shape = new PolygonShape();
                        shape.setAsBox( a, a );
 
                        Vector2 x = new Vector2( -7.0f, 0.75f );
                        Vector2 y = new Vector2();
                        Vector2 deltaX = new Vector2( 0.5625f, 1.25f );
                        Vector2 deltaY = new Vector2( 1.125f, 0.0f );
 
                        for( int i = 0; i < 20; i++ )
                        {
                                y.set( x );
 
                                for( int j = i; j < 20; j++ )
                                {
                                        BodyDef bd = new BodyDef( );
                                        bd.type = BodyType.DynamicBody;
                                        bd.position.set( y );
                                        Body body = world.createBody( bd );
                                        body.createFixture( shape, 5.0f );
 
                                        y.add( deltaY );
                                }
 
                                x.add( deltaX );
                        }
 
                }
        }
}

And that’s the original:

class Pyramid : public Test
{
public:
        enum
        {
                e_count = 20,
        };
 
        Pyramid()
        {
                {
                        b2BodyDef bd;
                        b2Body* ground = m_world->CreateBody(&bd);
 
                        b2PolygonShape shape;
                        shape.SetAsEdge(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
                        ground->CreateFixture(&shape, 0.0f);
                }
 
                {
                        float32 a = 0.5f;
                        b2PolygonShape shape;
                        shape.SetAsBox(a, a);
 
                        b2Vec2 x(-7.0f, 0.75f);
                        b2Vec2 y;
                        b2Vec2 deltaX(0.5625f, 1.25f);
                        b2Vec2 deltaY(1.125f, 0.0f);
 
                        for (int32 i = 0; i < e_count; ++i)
                        {
                                y = x;
 
                                for (int32 j = i; j < e_count; ++j)
                                {
                                        b2BodyDef bd;
                                        bd.type = b2_dynamicBody;
                                        bd.position = y;
                                        b2Body* body = m_world->CreateBody(&bd);
                                        body->CreateFixture(&shape, 5.0f);
 
                                        y += deltaY;
                                }
 
                                x += deltaX;
                        }
                }
        }

Ok, that’s it for now. Feels good to be back :)

  • Share/Bookmark
 

Android FloatMath revisited

Today i implemented a class called FastMath which offers the same static methods as the Android FloatMath class. Behind the scenes there’s a singleton instance which can be user defined that actually implements the math functions such as cosine, sine or sqrt. All the math code in libgdx now uses that static class to delegate those calculations to platform dependent optimal versions, like FloatMath on Android.

I have two implementations for the FastMath class, a standard implementatin using the Math class from the standard library as well as an Android specific implementation that uses the FloatMath class internally. When calling a method of the FastMath class it gets delegated to the singleton instance which means we have one additional call to a static method, another call to the singleton method, e.g. AndroidFastMath.cos(), and finally the call to the actual implementation, e.g. Math.cos() or FloatMath.cos(). That’s a total of 3 calls to get the cosine of an angle or a square root.

A request for enhancement over on the issue tracker requested this so we get maximum performance on all platforms. I had the suspicion that this wouldn’t work out from the beginning due to the function call overhead. The design is as slick as possible so i believe that the three method calls are the minimum.

Now here’s some hard data. I tested the methods Math.cos, Math.sqrt, FloatMath.cos, FloatMath.sqrt and FastMath.cos/FastMath.sqrt (which internally use FloatMath) on my HTC Hero (no FPU, Android 1.5) and my Nexus One (FPU, Android 2.2). Each function was executed a million times with a variable argument. Here’s the results for the Hero:


FloatMath.cos(): 10.42688 secs
FloatMath.sqrt(): 2.8764648 secs
Math.cos():9.445556641 secs
Math.sqrt(): 3.755310058 secs
FastMath.cos(): 13.469482422 secs
FastMath.sqrt(): 5.175018311 secs

Wow, now that is silly. Granted this is only a single run and FloatMath.cos() might still outperform Math.cos() when averaged over multiple runs. However, the big loser is my FastMath class which uses FloatMath internally. The function call overhead is immense so nothing is gained here really. How’s the situation on the Nexus One?


FloatMath.cos(): 0.70428467 secs
FloatMath.sqrt(): 0.23391724 secs
Math.cos(): 0.45666504 secs
Math.sqrt(): 0.133239742 secs
FastMath.cos(): 0.910583498 secs
FastMath.sqrt(): 0.48376465 secs

First we see the FPU and the JIT doing there magic. I don’t think that the JIT actually plays a big role here, it’s probably mainly the FPU which is speeding up things significantly compared to the Hero. Math beats the crap out of FloatMath here. This is similar to the old x86/87 Wisdom that using doubles actually increases performance as most FPU registers are > 32bits anyways. You can therefor eliminate a costly conversion to and from float. On the Hero that effect is non-existant as it has no FPU and everything is done in software, so double is slower than floats. FastMath still stinks. The relative timings to FloatMath are nearly the same as on the Hero which suggests that the function call overhead is still there. The JIT in Dalvik does no inlining yet so you still have to pay the price for excessive function calls.

So what does this mean? FloatMath works a tiny bit better on older devices with no FPU as expected. On never devices with FPU it’s actually slower it seems due to load conversions to and from the FPU registers for 32-bit floats. Function calls are still evil and nasty even with the JIT. Finally, i’ll revert the changes to libgdx and use the standard library Math function instead. The performance impact on old devices is neglectable.

Note: Yes, those are only micro benchmarks and there’s a lot that’s ignored. However, for my purposes they are more than precise enough.

WTF: Google you scare me. 20 minutes after i posted this i get the following. I never felt so relevant…

  • Share/Bookmark
 

Today i stumbled across Ohloh, an open source project directory. I have no idea how many people actively use it, but it has some nice features that i miss on Google Code, namely project statistics. These range from simple LOC counts to more elaborate metrics like percentage of different languages used.

The most fun part of Ohloh are the widgets. There’s a couple of different widgets that allow you to display the number of users, project statistics etc. And then there is this widget.

What can i say, appearantly libgdx is worth around 800k$. Of course this is an estimate based on LOCs, average salary (55K, man i wished i’d get that at my day job :( ) and so on. It’s really silly. Additionally it also includes the LOCs of the 3rd party sources that are in the SVN repository. Libgdx itself now has around 40K lines of code (Java + C), so it’s actually only worth 600k. Anyone want to invest?

Here’s some more stats:

Pretty sweet. You can find libgdx’s Ohloh page here.

Btw, check out the brand new summary page over at Google Code!

  • Share/Bookmark
 

This is an issue i post-poned for a long time. What’s the problem? Libgdx uses various 3rd party libraries to implement part of its functionality.

  • Tremor for fixed point ogg vorbis decoding
  • libmpg123 for mp3 decoding
  • The FFT related classes from the Minim library for Processing
  • Kissfft for a native FFT implementation
  • Box2D, for 2D physics

All this libraries are licensed under specific terms. Tremor has its own kind of license which is not a problem for libgdx. It basically states that you can do with the code whatever you want as long as you hand out copyright notices with source and binary distributions. Libmpg123 is LGPL licensed, so that’s kind of a problem. The Minim FFT classes are also LGPL licensed, however i got written permission to use them in libgdx as i do (that is, not fully implementing LGPL by statically linking to the files). Kissfft is BSD licensed, which is just awesome. Finally, Box2D comes with its own license terms which basically state that you can do whatever you want as long as you give credit.

So the only problem currently is libmpg123. I will get in contact with the author in the next few days, i’m sure he’ll agree that the minor violation of the LGPL (not linking dynamically to libmpg123) is ok. If not, well, then just use ogg :)

That’s how you properly stand on the shoulders of giants! Open source is awesome, so keep up the spirit and don’t violate licenses.

  • Share/Bookmark
 

libgdx changes its license

Seeing how LGPL is not all that suitable for Android many people suggested i should change the license of libgdx. Well, so i did. By popular request libgdx is now under the Apache License 2.0. What does this mean to you? We’ll i’m not a laywer so take all this with a grain of salt.

The license basically states you can do with the source whatever you want, copy it, modify it, include it in open and closed source projects without getting infected by the license itself. All that is asked is that you

  • include the license file in your project
  • retain all copyright notices of my (modified) source files
  • if you chose to contribute your contribution will the Apache 2.0 licensed to

Given that this is an open source effort i urge you to contribute any generally valuable changes back to the project. Note that there is no requirement to do so. It would just be fair given that i put a lot of effort into this.

Have fun with your new commercially useable open source library :)

  • Share/Bookmark