So far I have focussed all my efforts for Cello Fortress on the gameplay. Controlling a game with a live cello is a big challenge, both technically and in terms of game design. Now that that is turning out well, the next step is to get rid of the prototype art and give the game real graphics. I have been thinking a lot about the exact visual style and the goal is of course to make Cello Fortress look really good. While the current version of Cello Fortress does not contain any of these visual ideas yet, today I'd like to show my inspirations, and some visual experiments that I did.
The base inspirational image for Cello Fortress' visuals comes from the special edition booklet to Radiohead's album Amnesiac. It is a really noisy and small image, and the scan makes it even worse, but the core of it is this: extremely low-polygon mountains with extremely low-res textures, so that there are big square pixels on the flat triangles.
Taking this idea, I did a quick experiment in 3D Studio MAX. I just piled some pyramid-like shapes in the scene and put on some textures, without any intend on making a real composition or anything finished. I didn't want it to actually be as rough as the Radiohead image, so I added lighting and depth of field blur to it.
The other big influence comes from an indie game called Teleglitch. In Teleglitch, whenever you shoot the colours on the screen are ripped apart. This gives a very raw and powerful effect, so I wanted something similar. Skip to 58s in this video to see the effect in action:
Gameplay footage from Teleglitch, check the effect after 58s
Of course, I wouldn't want to just copy that, so I came up with something different that was inspired by this effect: bullets and explosions deform the landscape in 3D with a rough noise. I added this effect to my little 3D Studio MAX testscene and made this little previz animation that shows the effect in action, much to my satisfaction:
Cello Fortress pre-visualisation
At this point I actually thought I had copied the effect from another Radiohead video, but I couldn't find it anymore. In my memory, Yorke's head deformed in exactly the same way whenever he held his finger close to his head. After a lot of searching I discovered the video was called "Go To Sleep", but to my surprise the effect is very different here. Instead of deforming, they animate the number of polygons in his head, which looks quite different, as you can see here. (Note that in 3D Studio MAX, this can be done very easily by animating the Optimise modifier.)
So my inspiration turned out to be completely different from what I had remembered, but my own result looks good, so I am happy. ^_^ This kind of process is something I like a lot: if I add my own interpretation to something that inspired me, it becomes something new. This also happened with Proun: it was strongly inspired by Kandinsky and Rietveld, but by adding my own ideas, it became instantly recognisable as something else, something of my own.
At this point, I concluded rawness was my goal. I found another great example of the vibe I wanted in a trailer for Luftrausers, a game by our friends and neighbours from Vlambeer. I really like the extreme vibe they managed to achieve:
Luftrausers by Vlambeer, coming soon to PS3, Vita and PC!
From here, it seems quite simple to conclude what Cello Fortress' visual style should be: raw, pixels, big polygons, extreme effects, noise, screen shakes, grey. However, more recently I discovered some other images that I find extremely inspiring, but that contradict that. They also work with the big-polygons-big-pixels style, but are much less raw. Just have a look at these beauties:
These images from the fantastic Geo A Day and JR Schmidt combine a lot more colour and smoothness with the sharpness of the polygons, and I'd love to make something like that. However, they are quite at odds with the roughness I was previously aiming for.
The final element that has been inspiring me for Cello Fortress, and that I think will combine very well with the images above, is the tilt shift effect that is seen in the new Sim City. It is also found in tons of random videos on Youtube, like in "The Sandpit", which, if you have never seen it before, you need to watch right now. Tilt shift is basically just an extreme depth of field blur that makes everything look small. I also think it looks absolutely gorgeous.
Tilt shift in the new Sim City (which, by the way, is a great game, and much better than the 6.5 Metacritic currently has it at because of those DRM shenanigans...)
Having all these elements, I am not sure yet how I shall mix them. I expect some kind of combination of all of these ingredients, but I am really curious how raw Cello Fortress will end up exactly. Knowing myself, there is a good chance it will turn out a lot more smooth, like my Solid Motion series.
Regardless of what it ends up being exactly, I hope it ends up both unique and awesome! Next week I will release a new gameplay trailer for Cello Fortress, still with the old prototype graphics, and after that I'll get cracking on these graphics!
Sunday, 28 April 2013
Saturday, 13 April 2013
Making everything animatable
Everything in our tools is animatable. Not just position, rotation and scale, but also things like colour, skew, taper, texture scroll and the number of particles emitted. This is a feature that I know from 3D Studio MAX and that I had been admiring for ages, so as a programmer I really wanted to come up with a neat system to build this. Being able to animate everything also happens to be really useful for our artists... ;) Today, I would like to explain how we built this.
You might already have seen our animation tools in the Ronitech tools trailer I made a while ago, but that was only a very short fragment, so here is a more complete demo of the animation capabilities of the Ronitech animation editor:
Before I continue, I should note that although I designed most of this system, the real credit should go to Thijs (at the time a coding intern at Ronimo, now a gameplay programmer): he implemented it all, figured out the nitty-gritty details, and built the editor's animation UI.
With so many variables that can be animated, we need a good way on the coding side to hide the actual animation code from everything else. In fact, ideally I would like to be able to just mark a variable as being animatable, and that's it. Relatively simple object oriented design allowed us to do just that.
To make a value animatable, we write a class around it called AnimatedFloat, which handles the animation and contains the data needed for that. This class is updated every frame, and whenever the value is used, we just ask for it in that class. Using our AnimatedFloat in a gameplay object looks something like this:
This works simple enough, and AnimatedFloat itself is quite straightforward to implement like this. There are a couple of things in this bit of code that we could try to improve, though. One is those calls to getCurrentValue(). This function returns the value that the scale has at the current moment in time. If we use the scale variable a lot, it might be cumbersome to call getCurrentValue() all the time. Luckily, there is a nice (and rather obscure) solution for this in C++: we can skip calling that function by providing a conversion operator in the AnimatedFloat class. Like this:
The operator float() there is a conversion operator and tells C++ what to do if we use an AnimatedFloat in a spot where a float was expected. It removes the need for calling the function getCurrentValue().
This is a simple and nice solution. However, in practice we ended up not using it in our code, because our AnimatedFloat also has a function getBaseValue() (for animations that perform a periodical animation around a base value), and we felt it was not clear enough which value the conversion operator would return.
A bigger problem in our current design is that it is easy to forget to update one of the AnimatedFloats in a class. If we forget to update it, everything still works, but the object won't animate anymore. With the large number of AnimatedFloats some of our classes have, this is an easy oversight, and forgettig it might not become apparent until an artist actually tries to animate something and it doesn't work. I would prefer it if we could make it so that it is not possible for the programmer to forget updating a single variable.
I imagine there is a solution for this using macros, but I in general I think macros are not very readable, so we avoid them whenever possible.
The solution we came up with, is that values are updated by another class: the ObjectAnimator. The AnimatedFloat itself can only be created by providing an ObjectAnimator. Now the programmer only needs to update the ObjectAnimator and cannot forget about individual variables anymore. It is still possible to forget to update the ObjectAnimator, but then nothing at all will be animatable, so this is much less likely to be overlooked. Our design now looks like this:
The clue is that AnimatedFloat's constructor requires an ObjectAnimator. Without an ObjectAnimator, it cannot be created at all, so it is impossible to forget about it in WorldObject's initialiser list.
This is a nice example of a coding principle that is extremely important to me: code needs to be designed in such a way that common mistakes are simply not possible. Of course, this principle cannot be achieved in everything, but at least it is a good goal to strive for. In this case, by changing our class design, we have avoided a future bug that was very likely to happen quite often.
A big flaw in this design is that it currently only animates floats. In reality, a lot of our values are other things, like Colour, Radian and Vector2. The solution to this is to make AnimatedFloat templatised and to rename it to AnimatedValue. This is quite straightforward if you are experienced with templatised programming, but for any programmers less familiar with this weird part of C++, I'll provide a small example of roughly how that looks. Just think of a template as a type that will be filled in depending on what it really is. So T here can be a float, or a double, or a Colour, or whatever you want. In this specific piece of code, substitute the T with something that one can do math on, and it will still be good code.
There are some details to this that make the real code a bit more complex, but the core idea remains the same. By using templates, we now have a single AnimatedValue class that can animate any kind of value that we can do math on.
There are several topics that I have completely ignored so far. The first is actual animation. However, I don't want to make this post too long, so I won't go into detail on that. Animations are calculated in the updateAnimation() function of AnimatedValue.
Another topic I have ignored is how to generate an interface for editing these values, how to save them, and how to even have complete undo/redo for editing animation details. That is an interesting topic by itself, so I think I might get to that in a future blogpost at some point.
Finally, there is the topic of performance. Updating all these animation objects uses actual performance, especially if our artists animate tons of values. I had to optimise our animation code quite a bit to still get a good framerate on consoles. In the end, this is a trade-off I seem to encounter all the time: in most cases, the more flexible a system is, the more performance it uses. Luckily, computers and consoles are getting faster and faster, so as this is only a small problem for us now, I have no doubt a couple of years from now the performance of systems like this will have become completely irrelevant in all but the biggest triple-A games.
The fun part of our animation system, is that it is extremely flexible, but at the same time rather simple to build and use. In that sense it is rather similar to our upgrade system for gameplay, which I explained in a blogpost last year. Our artists have made tons of animations with our animation system for Awesomenauts, and it contributed greatly to the lively feel that the game has!
You might already have seen our animation tools in the Ronitech tools trailer I made a while ago, but that was only a very short fragment, so here is a more complete demo of the animation capabilities of the Ronitech animation editor:
Before I continue, I should note that although I designed most of this system, the real credit should go to Thijs (at the time a coding intern at Ronimo, now a gameplay programmer): he implemented it all, figured out the nitty-gritty details, and built the editor's animation UI.
With so many variables that can be animated, we need a good way on the coding side to hide the actual animation code from everything else. In fact, ideally I would like to be able to just mark a variable as being animatable, and that's it. Relatively simple object oriented design allowed us to do just that.
To make a value animatable, we write a class around it called AnimatedFloat, which handles the animation and contains the data needed for that. This class is updated every frame, and whenever the value is used, we just ask for it in that class. Using our AnimatedFloat in a gameplay object looks something like this:
class WorldObject { AnimatedFloat scale; AnimatedFloat rotation; TexturedRectangle* visualObject; void update(float time) { position.updateAnimation(time); rotation.updateAnimation(time); visualObject->setScale(scale.getCurrentValue()); visualObject->setRotation(rotation.getCurrentValue()); } }; |
This works simple enough, and AnimatedFloat itself is quite straightforward to implement like this. There are a couple of things in this bit of code that we could try to improve, though. One is those calls to getCurrentValue(). This function returns the value that the scale has at the current moment in time. If we use the scale variable a lot, it might be cumbersome to call getCurrentValue() all the time. Luckily, there is a nice (and rather obscure) solution for this in C++: we can skip calling that function by providing a conversion operator in the AnimatedFloat class. Like this:
class AnimatedFloat { float currentValue; void updateAnimation(float time) { //perform actual animation here and update currentValue } operator float() const { return currentValue; } }; |
The operator float() there is a conversion operator and tells C++ what to do if we use an AnimatedFloat in a spot where a float was expected. It removes the need for calling the function getCurrentValue().
This is a simple and nice solution. However, in practice we ended up not using it in our code, because our AnimatedFloat also has a function getBaseValue() (for animations that perform a periodical animation around a base value), and we felt it was not clear enough which value the conversion operator would return.
A bigger problem in our current design is that it is easy to forget to update one of the AnimatedFloats in a class. If we forget to update it, everything still works, but the object won't animate anymore. With the large number of AnimatedFloats some of our classes have, this is an easy oversight, and forgettig it might not become apparent until an artist actually tries to animate something and it doesn't work. I would prefer it if we could make it so that it is not possible for the programmer to forget updating a single variable.
I imagine there is a solution for this using macros, but I in general I think macros are not very readable, so we avoid them whenever possible.
The solution we came up with, is that values are updated by another class: the ObjectAnimator. The AnimatedFloat itself can only be created by providing an ObjectAnimator. Now the programmer only needs to update the ObjectAnimator and cannot forget about individual variables anymore. It is still possible to forget to update the ObjectAnimator, but then nothing at all will be animatable, so this is much less likely to be overlooked. Our design now looks like this:
class ObjectAnimator { std::vector |
The clue is that AnimatedFloat's constructor requires an ObjectAnimator. Without an ObjectAnimator, it cannot be created at all, so it is impossible to forget about it in WorldObject's initialiser list.
This is a nice example of a coding principle that is extremely important to me: code needs to be designed in such a way that common mistakes are simply not possible. Of course, this principle cannot be achieved in everything, but at least it is a good goal to strive for. In this case, by changing our class design, we have avoided a future bug that was very likely to happen quite often.
A big flaw in this design is that it currently only animates floats. In reality, a lot of our values are other things, like Colour, Radian and Vector2. The solution to this is to make AnimatedFloat templatised and to rename it to AnimatedValue. This is quite straightforward if you are experienced with templatised programming, but for any programmers less familiar with this weird part of C++, I'll provide a small example of roughly how that looks. Just think of a template as a type that will be filled in depending on what it really is. So T here can be a float, or a double, or a Colour, or whatever you want. In this specific piece of code, substitute the T with something that one can do math on, and it will still be good code.
template ‹typename T› class AnimatedValue { T currentValue; T getCurrentValue() const { return currentValue; } }; class WorldObject: ObjectAnimator { AnimatedValue‹float› scale; AnimatedValue‹Radian› rotation; }; |
There are some details to this that make the real code a bit more complex, but the core idea remains the same. By using templates, we now have a single AnimatedValue class that can animate any kind of value that we can do math on.
There are several topics that I have completely ignored so far. The first is actual animation. However, I don't want to make this post too long, so I won't go into detail on that. Animations are calculated in the updateAnimation() function of AnimatedValue.
Another topic I have ignored is how to generate an interface for editing these values, how to save them, and how to even have complete undo/redo for editing animation details. That is an interesting topic by itself, so I think I might get to that in a future blogpost at some point.
Finally, there is the topic of performance. Updating all these animation objects uses actual performance, especially if our artists animate tons of values. I had to optimise our animation code quite a bit to still get a good framerate on consoles. In the end, this is a trade-off I seem to encounter all the time: in most cases, the more flexible a system is, the more performance it uses. Luckily, computers and consoles are getting faster and faster, so as this is only a small problem for us now, I have no doubt a couple of years from now the performance of systems like this will have become completely irrelevant in all but the biggest triple-A games.
The fun part of our animation system, is that it is extremely flexible, but at the same time rather simple to build and use. In that sense it is rather similar to our upgrade system for gameplay, which I explained in a blogpost last year. Our artists have made tons of animations with our animation system for Awesomenauts, and it contributed greatly to the lively feel that the game has!
Saturday, 6 April 2013
From melee to ranged: the most difficult design decision in Awesomenauts
Many people probably won't realise this, but while Awesomenauts may feel like a logical translation of the MOBA genre (games like DotA and League of Legends) to a 2D platformer, the design process was in fact long and difficult. Striking the right balance between tactical gameplay, platforming combat and match flow took a long evolution, with tons of experimentation and careful design. A little bit of that process shows through Sheriff Lonestar's evolution, which I talked about last week.
Awesomenauts' design originally featured tons of features that didn't make it into the game. Probably the most striking of those is the disappearance of most heros' melee skill. Originally all classes in Awesomenauts had both a ranged skill and a melee skill, including Lonestar. Looking back, this surprises me, since the current distinction between ranged and melee characters feels so natural. It took us a long time to figure this out, though!
Originally we wanted to make something with some similarities to a brawler, so the melee skills that every character had were very strong. They also had a ranged weapon, but in the early balance of the game you had to get close to do some real damage. This was a constant gameplay headache during early development. With all the characters and droids, gameplay is just too chaotic to make melee combat work. Most combat came down to standing in front of each other and just bashing the attack button to do maximum melee damage. Nevertheless, we had a certain vision for the game, and several team members fought valiantly to keep the melee combat central. So we explored lots of melee mechanics to find a way to make it work.
The biggest problem was that everyone just stood in front of each other and bashed the punch button. We first tried solving this by adding depth to the combat. We added combos (every third attack is stronger if you time the button presses right), we added two buttons for a fast and a slow hit, we even added a parry button: a defensive move that if pressed at the right moment would fend off a hit and cause the attacker to be stunned for a short moment.
However, all of these bumped into the same problem: if more than one opponent is standing in the same spot, this quickly turns into massive chaos. For example, it is impossible to time your parries if three opponents stand in one place and attack with different timings.
Other games often solve this by changing the AI. For example, Assassin's Creed lets part of the group wait, so that enemies roughly attack in turn. Another solution for group combat can be found in Shank and Batman Arkham City, where many of your attacks stun or knockback enemies, allowing the player to temporarily keep some opponents out of the battle and focus on one or two enemies at a time. However, both of these solutions totally fail to work if the opponents are human players: being stunned a lot is no fun, nor is waiting for your turn to attack.
Another thing we tried to make the combat more dynamic, was adding a 'lunge' attack. This was a game mechanic where if you are in the air, you can press a button to home in on an enemy and kick him from above. This made it more useful to keep jumping and moving, but definitely didn't decrease the chaos.
We even experimented with letting teammates collide with each other, so that no two players could stand in the same spot. This turned out to feel very frustrating: your allies were now always standing in your way and sometimes you couldn't hit an enemy because a droid was standing in front of him already.
Several team-members really wanted to keep the melee mechanics in the game, but at some point our designers (Fabian and Jasper) got bold and simply removed all melee skills for one playtest. It turned out that this instantly fixed all these problems. Everyone keeps a little bit of distance from each other and you don't need to all stand in the same spot anymore to attack. Also, jumping became way more important, because you can evade bullets and aim at opponents at the same time!
This was one of the biggest breakthroughs in the design of Awesomenauts. The result was so convincing, that of the original six Awesomenauts, only Leon ended up with a melee skill. All the others turned ranged and it worked great!
Awesomenauts' design originally featured tons of features that didn't make it into the game. Probably the most striking of those is the disappearance of most heros' melee skill. Originally all classes in Awesomenauts had both a ranged skill and a melee skill, including Lonestar. Looking back, this surprises me, since the current distinction between ranged and melee characters feels so natural. It took us a long time to figure this out, though!
Originally we wanted to make something with some similarities to a brawler, so the melee skills that every character had were very strong. They also had a ranged weapon, but in the early balance of the game you had to get close to do some real damage. This was a constant gameplay headache during early development. With all the characters and droids, gameplay is just too chaotic to make melee combat work. Most combat came down to standing in front of each other and just bashing the attack button to do maximum melee damage. Nevertheless, we had a certain vision for the game, and several team members fought valiantly to keep the melee combat central. So we explored lots of melee mechanics to find a way to make it work.
The biggest problem was that everyone just stood in front of each other and bashed the punch button. We first tried solving this by adding depth to the combat. We added combos (every third attack is stronger if you time the button presses right), we added two buttons for a fast and a slow hit, we even added a parry button: a defensive move that if pressed at the right moment would fend off a hit and cause the attacker to be stunned for a short moment.
However, all of these bumped into the same problem: if more than one opponent is standing in the same spot, this quickly turns into massive chaos. For example, it is impossible to time your parries if three opponents stand in one place and attack with different timings.
Other games often solve this by changing the AI. For example, Assassin's Creed lets part of the group wait, so that enemies roughly attack in turn. Another solution for group combat can be found in Shank and Batman Arkham City, where many of your attacks stun or knockback enemies, allowing the player to temporarily keep some opponents out of the battle and focus on one or two enemies at a time. However, both of these solutions totally fail to work if the opponents are human players: being stunned a lot is no fun, nor is waiting for your turn to attack.
Another thing we tried to make the combat more dynamic, was adding a 'lunge' attack. This was a game mechanic where if you are in the air, you can press a button to home in on an enemy and kick him from above. This made it more useful to keep jumping and moving, but definitely didn't decrease the chaos.
We even experimented with letting teammates collide with each other, so that no two players could stand in the same spot. This turned out to feel very frustrating: your allies were now always standing in your way and sometimes you couldn't hit an enemy because a droid was standing in front of him already.
Several team-members really wanted to keep the melee mechanics in the game, but at some point our designers (Fabian and Jasper) got bold and simply removed all melee skills for one playtest. It turned out that this instantly fixed all these problems. Everyone keeps a little bit of distance from each other and you don't need to all stand in the same spot anymore to attack. Also, jumping became way more important, because you can evade bullets and aim at opponents at the same time!
This was one of the biggest breakthroughs in the design of Awesomenauts. The result was so convincing, that of the original six Awesomenauts, only Leon ended up with a melee skill. All the others turned ranged and it worked great!
Monday, 1 April 2013
Announcing Awesomenauts The Movie with a trailer!
We have just released this press release, figured I should share this awesome piece of news with you!
Today Ronimo Games announces that their massively successful platforming MOBA Awesomenauts is coming to Hollywood! Awesomenauts The Movie will be directed by the award-winning director G.G. Abrams. The announcement is celebrated with a teaser trailer:
Awesomenauts The Movie will be released in full 3D and will reach theaters around the globe this Fall. Joost van Dongen, co-founder of Ronimo Games, says "This movie is a dream come true. Plans for an Awesomenauts movie have been in development since we started working on the game, and now that the game has reached such huge success, we have finally been able to break into Hollywood and get the production of the movie started!"
Actors have not officially been announced yet, but rumours currently suggest several famous Hollywood actors might have enlisted to play the roles of Froggy G, Clunk and Sheriff Lonestar.
About Awesomenauts:
The downloadable game Awesomenauts is a unique combination of an action platformer and the MOBA genre (games similar to League of Legends and DotA). Awesomenauts was released on PS3, Xbox 360 and Steam in Summer 2012 and features lovingly crafted 2D graphics. It also happens to come with one of the best theme songs in the history of gaming.
About Ronimo Games:
Ronimo Games is the Dutch indie studio responsible for the downloadable hits Awesomenauts (Steam, PS3, Xbox360) and Swords & Soldiers (Wii, PS3, Steam, iOS, Android), which both won numerous awards.
Today Ronimo Games announces that their massively successful platforming MOBA Awesomenauts is coming to Hollywood! Awesomenauts The Movie will be directed by the award-winning director G.G. Abrams. The announcement is celebrated with a teaser trailer:
Awesomenauts The Movie will be released in full 3D and will reach theaters around the globe this Fall. Joost van Dongen, co-founder of Ronimo Games, says "This movie is a dream come true. Plans for an Awesomenauts movie have been in development since we started working on the game, and now that the game has reached such huge success, we have finally been able to break into Hollywood and get the production of the movie started!"
Actors have not officially been announced yet, but rumours currently suggest several famous Hollywood actors might have enlisted to play the roles of Froggy G, Clunk and Sheriff Lonestar.
About Awesomenauts:
The downloadable game Awesomenauts is a unique combination of an action platformer and the MOBA genre (games similar to League of Legends and DotA). Awesomenauts was released on PS3, Xbox 360 and Steam in Summer 2012 and features lovingly crafted 2D graphics. It also happens to come with one of the best theme songs in the history of gaming.
About Ronimo Games:
Ronimo Games is the Dutch indie studio responsible for the downloadable hits Awesomenauts (Steam, PS3, Xbox360) and Swords & Soldiers (Wii, PS3, Steam, iOS, Android), which both won numerous awards.