libgdx part 0 – Hello World

NOTE: This tutorial was written in march 2010. It is extremely outdated. Please go to the new fangled wiki at http://code.google.com/p/libgdx/wiki/TableOfContents?tm=6

Today i present you libgdx, the framework i wrote in december last year for doing all my android game development. I open sourced it today under the LGPL license. You can find it at http://code.google.com/p/libgdx/. In this article we’ll see how we can easily setup a new project (actually two) so we can prototype and work on the desktop allowing fast iterations and have the same desktop code run on any Android device.

What you need:

  • a properly setup JDK, 32-bit (no 64-bit support at the moment i’m afraid. But you can always install several JVMs alongside each other).
  • Eclipse
  • Android SDK and the Eclipse adt plugin correctly setup
  • Windows or Linux (sorry Apple people, don’t have a Mac, can’t test)

If you read this blog you have all that setup already anyways i assume :). Now there’s 3 ways to get libgdx up and running. The first one is checking out the source code, compile it and put together a proper project with the created libs. We won’t do that as compiling the whole thing for different platforms (win32, linux) is a bit of a hassle at the moment. The second way is to download the current release of libgdx from the google code site. You can find the most up to date version at http://libgdx.googlecode.com/files/gdx-0.2.zip. In there is a README file that explains you how to setup your own projects. For this post we are gonna use the 3rd way of setting up a libgdx project and that is by downloading the template “hello world” zip file from http://libgdx.googlecode.com/files/gdx-helloworld.zip.

Extract that zip file into your workspace and import the two projects contained in there. This is what you’ll see in your package explorer:

The first project we have a look at is the gdx-helloworld project. It has a couple of jars and shared libraries in the libs/ folder. Two of them are easily identifieable as libgdx jars, one containing the class files, the other containing the sources. The sources are in there so we have java docs when we write our libgdx application. The third jar called desktop-dependencies contains all the 3rd party libraries that libgdx uses on the desktop to for example decode ogg files and so on. Additionally there’s shared libraries which come for windows 32-bit and linux 32-bit and contain the native code of libgdx (to date this contains the native mp3 decoder). If you want to setup your own project you simply copy over this libs/ folder to your new project and add the contained jars to your java project. The armeabi/ folder are technically not needed in the Java project but i was to lazy to remove them 🙂

The second project is called gdx-helloworld-android. It also has a libs/ folder that contains the libgdx jar file as well as a subfolder called armeabi/ containing a shared library libgdx.so. We don’t need the desktop-dependencies.jar here as that won’t work on Android anyways.

Let’s have a look at what the HelloWorld.java file of the Java project contains:

That’s the most basic libgdx application you can write. We start of by stating that the class HelloWorld implements the interface RenderListener. We’ll get to that in a later article. Next we have a nice little main function that instantiates a JoglApplication with certain properties (title, dimensions, whether to use OpenGL ES 2.0) and register a new instance of HelloWorld with it. The following method stubs are the implementation of the RenderListener interface. To start this application we create a new run configuration. As libgdx has part of its functionality implemented in native code we have to tell the JVM where to find the shared library. For this we go to the arguments tab of the run configuration and enter “-Djava.library.path=libs/” as the VM arguments:

If we run that we get the following output:

Black is beautiful. What we just did was setting up a complete application which initiates OpenGL in the background and creates a rendering thread which invokes the RenderListener.render() method of all registered RenderListeners, in our case that’s the HelloWorld instance.

Now we want to run the same RenderListener on Android. Let’s have a look at the GDXHelloWorld.java file in the Android project:

