November 16, 2015

Another Indie Game Post Mortem

As Biodrone Battle had been published on Steam in July, it is time to look back with this post-mortem.

The history

In the 80s of the past century I used to play the famous Paradroid from time to time and when I replaced my C64 with an Amiga 500, I decided to create a similiar game. Rooms, walls, more or less living things, guns, explosions, etc. In those days, to achieve acceptable gaming performance, you had not only to dive into the painful depths of Assembler, but also had to directly program the graphics chip. I neither did have the skills to do it, nor was Assembler ever my cup of tea. The result was a tech demo with stuttering scrolling tile maps and some sprites moving around. I probably experienced a lot of guru meditations as well :)
Today, hardware is so fast that games like Biodrone Battle run easily in virtual machines and can benefit from scripting languages.
Anyway, in the mid 90s I started working as developer for business software and as games evolved to huge mega-budget productions, it seemed that the time for independent developers was over, for good. The times they are-a-changing, and some day, Indie games started to rise from the dead.

Development started part time in 2011, evolved to a full time project in 2012 for about a year, and turned back to part time development until July 2015 when the game was published on Steam.

About the infamous game engine or Libgdx

Biodrone Battle was built with and upon Libgdx.

The good:

It was really helpful. Without any OpenGL knowledge I could still create an OpenGL game while Libgdx was covering the low level details under the hood.
Biodrone Battle uses Libgdx for the following topics:
  • rendering sprite batches
  • physics library Box2D for collision detection and line of sight
  • lighting with Box2dLights
  • particles
  • loading Tiled maps
  • playing sound
  • UI controls for the game lobby

The bad:

Documentation was partly hard to find. It still lacks JavaDoc.
There are 3rd party libraries integrated into the LWJGL backend jar which is a bad decision because it can easily mess up when you got another version of the same library in your project.
Loading of native libraries is done by silently unpacking into the user's system temp folder. Which is meant to simplify things, does actually the opposite like every hidden black magic code.
Dependencies. There is a potential danger that as Libgdx grows, it will become a clunky monolith which can no longer divided into meaningful sub-modules. Just as the Java SDK is now. There are unnecessary cyclic references between actually unrelated packages.
Some time ago, Libgdx got a new loader for Tiled maps. But unfortunately, it was not designed with a separation of model (maps) and the graphics side (images and rendering). In the time of multiplayer and web games, it should be possible to load maps on the backend without having all the rendering stuff hardly glued to it.
Leaving the given route is at places hard to do because of protected classes or private methods.
Easy lighting is only possible through Box2dLights which is great at the beginning but lacks support for example height of scene bodies in order to have variated shadow lengths.

The conclusion:

Do I recommend to use Libgdx ?
If it is the right tool for the job, use it.
If you want to create your own game engine and are a beginner, even more likely check it out. Because you do not (yet) have the skills to build your home brewn engine, no matter what you think.
If you want to be a game developer (means someone who actually finishes games), check it out.

Game art

Maybe the biggest problem was to not have a dedicated graphic designer as constant team member. I did not know any designer when I started. Thus, I had to use the internet to find someone, which turned out surprisingly difficult. I needed someone who was good, affordable, available and reliable. A challenging combination. Luckily I was finally successful. Several times in fact, as the game art was done by multiple people (which leads to the next problem: a potentially inconsistent art style).

There are tons of free textures to be found in the internet, even 3D models are often available for little money. Can't you just use them ? Sometimes you can, very often not. Because art styles are too diverse and mixing assets wildly leads to a some kind of unprofessional patch work game appearance. For Biodrone Battle, textures were often too realistic and did not fit the existing hand drawn assets.

Game art is not finished after receiving your outsourced assets. Inevitably, there will be adjustments to be made, again and again, which can be very time consuming. Having someone taking care of all of it is an invaluable enrichment.
To be on the safe side, if you outsource art, in any case add the original sources (Photoshop files mostly) explicitly as part to the contract.

What about pixel art, isn't that much easier ? First of all, good pixel art is not easily done at all and takes much experience as well. Then, as I grew up gaming wise in the 80s, I rather look at it as something which has luckily been overcome. Finally, pixel art is currently to be seen everywhere and I got kinda bored of it (again). Each to their own.

In the beginning, one open design decision was whether to create a game with a top-down or a side view. As you see, top-down won. In retrospect, I think a side view would have been better. Simply because it leaves more options for creating the game world, for adding details to the characters and environment.

Graphics programming

I started off by using Java2D, simply because it was easy and straightforward to use without the need to learn a lot. It wasn't a bad decision performance wise. As long as you use Java2D for simply rendering textures, it is pretty fast (as opposed to repeated contrary statements). But to play in the gaming league of today, a game has to offer impressive graphics effects like lighting and particles. To deal with that, it was time to drop Java2D and look out for something more practicable to do the job. For the Java platform, it means OpenGL and most probably LWJGL. Furthermore, if you don't want to mess with low level details, Libgdx is the way to go. So, in the middle of development, I had to switch the frontend from Java2D to Libgdx. Luckily, because Biodrone Battle was planned and had already been developed as multiplayer game, game logic and graphics rendering were strictly separated, this task wasn't such a drawback as one might think. There were relatively few places to change and reimplement.

