One of the things I hated most while developing Swords & Soldiers for the Wii, was the safe frame. CRT televisions (you know, those old, big televisions that some people still have) don't show the entire screen: they simply leave out the screen's edges. I don't know exactly why this is traditionally done, but the amount of screen that is left out varies per television and can be pretty large on some of the worst TVs.
Surprisingly, many modern LCD/LED/Plasma televisions are by default set to also leave out the edges. They just zoom in a bit. However, since there is no technical reason why this is, these televisions come with a setting to turn that irritating behaviour off.
Now the good thing, is that there is a limit to how much of the edges a television actually cuts off. The area that you can be sure will be shown on every television, is called the safe frame or safe area.
Since games need to be playable on any television, Xbox, Playstation and Wii all have requirements that the game should be playable even if everything outside the safe frame is cut off. So crucial information or interface elements can not be positioned outside the safe frame. It is of course a good thing that Microsoft, Sony and Nintendo force developers to make games that are playable for everyone, but this is pretty horrible for us as developers: usually you want the interface to be as far to the sides of the screen as possible to leave lots of playing field, but that is not possible any more.
Luckily for me, our art team had to deal with this and not me. So they moved the interface elements further from the edges of the screen. Now the total screen (as is seen on televisions that don't cut off the edges), looks like this:
Note that it actually takes quite a lot of time and effort to do this correctly: in our office we have no television that has the worst possible safe frame, so instead we made a paper frame to put in front of the screen and 'emulate' the worst possible safe frame. Everything needed to be tested with this piece of paper in front of the screen.
Moving the interface away from the edges works, but it is pretty limiting for interface design, and it is also irritating work. While making Swords & Soldiers, we thought we had to do this, but right after the game was done, we discovered that some games solve this in a much easier way. So easy, that at the time it almost felt like a trick.
So, to keep you, the reader, from spending a lot of time on the safe frame, here is the simple trick that our new game Awesomenauts and some other games use instead:
Allow the user to set the zoom of the screen.
That's it. In OpenGL and DirectX, you can just create smaller viewports and leave the borders of the screen black. So on televisions that cut off a lot of pixels at the borders, you just render the game to a smaller part of the screen. Everything outside that is black. As long as the user sets this correctly (which he is forced to do when he starts the game for the first time), everything will always be shown, so you can put your interface elements wherever you like.
The only real downside this solution has, is that the resolution of the game is now pretty much dynamic. So rendering pixel-precise effects becomes a bit more difficult now. On the other hand, it also has a hidden benefit: since you render to a smaller portion of the screen, people with CRT televisions might get a better framerate...
This really is a simple trick, but for those who didn't know it yet: be glad you do now! ^_^
Friday 27 January 2012
Friday 20 January 2012
Follow your heart, not your wallet!
Last November my game Proun won a Dutch Game Award for Best Original Game Design. When I received the award, I grabbed the microphone and did a short speech, which Control Magazine then asked me to write that into a column. Which I did! The Dutch version is currently on their website and in the magazine, and here is the English translation.
The Dutch games industry is doing really well. More developers than ever before! But still, if you look for truly special Dutch games, you will find painfully few. Testament to this is that at the last Dutch Game Awards, two student games and a hobby game were nominated for Best Original Game Design. Where are the companies? So many developers, so few people who create their own concepts. It's as if we have all become entrepeneurs, and left our passion and creativity at the door.
I think this is because many Dutch developers are afraid to follow their heart. With all these talented people, there must be so many good ideas floating around! Yet almost everyone is doing work for hire. Within budget, finished on time, a certain income. Hardly any creative freedom and everyone will have forgotten your game two months later.
Of course, there are exceptions. Just think about Ibb & Obb, Dinner Date, Super Crate Box, Killzone (yes, that one as well!), and of course our own Awesomenauts. And don't get me wrong: there is nothing wrong with doing work for hire. It is an important part of our industry and it is a good thing that we Dutch are as good at it as we are. But it has been taken a step too far: most developers seem to only care about a steady income.
And of course, building your own concepts also means more risk, and will fail once in a while. But I am certain that more truly special games would be born in the Netherlands, and more international success would follow!
Because truly great games are made from the heart, not from the wallet!
The Dutch games industry is doing really well. More developers than ever before! But still, if you look for truly special Dutch games, you will find painfully few. Testament to this is that at the last Dutch Game Awards, two student games and a hobby game were nominated for Best Original Game Design. Where are the companies? So many developers, so few people who create their own concepts. It's as if we have all become entrepeneurs, and left our passion and creativity at the door.
I think this is because many Dutch developers are afraid to follow their heart. With all these talented people, there must be so many good ideas floating around! Yet almost everyone is doing work for hire. Within budget, finished on time, a certain income. Hardly any creative freedom and everyone will have forgotten your game two months later.
Of course, there are exceptions. Just think about Ibb & Obb, Dinner Date, Super Crate Box, Killzone (yes, that one as well!), and of course our own Awesomenauts. And don't get me wrong: there is nothing wrong with doing work for hire. It is an important part of our industry and it is a good thing that we Dutch are as good at it as we are. But it has been taken a step too far: most developers seem to only care about a steady income.
And of course, building your own concepts also means more risk, and will fail once in a while. But I am certain that more truly special games would be born in the Netherlands, and more international success would follow!
Because truly great games are made from the heart, not from the wallet!
Friday 13 January 2012
The code of Awesomenauts' upgrade system
Last week I explained how our designers can create tons of upgrades for Awesomenauts using our Settings system. However, I didn't say a thing about how we actually made that work. We used some fun template and functor tricks there, so I figured it would be nice to show how it was built to work elegantly, without making our code a big mess of checks for upgrades.
Warning: this blogpost contains hardcore programming awesomeness! If you are an artist or game designer and fear templatised meta-programming functors might disintegrate your brains and/or explode your head, then I advice skipping this specific blogpost and coming back next week!
First lets have a look at how things would work without upgrades. Note that to keep things readable, I only show the essential bits of code, and I have greatly simplified all the code examples here.
The function loadSettings() translates from a variable name to a string, so that we can actually load the variable from a text-file. Doing this for every setting in the game is a bit cumbersome, but necessary because variable names in C++ are not real things and become simple memory addresses when the code is compiled. Some spot is needed where we have the variable name as a string in code, and I chose to put all of those in a single place in the function loadSettings(). I guess it might be possible to write a macro that does the same thing, but I don't know about that myself.
The key thing to notice here is how easy it is to use the settings in gameplay code, as can be seen in the function handleWalking(). We are going to add upgrades to this and out most important goal for that, is to keep the gameplay code this simple.
Since the upgrade system requires each setting to be able to have several upgrades and combine them, we switch the settings from a simple float or bool to a real class.
I want basically the same behaviour from floats, bools, strings and any other types that need to be upgradeable, so I used templates for this. Experienced programmers probably know what templates are, but for those who don't: in the code below the type T is left open and it can be interpreted as whatever we say it is. So we can make an UpgradeableSetting where T is a float, or where T is a bool, or something else. C++ can compile this code with any type we want it to.
The load() function fills baseValue and upgrades by looking for all the occurrences of the setting in the settings file.
The get() function returns the value that this setting has for the Character that is passed to it. The Character is needed here, because we need to check which upgrades he has and return a different value depending on that. Its code is rather simple, but seeing it might help understanding how this works:
Note that this code only handles upgrades that replace the standard value, so upgrades that are marked with @ in the settings file. For simplicity, I have left out upgrades with + (which add to the original value) that I discussed last week.
Now that we have this, we can make some slight modifications to our gameplay code to use the upgraded value:
This all works fine, but I am not all too happy with that function get(). Normally it would be perfect, but there are so many places in the gameplay code where settings are used, that I would rather not add get() to all of those.
Now C++ happens to have a nice solution for this. I rarely see it used outside STL, but it has an absolutely awesome name: "functor". I love that name! Got to be a Decepticon! Anyway, a functor is a construction where you can call an object as if it is a function. With a functor, our little class looks like this:
Now we can do the exact same gameplay code as before, but we can simply leave out the get call. For the rest, this code does the exact same stuff. Because we use the settings so often, this is a nice improvement.
Since we have so many settings in our game, typing the entire type every time is too much work, since that would be something like UpgradeableSetting every time. We simply solved this using typedefs. At Ronimo we normally try to avoid typedefs, because they hide the real type of a value and I would rather know exactly what I am dealing with. However, because there are thousands of settings, I consider this an exception and use typedefs anyway:
Now that we have this new class, let's have a look at the same code we had before, but now with the upgrade system added to it. Note how it has hardly changed, but can do so much more now!
So, that's it. It's just a little bit if code, but this makes the settings system way more powerful and flexible. It is definitely a great improvement to the RoniTech (the engine we created here at Ronimo Games and that we used to build Awesomenauts). In fact, its uses are so diverse that we also use it for many other things than the upgrades that the player can buy in the shop. So let's conclude this blogpost with this nice example of that:
Warning: this blogpost contains hardcore programming awesomeness! If you are an artist or game designer and fear templatised meta-programming functors might disintegrate your brains and/or explode your head, then I advice skipping this specific blogpost and coming back next week!
First lets have a look at how things would work without upgrades. Note that to keep things readable, I only show the essential bits of code, and I have greatly simplified all the code examples here.
The function loadSettings() translates from a variable name to a string, so that we can actually load the variable from a text-file. Doing this for every setting in the game is a bit cumbersome, but necessary because variable names in C++ are not real things and become simple memory addresses when the code is compiled. Some spot is needed where we have the variable name as a string in code, and I chose to put all of those in a single place in the function loadSettings(). I guess it might be possible to write a macro that does the same thing, but I don't know about that myself.
The key thing to notice here is how easy it is to use the settings in gameplay code, as can be seen in the function handleWalking(). We are going to add upgrades to this and out most important goal for that, is to keep the gameplay code this simple.
Since the upgrade system requires each setting to be able to have several upgrades and combine them, we switch the settings from a simple float or bool to a real class.
I want basically the same behaviour from floats, bools, strings and any other types that need to be upgradeable, so I used templates for this. Experienced programmers probably know what templates are, but for those who don't: in the code below the type T is left open and it can be interpreted as whatever we say it is. So we can make an UpgradeableSetting where T is a float, or where T is a bool, or something else. C++ can compile this code with any type we want it to.
The load() function fills baseValue and upgrades by looking for all the occurrences of the setting in the settings file.
The get() function returns the value that this setting has for the Character that is passed to it. The Character is needed here, because we need to check which upgrades he has and return a different value depending on that. Its code is rather simple, but seeing it might help understanding how this works:
Note that this code only handles upgrades that replace the standard value, so upgrades that are marked with @ in the settings file. For simplicity, I have left out upgrades with + (which add to the original value) that I discussed last week.
Now that we have this, we can make some slight modifications to our gameplay code to use the upgraded value:
This all works fine, but I am not all too happy with that function get(). Normally it would be perfect, but there are so many places in the gameplay code where settings are used, that I would rather not add get() to all of those.
Now C++ happens to have a nice solution for this. I rarely see it used outside STL, but it has an absolutely awesome name: "functor". I love that name! Got to be a Decepticon! Anyway, a functor is a construction where you can call an object as if it is a function. With a functor, our little class looks like this:
Now we can do the exact same gameplay code as before, but we can simply leave out the get call. For the rest, this code does the exact same stuff. Because we use the settings so often, this is a nice improvement.
Since we have so many settings in our game, typing the entire type every time is too much work, since that would be something like UpgradeableSetting
Now that we have this new class, let's have a look at the same code we had before, but now with the upgrade system added to it. Note how it has hardly changed, but can do so much more now!
So, that's it. It's just a little bit if code, but this makes the settings system way more powerful and flexible. It is definitely a great improvement to the RoniTech (the engine we created here at Ronimo Games and that we used to build Awesomenauts). In fact, its uses are so diverse that we also use it for many other things than the upgrades that the player can buy in the shop. So let's conclude this blogpost with this nice example of that:
Friday 6 January 2012
Building hundreds of upgrades for Awesomenauts
In Awesomenauts, players can buy hundreds of different upgrades. There are around 150 unique ones, and most have two or three upgrade levels, so in total there are probably around 300 upgrades in the game. We wanted our designers to be able to create those themselves, without any work from the programming team for specific upgrades. At the same time, we also wanted the upgrade system to be super flexible, so that the upgrades would be very diverse, and not just all be cooldown reductions and damage increases.
When we first started looking for a way to build this, I was really at a loss. How to add a flexible system for upgrades to our settings system? It took some time, but coding intern Daan and I came up with a system that is easy to use and so flexible, that we ended up not just using it for upgrades, but also for temporary boosts and areas with modified mechanics, like low-gravity areas.
The idea is that for every setting, our designers can create modified versions for when a character has certain upgrades. Each setting always has one base value. Then as many modified versions can be added as desired, simply by copying the setting and adding @ and the name of the upgrade.
The @ sign works for many things, but it has the problem that it is problematic to have different upgrades for the same setting: what should happen if you have both upgrades? So we also introduced the + sign, which means that that upgrade's value is added to the original value. This way several upgrades can influence the same value.
This system does not just allow for simple upgrades that upgrade a single value, but can also be used for more complex stuff. Especially since our designers can give a player a temporary upgrade when he presses a button. So let's say we want to create a skill that temporarily makes the player deal twice as much damage, but also make him half as fast and twice as big. A designer could simply use the name of a single upgrade to modify all of these values at the same time.
Of course, the more flexible and complex things get, the easier it is for our designers to mess up. We have had quite a few bugs where certain combinations of upgrades behaved in a different way than our designer intended, simply because they chose the wrong values. The plus side of these kinds of bugs is that our designers can fix them themselves, so as a programmer I am okay with that... ;)
The upgrade system also gives our artists a lot of flexibility. For example, if a bullet does more damage, our artists can upgrade its graphic and its explosion to use a different animation.
The upgrade system described in this blogpost looks pretty obvious to me now, but it definitely was a revelation to us when we came up with it two years ago, and I still think it is the most elegant solution we came up with for any problem at Ronimo Games so far (although I suppose this system is not unique and other RPGs probably use something very similar). It is incredibly flexible and really easy to use, and allows our game designers to make almost any upgrade they want. And the good thing is that it is not specific to any games, so anything we make with the Ronitech (our engine) will have this feature for our designers! ^_^
Next week, I'll explain the technical side of how we made this upgrade work in C++!
When we first started looking for a way to build this, I was really at a loss. How to add a flexible system for upgrades to our settings system? It took some time, but coding intern Daan and I came up with a system that is easy to use and so flexible, that we ended up not just using it for upgrades, but also for temporary boosts and areas with modified mechanics, like low-gravity areas.
The idea is that for every setting, our designers can create modified versions for when a character has certain upgrades. Each setting always has one base value. Then as many modified versions can be added as desired, simply by copying the setting and adding @ and the name of the upgrade.
The @ sign works for many things, but it has the problem that it is problematic to have different upgrades for the same setting: what should happen if you have both upgrades? So we also introduced the + sign, which means that that upgrade's value is added to the original value. This way several upgrades can influence the same value.
This system does not just allow for simple upgrades that upgrade a single value, but can also be used for more complex stuff. Especially since our designers can give a player a temporary upgrade when he presses a button. So let's say we want to create a skill that temporarily makes the player deal twice as much damage, but also make him half as fast and twice as big. A designer could simply use the name of a single upgrade to modify all of these values at the same time.
Of course, the more flexible and complex things get, the easier it is for our designers to mess up. We have had quite a few bugs where certain combinations of upgrades behaved in a different way than our designer intended, simply because they chose the wrong values. The plus side of these kinds of bugs is that our designers can fix them themselves, so as a programmer I am okay with that... ;)
The upgrade system also gives our artists a lot of flexibility. For example, if a bullet does more damage, our artists can upgrade its graphic and its explosion to use a different animation.
The upgrade system described in this blogpost looks pretty obvious to me now, but it definitely was a revelation to us when we came up with it two years ago, and I still think it is the most elegant solution we came up with for any problem at Ronimo Games so far (although I suppose this system is not unique and other RPGs probably use something very similar). It is incredibly flexible and really easy to use, and allows our game designers to make almost any upgrade they want. And the good thing is that it is not specific to any games, so anything we make with the Ronitech (our engine) will have this feature for our designers! ^_^
Next week, I'll explain the technical side of how we made this upgrade work in C++!
Subscribe to:
Posts (Atom)