Technical

The art pipeline is something often underlooked by indie developers. You may think that you don’t need one because you don’t have 3000 3D models with different textures, materials, etc.

It may be true if you only have a small amount of images, sounds and music. But there are some cases when it’s very important to have a good pipeline, and Reckless Squad is one of those.

For the prototype of Reckless Squad, we used 2D sprites for the units:

They weren’t animated. I knew I needed 8 directions, at least 3 frames for walk animation, and a bunch of other animations like using a sword, a bow, or dying.

The amount of work was just astounding, and I knew I couldn’t do it alone. Worst, I’m not even an artist to begin with.

So I had to find a solution and use my abilities as a programmer to produce the needed content. Quickly it was clear that 3D was the way to go.

However, we didn’t want the game to be in 3D. It was a huge amount of work as it is in 2D, no need to add more complexity. So we used pre-rendered 3D graphics, like Diablo or Age of Empires.

I used Cinema4D as a 3D package

To do it I started by modeling a base mesh with rough edges. Then I added Hyper NURBS to subdivide the mesh and make it look more organic.

I wanted to keep the look and feel of the 2D sprites, and I knew the final images wouldn’t be larger than 48×48 pixels. So I used really simple shapes, with few to no details and plain colors as textures.

Speaking of textures, I used palettes. If you played a NES or SNES RPG before, you may remember all the similar monsters with just different colors. It was because the developers used the same image with a different palette (to save memory). I used the same technique for Reckless Squad: I unwrapped the UV once, and then only changed the colors in the palette to make them match the unit.

The next step was rigging, no magic here: I just added bones and painted vertex weights. What’s interesting is how I used little scripts to attach props to the bones, because different colors would never be enough to differentiate the units.

When the system to customize the base mesh was ready, it was time to add animations to it.

I first listed all the needed frames:

1 idle

3 walking

3 using a sword/staff

3 using a bow

3 dying

1 standing victorious

It’s 14 frames, for just one direction, meaning 112 for an entire sprite sheet.

I made the timeline 112 frames long, and started making poses using the previously created rig. Once I finished a direction, I copy/pasted it 7 times and rotated the model to face new directions.

It was time to setup the rendering. I decided to use global illumination to shade the models because I didn’t wanted to make the light come from just one direction, it wouldn’t feel very natural. With global illumination, the light seems to come from everywhere and makes the shape stand out. The downside was that the time to render a sprite would be quite long…

I configured the rendering so that it will save each frame to two bitmap files: one for the diffuse color and one for the alpha mask. It was the more automatic setup I could come up with.

So I basically had 224 bitmap files on my hard disk, and I needed to combine them into a sprite sheet usable by the game.

And I needed to make it automatic as well. So I wrote a little script in C# for that. The program create a blank texture sheet and then load the diffuse color and the alpha mask files for each frame and combine them before placing them on the sheet.

When finished, it saves the final sheet to a new PNG file, with transparency.

A finished sprite sheet

I’m glad I took the time to setup a real art pipeline as automated as possible, because I ended up with 46 sprite sheets.

5 152 frames in total. It would really have been impossible for me to do them by hand in a pixel art fashion.

However, we did have some concerns with the graphics, mainly all the units share the same silhouette. Using very different and instantly recognizable silhouettes make the game easier to play and visually nicer. Just look at Team Fortress 2 and the amazing work done by Valve to give each class a unique silhouette.

But I still know it would have been impossible to make them all by hand. Using morphing could be a solution, and it would be interesting to make some researches in this direction next time.

Optimization is a special keyword in the world of video games. If you go to player-centric websites chances are you will hear it a lot.

Video games are interactive simulations and simulations are a very specific type of software. You don’t program a game like you program a business app. Games need to update themselves over time, not only when the user click on a button, and this can quickly lead to performance problems.

Here are some tips about optimizing your game based on what I experienced during the development of our game, Reckless Squad.

1. Profile

You can’t just optimize all your code, it’s not realist. You don’t have time for that and you will needlessly obfuscate your code base and make it harder to maintain.

So how do you decide which parts of your code need to be optimized?

Enter profiler. A profiler can take many forms, but its purpose is always the same: telling you how long the different parts of your code take. All the major IDE ship with one, and if you don’t have one you can always do it manually with the good old time() function.

Start by profiling on a high level, is it your update() or your draw() function that takes this much time? Once you know you can be more specific and see if it’s updatePlayer() or updateUserInterface().

2. Don’t run it

Now that you know what is slowing down your game, you can start optimizing it. Here is the most effective and easy way to make a function run fast: don’t call it.

If it’s not running, it won’t take time, it’s obvious!

Okay, it’s not that simple, you wrote this code for a reason, right? You still need to run it, but maybe not that often.

Reckless Squad is a RTS game, with a lot of units, all updating at once. I quickly discovered that the AI was what took the most time. I asked myself: “is it really important that the AI run at 60Hz?” The answer was obvious: no.

So instead of running the AI code every time, I do it less often. Performances increases.

There is a problem with this approach: every time the code does run, you will experiment a sudden performance drop. Spreading the execution of this function across the frames will prevent this.