By the way, why on earth did I start to develop a serious game with a language and platform  everybody knows is slow ?
Two simple answers:
1. I knew Java very well due to my daytime job as business software developer. No learning efforts means more time for the actual game programming.
2. Java is more than fast enough for the job.

And you probably all know that the most insanely successful Indie game ever was written with Java...

As Biodrone Battle's maps are made of square tiles, I needed a map editor to create them. Because programming my own editor would have taken valuable time, I looked for a ready-to-use piece of software and stumbled upon Tiled. Using Tiled started out as very convenient, but as graphic features like lights and particles were added it became more and more cumbersome to create maps. Level design was one largely underestimated task anyway.

On the wrong track

One driving idea and key feature was to not simply to create a Paradroid-inspired game, but if anything, it should become a multiplayer game.
Every game of today is multiplayer ready, isn't it ? So, Biodrone Battle got a full blown client-server architecture and worked nicely as network game. As local network game, to be precise. Because for the internet, you have to deal with lag, latency, client prediction, you name it.
To make things worse, Biodrone Battle uses the physics libary Box2d, which makes it very hard if not impossible to let a game work in a client/server setup. Furthermore, in a 2D game, every discrepancy between clients and server is hard to hide.
End of story, multiplayer support is history for this game. I still kinda regret it, thinking of very nice and fun game play enhancements, and the wasted development efforts. But it was right to do so. Would there have been enough people to play the game anyway ? And if there were, who would have run game servers to play on ?
It is regretful, but was the right decision.

Time eaters

The biggest time eater was the multiplayer excourse, but there were many more that added up quite a bit:
  • Switching from Java2D to Libgdx
  • Fiddling with sprite, tile sheets, colors, particles
  • Setting up a build environment, build scripts, source control
  • Creating a website, installing forum software
  • Switching from a home brewn movement and collision detection module to Box2D
  • After porting to Android realizing that Biodrone Battle is not playable nicely as mobile game due to the lack of usable controls
  • Creating new drone characters and implementing new individual AI behaviour during the middle of development
  • Balancing, balancing, balancing. There are many, many settings to adjust which influence each other and require testing after tweaking one
  • Level design. This is tricky, demanding and time consuming. Levels need to be fun and interesting, challenging but manageable, diverse in appearance and gameplay.
  • Game video
  • Polishing

Money, money, money

That's what everyone wants to talk about, isn't it. How much money did Biodrone Battle collect on Steam ? Am I rich now ?
Answers are:
1. next to nothing
2. no

The game sold few copies and I got out of it with actually losing money which I had spent for artists, music, assets, software and testers. The reasons for this are more or less the same as they are for many other Indie games and have been discussed lots of times on the Internet.
There are three points specific to Biodrone Battle, though:
First of all, my assumption about the target audience was apparently wrong. Being inspired by the famous game Paradroid, I thought that people who liked the original, might have fun in a modern remake. But gamers are conservative gaming-wise and this is even more true for retro players. Biodrone Battle is a somewhat retro game, but again lacks a typical pixel look.
Another problem could be the game's difficulty. Hard games seem to be a no-go these days. Having said that, I also saw a newbie rushing through the first five levels making me think whether the game was too easy.


Was it fun ?
Yes (most of the time, during the last 6 months not a bit)

Did I learn anything ?
A lot.

Do I regret it (years of unpaid work and additional investment of cash) ?

Would I do it again ?
To be precise, only with appropriate budget and without the need to earn money on the side, only with an artist as project member, and last, but not least, only with a maximum time schedule of one year (means having a finished and polished game) in that time span.
Before Biodrone Battle, I had only done business software and wanted to have at least one finished computer game done. According to this - mission accomplished.

Addendum: The Multiple Personalities of the Solitary Indie Game Developer

Did you ever think of creating a computer game all on your own ? There is probably much more to be done than you can think of. Various topics are to be covered which makes it both interesting and challenging. As such a project evolves, sensations of being overwhelmed might come up as well..
Here is my list of tasks that occurred for Biodrone Battle, but it could also act as task template for other more or less similar games:

Programming the infrastructure

  • some kind of basic keep-it-simple architecture
  • game startup/setup and shutdown
  • loading and caching of assets and levels
  • switching screens
  • sending and receiving in-game events
  • thoroughly taking care of threading
  • asynchronous asset loading
  • player registration
  • saving and resuming games in a database
  • game lobby with game options
  • levels configurable by property files


  • making decisions for all drone types with individual goals and states
  • path finding


  • creating assets
  • manage all assets in three basic sizes (64x64, 96x96, 128x128)
  • laying out sprite maps
  • adjusting colors, brightness and contrast
  • rendering sprites
  • drawing (layered) tile maps
  • lighting
  • designing particles
  • controlling the frame rate, interpolating view for smooth movement
  • switchable screens (lobby, levels, transporter between levels)
  • HUD
  • triggering particles, light and other effects on receiving relevant events
  • switching light on and off, rotating cone lights, player focusing spot lights
  • effects like light flickering, sreen shaking, drone materializing, game over noise
  • sprite animation (looped or once)


  • creating or licensing sound and music
  • adding effects like reverb, distortion, compression
  • taking care of fades and loopable sounds
  • adjusting volumes
  • playing, stopping, fading and resuming sound
  • triggering sound effects on receiving relevant events


  • creating physics objects for walls, enemies, player, bullets
  • collision handling
  • bullets
  • calculating line-of-sight/field-of-view


  • handling of keyboard, mouse and controller events
  • mappable key events


  • tutorial / showing in-game context dependent hint
  • showing HUD help layers
  • writing documentation

