Saturday, 25 July 2015

When creating a new game character it's crucial to get a feel for his in-game poses and movement as quickly as possible. During the visual design of a character you shouldn't just wonder how he looks, but also how he moves. If a character looks cool while standing still but bad while in motion, you have a problem. Not only is this a key part of a character's personality and look, it also helps discover problems early on. Maybe that big weapon is obstructing the dynamic actions your hero needs to do?

This is why our artists first draw key animation poses and throw those into the game as quickly as possible. During early development of a new character for Awesomenauts we playtest with just those key poses, without any animation. Less than 10 frames represent the entire movement set of the character. One frame for a jump, one for a fall, a couple for a walk, one for each attack, for sliding to a halt and for idling, and that's roughly it.

It's surprising how smooth and awesome a character can already feel with just one still frame per action. Doing this also has another benefit: the game design feels much more solid if a character isn't a box and doesn't look like some other character you already have in the game.

Of course, the phase after this is to create the actual animations. A finished character in Awesomenauts consists of hundreds of animation frames. But today I'd like to focus on the prototyping and concepting before the real animations are made.

Most of the characters we added to Awesomenauts during the past two years were animated by Ronimo artist Tim Scheel. Tim is a master at drawing dynamic poses and experiments a lot with the animations.

To show how this works I have dug into our archives and made a video of how Scoop, Nibbs and Rocco moved before they got any real animation. I think it's pretty amazing how powerful these already look!

Early animations of characters in Awesomenauts, using key poses only.

A nice thing to notice in this video is that Tim adds some quick in-engine squash-and-stretch effects to make it look a little bit more dynamic. This is especially noticeable in Nibbs' idle and attack frames.

Before Tim puts anything in the game he first makes animation concept art. This is just a sheet with a lot of sketches of what the various animations might look like. Here are the sketches Tim made for Rocco:

In Rocco's first gameplay design he couldn't move while doing special attacks. This allowed Tim to draw some really cool attack poses, as you can see in the sheet above. Later the game design changed and Rocco wasn't forced to stand still during attacks any more. This means Rocco needs to do his normal movement animations while doing a special attack, so the attacks changed from character animation to purely special effects.

A particular challenge when designing a character is the amount of detail. Awesomenauts has a strong cartoony style in which microscopic details don't really fit, especially since characters aren't that big on the screen. This means details that were in the concept art are often removed when the in-game version of a character is created. You can already see this happening in the concept art above: some shots have two little straps in the part around the neck, while others only have one of those, reducing the amount of detail a bit.

Rocco's scars were also a challenge: initially he had a scar on his nose but this turned out too small. The scar around his eyes was kept after making it a lot bigger to be more legible. The headphones had to go for a different reason: they had too little to do with Rocco's backstory and personality.

Another example of removing details can be seen below in Nibbs' animation concept art. Tn the bottom right you can see Nibbs' tongue hanging out while running. This is a little detail that I absolutely love: it makes Nibbs look so much more like an overly enthusiastic puppy dragon. However, it turned out to be too small and illegible in the actual game, so it was removed. How much detail there is, is an important part of any visual style, so this needs to be kept somewhat similar in all characters.

Another great example of animation influencing a character's visual design can be found in Ori And The Blind Forest, one of my favourite games of recent years. In a presentation at GDC animator James Benson mentions that Ori has a tale because it helped him show the direction of movement better. It's interesting to hear that a crucial element like a tail is there mostly because of the animation, not because of anything else. Be sure to check out this video of his highly interesting presentation!

Back to Awesomenauts! Because Scoop doesn't have legs, his walk cycle was a challenge. As you can see in the concept art below Tim drew a lot of poses for the walk cycle to try different things and find something that works.

When drawing game art one must never forget the goal of the art: to be used in an actual game. The requirements of the gameplay need to be kept in mind. In Awesomenauts this means that melee attacks allow for much more freedom than ranged attacks. Melee attacks are generally just an animation that plays, so Tim go do whatever he wants to make it look awesome. Ranged attacks however need to be aimed at the cursor, which means that the gun-arm needs to be able to rotate freely even during the attack. Not being able to animate the gun-arm is a huge limitation to the animations. Such gameplay limitations are important to keep in mind and this is why Tim enjoys animating melee attacks more than ranged attacks: more freedom!

A couple of years ago I hadn't realised that animations need prototyping and playtesting just as much as any other part of a game. The video at the start of this post gives a great example of this. I hope you enjoyed seeing Tim's animation concepting as much as I did!

Sunday, 19 July 2015

Solving complex coding problems is hard. What to do when the solution isn't immediately clear? Sometimes you might just get stuck on something, or you might have a solution but are wondering whether there is a better structure or algorithm. No matter how good you are as a programmer, there are always things that are just too complex to easily figure out. How to handle those? The simplistic answer is that you should simply get smarter and more experienced. This is also a lazy answer, as it means you can just keep doing what you do and hope you get better over time. What you can do right now is work on your mental toolbox, your own personal set of approaches and techniques to help your mind tackle topics that are too complex to otherwise solve.

By "mental toolbox" I basically just mean a bunch of tricks to help you think. Such tricks are very personal: what works for one person might not work for someone else. The important thing is to try different approaches and find out what works for you. In today's post I would like to share my own tricks, hoping some of these can help others as well.