In my example I only update the AI of a fragment of the unit list each frame, allowing a sort of load balancing.

3. Know your platform

Every platform, language or SDK have its little secrets. Knowing some of them can be interesting from a performance standpoint.

For Reckless Squad we’re working with Lua. Lua is already a fast language but extra-performances can be obtained if you know how it works. There is some good information about it on the wiki.

To give other examples, using StringBuilder to concatenate strings in .NET or calling reserve() on the C++’s vector are other good practices specific to their platform/language/framework.

Similarly if your platform has 2 cores, it’s a good idea to use them effectively. And if you’re working for console or mobile devices, knowing your platforms and its pitfalls is increasingly important.

4. Think like a computer

Object Oriented Programming is cool. It’s easy to learn and to use because it naturally maps our way of thinking as humans. My computer in front of me is an object, it’s actually in a turned on state and it execute various methods like shutting himself down. It’s seems very natural to think like this when you code too.

However it’s not how computers work. Computers are calculators, processors. They take a bunch of input data and apply to them a specific transformation to get different output data.

If you can think this way too, you can present the problem in a more computer-friendly fashion.

I won’t go into details about it, because others had already done a great job:

This article is a departure from previous ones, as it’s aimed to other developers, hobbyists, and curious people.
It’s a technical article, some kind of “behind the scenes”.

The goal of this article is not to be theoretical or generalist, there’s already plenty of these on the Web. I will rather talk about our experience with scripting languages.

How it works at D2P Games

We made the early choice to use Lua as a scripting language. That wasn’t a very difficult choice, there’s a lot of good solutions available and Lua is really well suited for video games. It’s used in a lot of commercial games and is fast, robust and well documented.
I already used Lua for some years and I didn’t find any good reason to use something else.
The addition of Luabind was a huge time saver, as it takes care of the binding for us.

So how do we use Lua ? We use it for almost everything !

We have a C++ codebase, based on SFML and OpenGL. This codebase is very, very low level. It provides a set of functions like “LoadImage”, “DrawImage”, “PlaySound”, etc.
The implementation is object-oriented, but the final interface is not. Resources are handled using simple numbers passed across the different functions.
It really eases the binding with Lua.

So if the C++ engine provides only low level functions, we need to implement ALL the game logic in Lua.
There are pros and cons.

The advantages

Productivity. We are only three people working two days per week, every gain in development time is welcomed.
We don’t want to lose time with memory management, header/implementation separation, etc.
It keeps compilation times away from us : we just need to change the code, then relaunch the game. No time wasted waiting, it’s really useful when you want to quickly change some parameters to try some of your ideas.
Getting rid of large amounts of code is also easier because you spent less time to write it. No more “I won’t rewrite this part because it took me so long to write in the first place”, just press delete and move on to the next task.

It allow us to be messy. Yes, it may sounds like a strange advice. I’m sure all your teachers have told you not to write messy code but to do careful planning, draw UML diagrams and bla bla bla blaaa… But in the end, you have to get the job done. The good programmer is not the one that follows all the guidelines, but the one that ships his product with all the planned features, no critical bug, and in time.
The only real and universal advice that can apply for programmers is : “choose the right tools for the job”. It also works with methodology and processes.
We follow an iterating process, similar to agile methods : the goal is to get a working version as soon as possible, and then keep on iterating on it, adding (or removing) features.
This way, planning our code or documenting it is very time consuming, it would slow us down too much. Considering 90% of the code will be refactored anyway, it just doesn’t worth it.
Don’t get me wrong, you still have to follow some internal guidelines and write readable code with comments and meaningful variables’ names. I’m just saying you don’t have to bother with strict OOP principles : keep it simple and working. And do it quickly.

Scripting languages are simple. With few features and verbose syntax. Learning them shouldn’t be a problem for a designer with no prior technical background.
Though it’s not the case for us as we are three computer-science students with some affinity for programming.

The inconveniences

It may not be obvious but the dynamic aspect of these languages makes them hard to debug : all the errors are going to be runtime errors. If you passed the arguments in the wrong order, you won’t know until this specific code is executed, which may be a rare scenario. It’s vital to test the game often, and fully.
Otherwise you will be like “argh, the game crashed, but don’t worry it’s nothing, I will fix it right now” during a playtest (true story by the way). It may be okay for a playtest, but it’s unacceptable for a public release.

The topic of performances is often debated. The only truth is that it depends of the game. We experienced performance issues with Reckless Squad, but it’s a real-time strategy game, with a lot of units that need to run relatively-complicated AI and this lead to a huge CPU charge.
Moving the pathfinding (A*) and neighbor units queries from Lua to C++ did help a lot to solve those problems.
But don’t do it until you’re really sure it’s your bottleneck. Trying to optimize too early is generally a bad idea.

Lessons learned

Reckless Squad is still far from being finished, but we already learned some important lessons.

The first one is that using a scripting language has advantages that far outweigh the inconveniences. So it’s worth it.

The second one is that you should keep your binding layer thin. Make your C++ code higher level if you need to, but expose the fewest functions possible to the scripting language.

Finally, be very careful about what you do, because the flexibility of the scripting languages made them harder to debug.