Game play 

  • first of all, defining the game play
  • implementing the game's rules
  • acting on collision events
  • watching life power of all drones
  • using gadgets like invisibility, super speed, damage doubling, etc.
  • walking upon special tiles for powering-up
  • opening and closing doors 
  • watching out for finished levels, won and lost games


  • setting up build files for automatically bundling complete game packages
  • optionally asset encryption
  • handling version numbers
  • taking care of beta, demo and full versions
  • create proprietary game launchers for Windows, Mac and Linux

Level design

  • designing maps that are fun, unique, challenging, diversified, have the right size *
  • adding doors, objects, particles and lights
  • tweaking lights
  • adding enemies


  • looking for bugs
  • overall balancing
  • testing on Windows, Linux and OSX
  • testing for various hardware and drivers


  • tweaking graphics, sound, menus, colors, particles, help and levels, playing, balancing, adding more graphic assets - again and again


  • for outsourced tasks, writing job offers, choosing the right people, pushing to work, reviewing and integrating finished work 
  • taking breaks (I have a vague feeling I have to mention it...)


Taking care about website, Twitter, Facebook, blog, Youtubers, forumsa and press mails.

Tech stuff

Sorted batch rendering for Libgdx
Blackcat - a lightweight dependency injection library for Java
A Layered Game Architecture I - Overview
A Layered Game Architecture II - Backend AI
A Layered Game Architecture III - Scenes and Directors
Design Patterns in Game Programming (III): Visitor
Design Patterns in Game Programming (II): Strategy
Design Patterns in Game Programming (I): Observer / MVC
Some Thoughts about (Object Oriented) Game Programming

October 4, 2015

SpringBoot Tomcat logging configuration

I had a hard time in getting a SpringBoot Tomcat application configured in such a way that configuration files are read from TOMCAT_BASE/conf and log files are written to TOMCAT_BASE/logs. It should work from Eclipse as well as for an external Tomcat. Many questions and answers could be found about similiar problems, but this is what finally worked for me:

Put a bootstrap logback.xml into the classpath root and let point to the actual logging configuration:

            <include file="${catalina.base}/conf/myApp-logback.xml" />        


The logging configuration in ${catalina.base}/conf/myApp-logback.xml that writes to ${catalina.base}/logs/myApp.log looks something like this:      

            <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
                                   <pattern>%d{HH:mm:ss} [%thread] %-5level - %msg%n</pattern>

            <appender name="FILE" class="ch.qos.logback.core.FileAppender">
                                   <pattern>%d{yyyy.MM.dd HH:mm:ss} [%thread] %-5level - %msg%n</pattern>

            <root level="WARN">
                        <appender-ref ref="FILE" />
                        <appender-ref ref="STDOUT" />

            <logger name="de.myPackage" level="DEBUG"/>            

Other application settings are in a file at ${catalina.base}/conf/ and configured like this:

@PropertySources(value = {@PropertySource("file:${catalina.base}/conf/")})
public class Application extends SpringBootServletInitializer {           

            public static void main(String[] args) {

              , args);


Finally, when running from Eclipse, catalina.base is defined as VM argument:

Sorted Batch Rendering for LibGdx

This is a spin-off from the development of the game Biodrone Battle.
In the beginning, rendering was split up into multiple classes and as the code base grew, it was tedious to keep the right order for rendering layers of tiles and sprite components.

Furthermore, a lot of texture switches occurred. Whether that was a performance hit, was not analysed, but it was fixed easily after introducing sorted batch rendering. Taking the blend mode as sort criterium reduces the number of SpriteBatch flushes as well.

It is no longer necessary to provide an open SpriteBatch to each render class.

There are default implementations for rendering textures, particles and vertices. In case they don't meet your needs, just derive your own item classes from BatchRenderItem. The first sort criterium is always the layer (z-index) followed by individual criteria like texture handle or blend mode.

Run BatchQueueLauncher to get a first impression.

Create a render queue for texture items:
        renderQueue = new BatchRenderQueue(MAX_LAYERS);
        renderQueue.addItemClass(TextureBatchItem.class, new Pool() {
            protected TextureBatchItem newObject() {
                return new TextureBatchItem();
Queue a batch item:
            TextureBatchItem batchItem = renderQueue.obtainItem(TextureBatchItem.class);
            batchItem.setLocation(123, 456);

Draw all queued items:
private void render(BatchRenderQueue renderQueue, SpriteBatch batch) {
        long time = System.nanoTime();
        renderQueue.render(batch, time);