Make schemes

Don't try to create an overview in your head, do it on paper! Draw flowcharts, timelines, mindmaps, UML diagrams, lists, relationship graphs or whatever else that might help you see the entire problem, or see the problem in a different light.

Write down all your thoughts

This is my most personal trick, as I have never heard of anyone else who does this, but it is also my best one. Whenever I am truly stuck I fall back to writing down all my thoughts.

To me the biggest problem when trying to solve something is that at some point my mind grinds to a halt as it tries to hold too many thoughts at once, leaving no room for new ones. This is a common thing in humans: in psychology it is called "The Magical Number Seven, Plus or Minus Two", stating that the average human can hold 7 ± 2 objects in working memory. The problem is that as soon as I have a bunch of thoughts that I think are interesting, I try to remember them and lose the capacity to come up with new ones.

My solution is to just write down all my thoughts, including the bad ones. For a complex problem I might scribble an entire A4 full of miniscule notes. For half of those I realise they are irrelevant before I even finish writing them down, but this doesn't matter. The only point is to clear my mind: whatever is on the paper doesn't have to be remembered, so there is room for new thoughts. Letting my mind ramble on and writing it all down often leads me to a solution. This is by far the strongest tool in my box.

Split the problem into smaller pieces

If a problem is really big it might help to just ignore half of it and only solve the other half. Often the parts of a problem depend on each other and trying to figure out the dependencies might be what makes the problem too complex to solve. Try solving only one part while ignoring everything else. Only once the part is solved, try to figure out how to make it work with the rest of the problem.

It can help to force yourself to try a completely different angle, sometimes to even try angles that might seem ridiculous at first. A good example is randomness: if you can't find an exact solution, you might try to generate random solutions and choose the best one. This is rarely the best approach, but looking at it from an angle like that might generate new ideas. For example, this particular approach makes you think about how to compare random results to figure out which is best. The algorithm for comparing results might be the starting point of a real solution. The goal is to force yourself to let go of your current line of thought and try completely different angles.

Just start coding

Sometimes you already have some ideas on how to tackle parts of a problem, but not the rest of it. In this case it might help to just start coding. The code you write will probably end up being thrown away once you figure out the real solution. This is fine: the goal is to turn general ideas into concrete code so that you understand it better. When using this approach be sure to throw away the garbage code afterwards!

Leave markers to avoid being sidetracked

Often while programming something complex I come up with additional problems that I will also need to solve, or edge cases that need to be handled. Doing those all at once makes me lose focus, but I don't want to ignore them either, because I might not remember them later on. So whenever I think of something, I leave a small comment in my code as a reminder and leave it at that, allowing me to keep my focus on one thing at a time. To be able to find those comments quickly once the core code is finished, I add the letters "QQQ" to them.

The internet

Caption Obvious would like to mention that you can search online for solutions.

Ask for help

Surprisingly, quit a lot of programmers would rather be stuck on something for days than ask for help. I have supervised a ton of interns and quite often they keep chewing on a problem without real progress for way too long before asking for help. Asking a question online seems to have a similar barrier. There is no shame in looking for help or discussing a problem with someone else, and often just explaining the problem to someone else clears up the mind enough that you figure out a solution yourself.

Ignore performance and requirements

Often it is easier to solve a problem in an inefficient way than in an efficient way. Letting go of performance requirements is a great way to open your mind to solutions. Often an efficient solution is just a clever variation on an inefficient one.

The same goes for requirements. If you are stuck, let go of all the additional requirements and first try to solve only the core problem. Then try to adapt your solution to those requirements.

Know lots of programming patterns

I often struggle with finding a really good class structure to make my code as clear and maintainable as possible. For such situations it helps to know a lot of design patterns. Design patterns are common structures that can be applied to specific problems. There is an enormous amount of design patterns and the more you know, the better. Wikipedia has a nice overview, including well-known ones like Observer, Factory, Singleton and Strategy.

Know lots of algorithmic techniques

Many problems are completely different, but can be solved in similar ways. Often you can find a solution by trying approaches you have seen in other algorithms. The more approaches you have seen, the larger the chance you know something suitable. Here are a bunch of categories of solutions of which it is good to have seen a couple of examples of algorithms that use each approach:

Recursive algorithms

Heuristics (or: approximate solutions versus exact solutions)

Greedy algorithms

Dynamic programming algorithms

Iterative improvement (running the same algorithm over and over again to improve the result with each run)

Smaller steps (splitting a simulation into smaller steps instead of once with a big step, like in this collision trick I used in Proun)

Monte Carlo versus Las Vegas algorithms

Take your mind off the problem

If all else fails you can choose to simply leave the problem be for a day or two and work on something else. A solution might pop up when least expected. Under the shower, while cycling or taking a walk. I personally get lots of good ideas on the toilet... Key to this approach is to allow your mind to wander. Don't fill every waking minute of your day with entertainment/work as your mind would be too occupied for new thoughts.

Your mental toolbox is something you can improve and work on. You can experiment with new approaches and ask others what theirs are. Give all kinds of things a try, and see what works for you.