Now that is sleek. GDXHelloWorld is derived from AndroidApplication which is analogous to JoglApplication on the desktop. Both implement the Application interface which essentially hides all the platform specifics for us. The only plattform specific thing we have to code up is the instantiation of a proper Application subclass (either JoglApplication or AndroidApplication) and register a RenderListener with it. Here we see that instead of loading any views in the onCreate() method we first call the super.onCreate() method which does nothing fance. Next we call the AndroidApplication.initialize() method which sets up all the OpenGL and input things for us, much like the constructor of the JoglApplication does. Finally we set a RenderListener, in this case a new HelloWorld instance. This is the same class we defined in our Java project. The android project thus has to reference the Java project for this to work. Now create a run configuration for this activity and try it on the emulator or device. Here’s the result:

What have we done? We setup an OpenGL ES application on Android which runs the same code as the desktop version! From now on we don’t have to touch the Android project anymore as we’ll do all our development in the Java project. Via the link between the java and the Android project the later always has an up to date version of the HelloWorld class which is used as a RenderListener. The only time we modify the Android project is when we add Assets.

A black screen is not really interesting, so let’s draw something. As you might have guessed, the RenderListener interface we implemented is called each time a new frame has to be drawn, much like the Renderer interface of the GLSurfaceView works. The RenderListener.surfaceCreated() method is called once when we first register the RenderListener. In that method we are going to put all our initialization code, like loading textures and meshes. Once everything is setup the rendering thread is repeatedly calling the RenderListener.render() method. This is were we will do all our rendering. If you write a game you can also do your game logic in there, though some advocate to do that in a seperate thread and synchronize it with the rendering thread. I honestly don’t like this approach and have used the “do everything in the rendering thread” approach in all of my games so far. Finally, when the application is closing the RenderListener.dispose() method is called giving you a chance to save any data before exit. In a later article we’ll look into the RendererListener interface in detail as well as into the ApplicationListener interface which both together manage the life cycle of a libgdx application.

To make the hello world example a little bit more interesting let’s add a triangle. For this we simply construct a Mesh as well as a MeshRenderer. A Mesh holds the geometry for a model while the MeshRenderer is responsible for making OpenGL render the Mesh. Here’s a slightly extended version of the HelloWorld class showing you how to create a simple triangle.

I won’t go into the details of the Mesh and MeshRenderer class here as this is the topic of a later article. However, it should be straight forward to figure out what we do. We create a Mesh, set it’s vertices and then create a new MeshRenderer responsible for rendering that Mesh. This happens in the HelloWorld.surfaceCreated() method which get’s called once at start up. In the HelloWorld.render() we then simply call the MeshRenderer.render() method telling it that it should draw its data as triangles. Note that we use OpenGL constants here! Libgdx is tightly integrated with OpenGL ES for better or worse. Many graphics related classes will allow you to use familiar OpenGL constants and so on. We’ll talk more about that in a later article. Here’s the awesome output of the above program:

Yay, a triangle! Now here comes the beauty of libgdx. We don’t have any extra steps to do for that to work on Android. Simply execute the Android run configuration and check the output!

Nice, i like! That’s it for now. In the coming weeks i’ll introduce all the featuers of libgdx one by one. Libgdx encapsulates all necessary things like graphics, audio, user input and file i/o in a platform agnostic way so you can develop on the desktop and deploy to the mobile device seamlessly. So there’s a lot of things to learn. In the meantime you can check out the source code and read the Java doc. Everything is documented and should allow you to get up and running.

Have fun.

