3d Game Programming with Java and libGDX — Hints and Tricks

Or… the journey through the x, y, and z axes through the lens of a computer screen.

TL;DR

If you want a performant game, written in Java, on the libGDX library, here are some of the handy tips and tricks that I have come across.

Whilst this is a bit of a hodge-podge of hints and tips, it is worthwhile to read through them all, even if the terms and nomenclature is not clear, it always good to have in the back of your mind that there are handy hints about a subject you are working on.

Note: this is part of a series of articles: See

Always think of performance

If there is only one thing that you do, it is this one.

Always think of performance. If you leave this too long, all of the small decisions that you have made without thinking of performance will add up, and it will be too late to fix them, and your game will run slow.

Table of contents

  1. Code Related
  2. libGDX related
  3. Model related
  4. Other considerations

Code Related

Pre-compute everything

Well, at least as much as you can, save time and CPU cycles. If you can work it out before hand, rather than on the fly, this will save cycles.

For example, if you are loading the same model, over and over again, and every time that you do, you compute the bounding box — do it once, and never again.

Don’t create new objects

Instead of creating new Objects, use the a single object within a class to be utilised. Object creation will trip you up, waste memory, and CPU cycles.

You are periodically checking your stats with aren’t you?

Watch out for floating point mathematics

Floating point in computer terms are at best an approximation, and there are discrepancies between addition and multiplication (and division and subtraction for that matter). Looking at the code below

Running the above will give you the following output:

Adding 0.0 + 1.392 = 1.392
Adding 1.392 + 1.392 = 2.784
Adding 2.784 + 1.392 = 4.1759996
Adding 4.1759996 + 1.392 = 5.568
Adding 5.568 + 1.392 = 6.96
Adding 6.96 + 1.392 = 8.352
Adding 8.352 + 1.392 = 9.744
Adding 9.744 + 1.392 = 11.136001
Adding 11.136001 + 1.392 = 12.528001
Adding 12.528001 + 1.392 = 13.920001
Adding OFFSET 10 times in a loop = 13.920001
Multiplying OFFSET by 10 = 13.92

As you can see — they are not the same, and can lead to a lot of problems — 13.920001 does not equal 13.92.

Some ways around this:

  • Choose multiply or add and use it always — multiply is faster, but beware of loops and resetting counters.
  • Round your floats to a number of decimal places (i.e. remove the least significant digits)

I chose the last option above — to 3 decimal places.

Throw some of the core Object Orientated tenets out the window

Information hiding— gone — allow public access to primitives and fields, the following is ‘old school’

However, this is much ‘better’

Why, you ask — simply because you save having a method call being pushed on to the stack — and when you are trying to hit 60fps consistenly, all of these little things will add up.

libGDX related

Always use an InputMultiplexer — you never know when (or if you will need it), but it will make it easier to always think about multiplexing input (i.e. from differents screens or UIs)

Model related

Watch for scaling and the models

Blender, by default, scales everything to metres, libGDX, by default, scales everything to centimetres.

This manifests itself, that when you load and display a model in libGDX that has been exported by blender, and converted by fbx-conv —you may not see it rendered on the screen as your camera is actually ‘inside’ the model (and back face culling is active)

Invert the textures when you fbx-conv

When running ‘fbx-conv’ always set the ‘-f’ flag when exporting from blender, or your image textures will be upside down, as an example:

fbx-conv -v -f -o G3DB medium-rhombic.fbx medium-rhombic.g3db

Multiple models/image textures

If you are using the same model, just with different textures, load up the model once, and then change the image texture on instantiation. (don’t forget about transparency in your images if you have one…

// create a new material with an image texturethis.originalMaterial = 
new Material(
TextureAttribute.createDiffuse(
new Texture("textures/texture.png")));

// you will need this line if you have any alpha
(i.e. transparency) in the image
this.originalMaterial.set(
new BlendingAttribute(
GL20.GL_SRC_ALPHA,
GL20.GL_ONE_MINUS_SRC_ALPHA));

// clear the material which was loaded with the model
this.materials.get(0).clear();
// set the material on the model
this.materials.get(0).set(originalMaterial);

Other considerations

Load time is better than wait time

People will forgive loading times as you get everything up and running, however, games that run at below 60fps as things are happening in the background will not be tolerated. Load everything up-front to make your game snappy.

Screen planning

Plan your screens up-front and have a standard naming convention. Whilst this may seem obvious, the complexity comes in when you need to add in a lot of screens over time, and how you hook them in.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store