14 thoughts on “libgdx part 0 – Hello World

  1. Hi Jiri,

    currently there’s no physics support what so ever. I plan on including Box2D and/or Bullet once the base functionality is done (currently the audio module and the GUI module are missing, i’m working on that).

    Neither Box2D nor Bullet support ellastic collision detection and response afaik. I could be wrong on that though.

  2. I have developed games in applets before using g.drawgraphics (thats the most complicated stuff Ive worked with). I know about threads, game loop, collision detection implementation… What I wanted to know is if libgdx is for people who already know how to make desktop games and are just running it on android with a few lines of code? I dont know how to use jogl, I was looking for a library that simplified all the opengl stuff so I could just load sprites etc. Is that what libgdx is about?

  3. libgdx is for people who know their way around OpenGL a little bit. You can get away with only using OpenGL to clear the screen and then use the SpriteBatch to render your sprites. Apart from the graphics side the rest of libgdx offers all that’s needed for game development, from audio to input to file managment and so on. Check out the rest of the tutorials to get an impression of what’s possible.

  4. Hi, Mario. First of all, you are doing a great job with this framework!
    I have little questions please:
    1- in rendering step, i’m interested just rendering when “dirty”: is that posible?
    2- I have a running thread doing the logic/control task (much like MVC pattern): is there any method to wait to the rendering thread to finish its task?
    3- How can I shutdown the rendering thread from code?
    4- And, your native libraries are compiled for ARM processors: i suppose they should run only on android devices with such a processor, or ARM processor is standard for android device manufacters?

    Thank you again, for your time, i hope i can donate profit if things goes well for me in the future Mario!

  5. Hi Cani,

    thanks for your interest. Let me try to answer your questions as good as possible.

    1) With the current architecutre i’m afraid its not possible to only render when a scene got “dirty”. I don’t plan on adding this feature i’m afraid.
    2) In a dual thread setup you will have to synchronize your two threads by standard Java means. In general you want to have a sort of choke point where the two threads synchronize with each other, e.g. the rendering thread should get new information on what to render. How to achieve this in Java with various methods is described here
    3) You can’t i’m afraid.
    4) Yes, the native libraries are compiled for ARM. However, they are also compiled for x86 processors when using a desktop operating system like Windows, Linux or Mac OS. All Android devices available on the market to date are ARM based. Once Android is available for other platforms Google will provide means to package more than just the ARM native libraries with your application. Subsequently libgdx will of course also provide multiple binaries for different platforms. This should be seamless, all you need to do is copy over the libs folder to your project.

    I’d like to point out that we have a forum now where you can also post such questions. You can find it here.

    I hope this answers your questions.

    Ciao,
    Mario

  6. I’m lovin the informal nature of this article. It’s easy to follow and isn’t cut and dry.

    And yes, I agree, black is beautiful! :p

    (disclaimer: i’m not black)

    I’ll look forward to reading the rest over winter break.

  7. Hey Mario,

    After reading through this blog entry, I took a stab at implementing this, and everything rendered nicely, except when I got to the part about rendering the triangle with MeshFloat and MeshRenderer. I tried importing other jars to no avail. I also tried looking up those classes from http://libgdx.googlecode.com/svn/api/index.html, and I don’t see it.

    Thanks anyways.

  8. Ugh, i’m really sorry Brin, i should probably but a big around those blog posts 🙁

    I’m going to prepare a couple of video tutorials in a few weeks, maybe even have a few live streams. We’ll see how much time i have left over. Hopefully that can make up for you going through the old tutorials.

  9. It was actually my fault for not reading carefully the first time around. I’m thankful you were kind enough to stick up a note that lead me to the forums. I had a chance to play with everything some more, and I really like how awesome invaders appears given the little code that was needed. Also, up-to-date javadocs is such a huge bonus on top. :^)

    Video tutorials would be awesome if you have time for it. A quick readme in the wiki would be just as good. We can read … some of us just need to reread things a couple of times before we “get” it (i.e. yours truly). Aside from being relatively more time-consuming to create, I think the more videos, tutorials, etc. you create, the more you’ll regret it when you update something in libgdx that affects those tutorials. In the long run, readme’s and code samples are the preferred choice because they’re quick and easy to update, and can be embedded within svn, whereas videos are difficult to maintain in the long run. This is just my personal opinion.

    Quick question, are there any other examples or demos besides the 4 in “svn/trunk/demos”?

    Thanks again.

    p.s. the link to the ‘developer guide’ referenced by this blog entry is broken.

  10. If it’s outdated how about you link to the version of the Hello World tutorial that isn’t outdated? Or is it outdated for no reason?

Leave a Reply

Your email address will not be published.