tag:blogger.com,1999:blog-30643252145896495352024-03-28T06:52:16.882+01:00Joost's Dev BlogJoost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.comBlogger233125tag:blogger.com,1999:blog-3064325214589649535.post-23544863607669000762021-11-24T12:53:00.003+01:002021-11-24T14:47:03.492+01:00Neat tricks for modelling the Robo Maestro robot<p>Today I'd like to share some fun, slightly unconventional techniques I used to make the <a href="https://store.steampowered.com/app/1808490/Robo_Maestro/" target="_top">Robo Maestro</a> robot in Blender. I wanted shapes that are both smoothly curved and tight industrial. Hard surface modelling! I think it turned out well, so let's have a look at how it was made!</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="523" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgShRWsa1k_FKR5fB4dVeuOmMKEzEMz4g50h-Hywb-6H1zyBrfVnL1pl7Rb9Up8btCiukHvfAa5D_A9DFaE5vvTkci0rtyQMV6Hs7frC6vR7o6d3TqTsPLAHJ0uuqe87R1tPG3S3vLciU9j/s0/Robo+Maestro+model+-+1+Robot3D.jpg"/></div>
<p>The concept art I was going by is this rough sketch by Robin Keijzer, creator of the awesome point and click adventure Space Rescue (available on Steam, NSFW!). As you can see, all shapes are a combination of curves, straight lines and hard edges.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="281" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMMbEc0BTQ1JTPUTYl9f6_HgJ8J5uX3IgCBKCUVF7ta424JA_9BrS6Drxix8v8APPsrZIiF_MBOoD19ixHnhxcFznKF7dGln66N8A4EiY0rDKmqOMWn__RSLcbPP7DhjG70xrgfuWCO8Ej/s0/Robo+Maestro+model+-+2+Concept+art.jpg"/></div>
<p>Subdivision modelling is a great way of making these kinds of curves, but it's a bit cumbersome when you need hard edges and corners as well. The tip you usually see for getting hard edges is to add supporting geometry: extra vertices around hard edges.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="287" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPtYMqZS7vtd_Gc7y54Nm1spwPfw6l9iZsgQuYGzdHC6q_iQhWAFtvazCLZ4qBkgc_dPl-rdyBOaRihjAggjzajaX1-bMiqAvgvl90Q59X-RneLkoRXbOIRyJ76EMY9UEEZTQLY2hexeOd/s0/Robo+Maestro+model+-+3+Supporting+geometry.jpg"/></div>
<p>However, the more vertices you have, the harder it is to change the shapes: the model becomes unwieldy. Also, the fewer vertices, the smoother the curves you get. So I really really wanted to have as few vertices in the base model as possible for the best smooth curves.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="405" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPwnKKB5cRK7IkDZ551mGWcAg8W3iu-10SAYqUMujLpqeuhUkS64mOHdbqrE8y3vZAekbSmea4mqA957M4rg2eW-J_10bvi6jAM5eL3m62cx7a-y-1pPxHV9rSLXERrzwkY9nkO4RHX6rT/s0/Robo+Maestro+model+-+4+few+polygons.jpg"/></div>
<p>Here Blender comes to the rescue! It has a wonderful feature called "creases" that lets you mark edges that should not be smoothed by the subdivision modifier. This lets us combine hard edges and smooth curves with very few vertices in the base mesh. Very cool, very handy!</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="281" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeST7SmVM9yaUQ2LLinZYaUc1_5xJ_SCYvlll6qyqk7y_2j7eA8tGk65E7J-JA8-wot_MRtU3D7E5e58ZOFiaWzhbCGr-KLXX8D7ptY_Ep1JiYobq9aVvc0vqT2oMn04fC2kl1st4uzTGR/s0/Robo+Maestro+model+-+5+edge+crease.jpg"/></div>
<p>Here you can see just how few polygons the base mesh for the Robo Maestro has, and how smooth the curves are that that results in.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="281" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGg-aaFyK9Y_a_3Pv3n9i8DT7E4PXi1ddfne2vNyrHbyiZamtv-oBgxBxU5IGhJCIKCDi9M0iAZoV1fqocMIbAc84OqvKY-7l0tfvcmHST6P8i1AHRvQm7BPksNqiBvm-2XGzy-0kafrnG/s0/Robo+Maestro+model+-+6+smooth.jpg"/></div>
<p>However, 100% hard edges feels cheap and fake 3D. For high quality models, we want to slightly bevel the hard edges. Luckily, Blender can also provide this: we can simply add a Bevel modifier to do this automatically.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="281" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP6y5llQltV1AH8TxH_3jvQoIE-djqk1UG2ri9KRqTVREYTxZSPPa09ppieZxfnVe_JvJaf2p30jGaW1W2-vlhJZaDQwx3fVF0KsmK9ZY-CW3U4Qtq-r5DxGM2h9VVK1E3k1ncLiXZq-fi/s0/Robo+Maestro+model+-+7+Bevel.jpg"/></div>
<p>The bevel modifier by default is either one hard edge (still not perfect) or more edges. Adding more edges makes Auto Smooth kick in, which makes us lose a lot of the tightness. The "harden normals" option fixes this (by not using interpolated normals on the bevel edge).</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="281" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgubDgh0RnNsY9e68glQCUpB4F4oNLYWSAMukHCykSLht5Ri02wjLotihyphenhyphenRQvTsnAK8mtkCTTC4UrIn4IGjnquuDajVGG56Gzx9Ooz6JYLpbv_mD6CVTM7EIv86pds1nIw6rn1ShmWF41Vs/s0/Robo+Maestro+model+-+8+Harden+normals.jpg"/></div>
<p>The bevel modifier automatically looks for edges to smooth, but sometimes it gets it wrong. In such cases switch the "limit method" to "weight". Now we can mark edges that need a bevel in our base mesh, and we can even mark per edge how wide the bevel should be. Neat!</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="291" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9g0EfcIHZvqzrodseekyqF-pm6Qsbm5MHFvzQFz8VyhmM0wOf6Lq1CKH8QIRzTtvRAQFWupZh_FTjTJwzSPjrr0XyCbVP8074h8eCdFdTusSF2Iz9NrGol-5-GfNJ7ZkVJVphIiruQ5Lz/s0/Robo+Maestro+model+-+9+Bevel+weights.jpg"/></div>
<p>Being able to mark edges and vertices with special features that are used elsewhere is one of my favourite features in Blender. Besides "crease" (for subdivisions) and "bevel weight" there's also "seam" (for automatic UV mapping) and "sharp" (for smooth shading).</p>
<p>Combining these techniques I was able to create the Robo Maestro pretty quickly and still remain flexible until the last stages of modelling: Robin had some feedback on the shapes and I was able to change them very quickly because the base meshes have so few vertices.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="295" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghX7uF9Fc50t8sbN9bcQAoLoy_oYg1AomzfhROhuKQV2nrGcSSs0W0YKk9KGH_hrMlWp1KnjwBjCZbcLBK5mOcVp8ze_78S44AjY99CVdT5WDvmOzrLgeUmB8JT_630xfMsRTEgwGX8YMh/s0/Robo+Maestro+model+-+11+Differences.jpg"/></div>
<p>Finally, if you were wondering what this model is for: Robo Maestro is a procedural music toy that I'm developing for Steam. He even plays the actual notes with his fingers! Here's a little trailer that shows the concept. <a href="https://store.steampowered.com/app/1808490/Robo_Maestro/" target="_top">Wishlist Robo Maestro now on Steam</a>!</p>
<div class="separator" style="clear: both; text-align: center;"><p><iframe allowfullscreen="" height="305" src="https://www.youtube.com/embed/o_EUpL9ej7w" width="500" youtube-src-id="w-O885TrgMY"></iframe></p></div>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-66621779861069534972021-11-24T11:06:00.000+01:002021-11-24T11:06:12.058+01:00Robo Maestro is coming to Steam!<p>Play with music like never before! Robo Maestro is the 'game' I'm currently working on and it's a procedural music toy. Guide an endless stream of new music or make detailed tweaks in Editor Mode. Create songs, be inspired and share your creations. Robo Maestro is coming to Steam, add it to your wishlist <a href="https://store.steampowered.com/app/1808490/Robo_Maestro/" target="_top">here</a>!</p>
<p>Robo Maestro is a revolutionary new way of creating and experiencing music. You tell it what you want, and then the Maestro automatically generates music that fits that. Playing Robo Maestro requires no music knowledge at all: just have fun and hear what happens! Guide the Maestro and create awesome music together with it!</p>
<div class="separator" style="clear: both; text-align: center;"><p><iframe allowfullscreen="" height="305" src="https://www.youtube.com/embed/o_EUpL9ej7w" width="500" youtube-src-id="w-O885TrgMY"></iframe></p></div>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-8053867783246340232021-09-08T15:44:00.003+02:002021-09-08T18:23:25.291+02:00Where to get original ideas<div>Lots of games and game concepts are very similar, very derivative. Partially that's because people make more of what's successful, which is sound business. But partially it's also because of a lack of inspiration, or taking inspiration from the wrong sources.</div><div><br /></div><div>This is because most game creators get their inspiration from the same sources: other games, action comics, action movies and sci-fi/fantasy books. Thus many creators get the same ideas. To get truly original ideas, you shouldn't look at the same things as everyone else. </div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHOfKdG8ev9ecR7cCdV1lKO6CM5v0L_FB1A-Ih5O79ia8D2PsiRQ5VSFzd2gvE4ZBDIcUxBnMKx0o3ueCa10icNqxn4gPNCAXAhwAjDnOSYawrZPetyss-51FYu5IGUCrankKF63tTmpg4/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="318" data-original-width="500" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHOfKdG8ev9ecR7cCdV1lKO6CM5v0L_FB1A-Ih5O79ia8D2PsiRQ5VSFzd2gvE4ZBDIcUxBnMKx0o3ueCa10icNqxn4gPNCAXAhwAjDnOSYawrZPetyss-51FYu5IGUCrankKF63tTmpg4/w400-h255/image.png" width="400" /></a></div><br />What other things inspire you? Please share in the comments below!</div><div><br /></div><div>For me, modern art museums are the biggest source of inspiration, especially early 20th century stuff. I don't like it all, but it often triggers my creativity. For example, this painting by Kandinsky was the main source of inspiration for Proun at the time. </div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM8czddW2WLX0i3EWtiVhcRiSJq9DJ-jv-ExfO28A8fWWbzTwx_pUek4c54Al1i-BryUvg9UrpogUVXGRX8nIorYPWScbshzlYaYnUbyMQjkqbVIeilrff8g2sIQMT4wQWk2vIiiXNYAGs/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="824" data-original-width="1200" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM8czddW2WLX0i3EWtiVhcRiSJq9DJ-jv-ExfO28A8fWWbzTwx_pUek4c54Al1i-BryUvg9UrpogUVXGRX8nIorYPWScbshzlYaYnUbyMQjkqbVIeilrff8g2sIQMT4wQWk2vIiiXNYAGs/w400-h275/image.png" width="400" /></a></div><br />So let's play a little game. Look at the painting below, and try to imagine a game that looks like this. What would that play like?</div><div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOAoOhiyP3RLS4ZQKLn_r5sa3VKrC2HdiAizFUPd_nSuBEEhIMXV4evBCPMNrPBAhIyf2DGGbyTfIWMIDQe4rbPuMzsjn_Jb97NkH4UmDNmUlS7bIEN0AedKSB9D6TI2BYmZvNhxKc74WK/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="2048" data-original-width="1319" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOAoOhiyP3RLS4ZQKLn_r5sa3VKrC2HdiAizFUPd_nSuBEEhIMXV4evBCPMNrPBAhIyf2DGGbyTfIWMIDQe4rbPuMzsjn_Jb97NkH4UmDNmUlS7bIEN0AedKSB9D6TI2BYmZvNhxKc74WK/w413-h640/image.png" width="413" /></a></div><br />(This beautiful painting is by Ludek Tikovsky and was exhibited in castle Groeneveld.)</div><div><br /></div><div><i>Oh by the way, I'm trying a new format for my blogposts: super short and focussed on Twitter. I'll repost them here as well, as I'm doing now. Any thoughts on this new format, or tips?</i></div>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com2tag:blogger.com,1999:blog-3064325214589649535.post-53486293984116247412021-03-31T09:41:00.003+02:002021-04-07T22:12:58.416+02:00I’m leaving Ronimo, here’s why and what’s next<p>After 14 years at <a href="http://www.ronimo-games.com/" target="_top">Ronimo</a>, I’m leaving the company I co-founded. I’l keep making games, but starting this months it’s on my own (and in the future maybe I’ll start a new studio). This news makes me both very sad and very enthusiastic. Sad that I won’t be working with my amazing friends at Ronimo anymore; enthusiastic that I will have total creative freedom to make exactly what I want to make. Today I’d like to share why I’m leaving, and what I’ll be doing next.</p>
<p>The reason I’m leaving is that I want the creative freedom to carry out my own ideas. I have tons of concepts for games, music and art, but I can’t execute them at Ronimo. I might have had a leading role at Ronimo as technical director, producer and co-owner, but when it comes to creative choices, Ronimo is a pretty democratic company: everyone has input on creative choices. That’s great for the creative process: tons of ideas bubble up and stuff that a lot of people are enthusiastic about makes it into the games. However, with 7 founders and a dozen employees that means that my actual creative say wasn’t that large. Especially since Ronimo makes only one game every 3 years.</p>
<p>That used to be fine for me since I had a creative outlet in my spare time. I made <a href="http://www.proun-game.com/" target="_top">Proun</a>, <a href="http://www.cellofortress.com/" target="_top">Cello Fortress</a> and <a href="http://agelessgate.joostvandongen.com/" target="_top">The Ageless Gate</a> that way over the years. However, three years ago I became a dad and this has reduced my spare time a lot.</p>
<div class="separator" style="clear: both; text-align: center;"><p><img alt="" border="0" data-original-height="183" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiWca9_c5RX9O8YMaeD_MIXp3mDEDZiJK4XUtHr6McxU0aSvcmGkYbix4cYon0v3gKpPp283acVm-Jom1Wh6BD65c2PuMQx6Mp6KZlYasu4Bqlc1giGg_RgsN5SKLrnVtacuwf6Z7GwznL/s0/Leaving+Ronimo+-+Proun+and+Cello+Fortress.jpg"/><br />
<i>I solo developed Proun and Cello Fortress in my spare time, including code, design, music and 3D art.</i></p></div>
<p>The trigger for me to decide to leave Ronimo was a conversation with my wife, Marissa Delbressine. I always write down my ideas in my notebook. However, this became pretty depressing when I realised that I didn’t expect to be able to do anything with all those notes. So I said to Marissa: “I might as well not write down my ideas anymore, since it feels so useless if I can’t do anything with them.” This made her very sad, more than I had expected. Marissa is a creative person herself (she’s a comic artist, currently publishing <a href="https://www.webtoons.com/en/drama/the-shadow-prophet/episode-1/viewer?title_no=1881&episode_no=1" target="_top">The Shadow Prophet</a> on Webtoon) so she could imagine the pain of telling yourself not to be creative anymore.</p>
<p>Marissa’s response got me thinking: maybe instead of dropping my own ideas, I should quit Ronimo instead. But I also didn’t want to abandon my friends. So in Autumn 2019 I told the other founders of Ronimo that I wanted to leave, but that I wanted to first finish <a href="https://www.blightbound.com/" target="_top">Blightbound</a> with them. They were sad to see me leave and tried to convince me to stay, but they also supported me in wanting to follow my own path. Their response was heart-warming to me. After all these years the co-founders are still my friends, but I will see them a lot less now. I will miss them dearly, as well as the rest of my former colleagues at Ronimo.</p>
<div class="separator" style="clear: both; text-align: center;"><p><img alt="" border="0" data-original-height="290" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs6C85wbMutlYe5YFC1rzH_bXbfA4y4dEjZVn7PBPmPnhHJqTeSIfm89bxY_M9VaNdOdr5r5_t9LAmC-sbjeSiatbsB2l7uhTqgEU0-Ant2Qb8J-iAm4GrPh3P8ONh5O85pd9RMSv6xSjz/s0/Leaving+Ronimo+-+Founders.jpg"/><br />
<i>The 7 founders of Ronimo back in 2007, a few months after we founded the company. I'm on the left, lacking both a beard and grey hair back then.</i></p></div>
<p>Since people often leave their company because of frustrations or disagreements I would like to stress that that’s not the case here. I just want full creative freedom to explore my ideas, and that’s the only reason for my departure. I still love the folks at Ronimo and I plan to keep hanging out with them regularly (well, once the current pandemic dies down, I guess).</p>
<p>When I first talked about this with the other founders, we still thought I would be able to leave Ronimo in Summer 2020. But Blightbound got delayed and I decided to finish the game with the team. Then the game got delayed some more, and we agreed to set a final date, since I got restless as my departure kept moving. That date is now. As of this month I don’t actively work for Ronimo and I don’t have any management responsibilities anymore.</p>
<div class="separator" style="clear: both; text-align: center;"><p><img alt="" border="0" data-original-height="281" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqvrpiyolkdhyx_i5lVINQA3ZG8j3Ih4SCFLwUyCqt6dhS91LHD1xFHmlDSUwYBTz_k5gumVpi2ANsifBW6-xacwXn8-NeFcjDb_SoRApwVdxB9QM31GRJ13yYSwHDEfedzAHpd66SnS3a/s0/Leaving+Ronimo+-+Blightbound.jpg"/><br />
<i>Blightbound, which is currently in <a href="https://store.steampowered.com/app/1263070/Blightbound/" target="_top">Early Access on Steam</a>.</i></p></div>
<p>So, what will I be doing next? I mentioned I had tons of ideas, so I won’t be spending any time brainstorming or soul-searching. Instead, I’ve started already. My plan is to spend the next year learning new tech and skills and doing a bunch of smaller projects. After that I want to start making a bigger game that will hopefully be the start of a new studio.</p>
<p>I’ve already taken the first step last week: I’ve finally released my album <a href="http://agelessgate.joostvandongen.com/" target="_top">The Ageless Gate</a>. I’ve been working on this album for years and it’s great to finally get it out there. It’s available on all the streaming
services, with links to all of them <a href="http://agelessgate.joostvandongen.com/" target="_top">here</a>. The Ageless Gate is an instrumental concept album with lots of cello and a narrator that tells an overarching story in short fragments at the starts of the songs. It’s quite a unique thing and I hope it will find an audience!</p>
<div class="separator" style="clear: both; text-align: center;"><p><iframe allowfullscreen="" height="305" src="https://www.youtube.com/embed/w-O885TrgMY" width="500" youtube-src-id="w-O885TrgMY"></iframe><br /><i>Here's a preview of Sandrider, an intense cello trio and the opening song of <a href="http://agelessgate.joostvandongen.com/" target="_top">The Ageless Gate</a>.</i></p></div>
<p>As for the coming year, for now these are the smaller projects I intend to do:</p>
<ul><li>Finish the Steam version of Cello Fortress. This should become playable with any musical instrument (instead of just cello) and won’t require an audience to play against anymore.</li>
<li>I’ll apply for a government grant to experiment with my procedural music system and to turn that into a streaming radio station.</li>
<li>Make a minimalist railroad building game.</li>
<li>Make a crowd physics puzzle game with ballet and monsters, inspired by the art of the Dufy brothers.</li></ul>
<p>I also intend to learn a lot of new stuff. The main big things will be switching to Unreal Engine and Blender and learning the ins and outs of both. I also plan to expand my knowledge of UI design, design of management games and economies, task-based multithreaded programming and data-oriented code.</p>
<p>Then later on I hope to start working on a bigger 3D management/building game. I have a bunch of concepts for such games lying around and I currently tend towards one of the sci-fi ideas. I hope to build a bigger studio around this, focussing on high-quality 3D management games, similar in production value to games like Frostpunk, Planet Coaster and Two Point Hospital. I hope I’ll be ready to start pitching to investors with that in a few years.</p>
<p>It will undoubtedly take quite a while before all of these plans start making me a decent income. However, I’ve always been rather frugal, so I’ve collected enough savings that I can survive on those for long enough.</p>
<p>One thing you can see here is that I plan to do a LOT. Way too much, probably. I think this is going to be my biggest challenge from now on: keeping the scope of my projects small and limiting my expectations of how much I can do in a week. For years I’ve bottled up so many ideas and plans that I want too much too fast now. I’ve noticed that I’m already experiencing some stress because of how much I want to do, so keeping my plans realistic and doable in a chill manner is going to be my biggest challenge.</p>
<p>A clear split between work and leisure is going to be paramount to that, since up until now my hobby projects were my leisure. Now that they’ve become my work, I should make sure to not become a gamedev monomaniac. I’m sure my wife and son will help keep me grounded though, so I expect this will turn out fine.</p>
<p>I would like to conclude by thanking all my friends at Ronimo for 14 years of great fun. Thanks for everything I’ve learned from you and thanks for sharing all the lows and highs of making games together. I’m sure I will miss the banter and the laughter at the office most!</p>
<div class="separator" style="clear: both; text-align: center;"><p><img alt="" border="0" data-original-height="1294" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGTP1aHXAnFdo4LDnV3h-YX6SwyWMP0UNmy49REdb13ZJqs_ID1xMpdUt5Yr-n8So2CZM6D5SvM_nM4F69BBJikT5eAYPFrI5o3zBeHXTlStomz524Kd6Fa__d3JN6r_i1zl0S-NoS-Z7y/s0/Leaving+Ronimo+-+Joost+door+Ronimo+artists.jpg"/><br />
<i>On my last day at Ronimo, the art team chose </i>me<i> as the theme for their biweekly sketching session. I love the resulting portraits! Art by, from top to bottom: Gijs Witkamp, Koen Gabriels, Ella Kremer and Gijs Hermans.</i></p></div>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com19tag:blogger.com,1999:blog-3064325214589649535.post-41225961689298844722021-03-28T21:07:00.007+02:002021-03-28T21:09:32.772+02:00The Ageless Gate is OUT NOW!<p>On Friday I released my album <a href="http://agelessgate.joostvandongen.com/" target="_top">The Ageless Gate</a>! It's my atmospheric debut album with instrumental music and lots of cello. Together, the 13 songs tell a tale that spans three centuries, starting with a mysterious artefact and culminating in a gate to another world. The story is told by short text pieces in between the songs, voiced by voice actor Chris Einspahr.</p>
<p>The album is available on all the major streaming services (Spotify, Apple, Amazon, Tidal, Deezer, etc.). I've also made a deluxe CD edition in a limited pressing. Links to the different places where you can listen to the album can be found here:</p>
<h2><a href="http://agelessgate.joostvandongen.com/" target="_top">Click here to listen to The Ageless Gate</a></h2>
<div class="separator" style="clear: both; text-align: center;"><p><img alt="" border="0" data-original-height="498" data-original-width="498" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIFYp1w2Q4fyQCE2ti04Bli4I2h1eplbK_T80CEc955mEDGIttu8f5tdCR8oXMBHkYfi-L39Bnsi0wrWiGot2iYEM8sRDD3kYfrBr9u8NKWYNkt10ywdG2jM_fUA5gBrL4k6v5s769vO0B/s0/The+Ageless+Gate+-+Cover.jpg"/><br />
<i>For the cover of the album I combined a cello bridge with a sci-fi portal, bringing together the musical core (cello) and the storytelling theme of the album.</i></p></div>
<p>My cello is the foundation of the album, which varies from cello trios to songs with cello, drums, guitar and keyboard. The sound goes from melodic and euphoric to dark, pumping cello rhythms. Cello is mostly known as a classical instrument and a background instrument, but it’s so much more than that. For this album I really enjoyed experimenting and exploring the possibilities of the instrument. My favourite examples of that are the fast arpeggios in the opening track Sandrider, and the gliding chaos tones in Approach of the Derelict Research Station.</p>
<div class="separator" style="clear: both; text-align: center;"><p><iframe allowfullscreen="" height="305" src="https://www.youtube.com/embed/w-O885TrgMY" width="500" youtube-src-id="w-O885TrgMY"></iframe><br /><i>Here's a preview of Sandrider, an intense cello trio and the opening song of The Ageless Gate. The image shows the CD edition of the album, which can be ordered <a href="http://agelessgate.joostvandongen.com/" target="_top">here</a>.</i></p></div>
<p>I've worked on my album for 3.5 years and it's great to finally have a complete thing, with the storyteller, the art, the music and the production all working together to create one coherent whole. It started out as just a bunch of songs, but as I wrote more of them I realised they could be telling an overarching story. From that point on I started writing that story and also changing some of the compositions to make them work in the bigger whole. For example, A Century Flies By and A Century Sails By started out as one song, and I split them into two short related pieces since I liked them as bookends in between the chapters, marking the passage of time.</p>
<div class="separator" style="clear: both; text-align: center;"><p><img alt="" border="0" data-original-height="443" data-original-width="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEHFnWBtQg0TwHlJbTfBWsngKYCOQkCfWzhCV7tG3IYffrefDIXbvF-g-rZLhVmK7yaqwdOZSc9Fmm10AXbghmWWszS9xIV8LFzAou622_Qiy49GIAirCzyw9gBuZbnNJv1V0SXYj9Sfk3/s0/The+Ageless+Gate+-+Songlist.jpg"/><br />
<i>The story plays out in different time periods, as is seen on the back of the CD edition of The Ageless Gate.</i></p></div>
<p>While working on the album I learned a lot about composition, recording and music production. One of the biggest lessons I learned is that it's pretty doable to record a bunch of cello takes and then cut them in pieces to combine the best bits. This helps me a lot in achieving a consistent high quality cello recording. Before I knew this I thought I needed to record an entire song without any mistakes and this made me super nervous during recordings. Now I know that recordings with mistakes are useable, as long as the mistakes aren't always in the same spot.</p>
<p>My other big lesson is that mixing/mastering is such a specialised field that I should again hire a professional for that. I first tried doing it myself, but even after spending considerable time with tutorials and experimentation, I couldn't get it to sound pro. In the end I hired <a href="https://tremor.studio/" target="_top">Daan Kandelaars (Tremor.Studio)</a>, a professional mixing/mastering specialist, and his versions sound so much better than my own did. For my next album I won't first try to make final mixes myself and will instead hire a pro for mixing and mastering right away.</p>
<p>All in all I'm super happy with the final result and I hope others will like The Ageless Gate too! I'd love to hear if you have any favourite moments on the album!</p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com2tag:blogger.com,1999:blog-3064325214589649535.post-27506809842141889222021-03-17T14:41:00.009+01:002021-03-17T20:23:15.711+01:00Super flexible 2D animations through the Blightbound Skin Editor<p>Last week I discussed how we used After Effects and Duik as our animation tools for <a href="https://www.blightbound.com/" target="_top">Blightbound</a>, achieving crisp animations at high framerates with small filesizes and nice tools for our animators. The real strength of this workflow however comes from our Skin Editor. This makes it possible to reuse animations, quickly tweak the looks of characters, swap gear, add special effects and attach objects to characters convincingly. Today I’d like to explain the ideas behind our Skin Editor and how this impacted the work of our artists.</p>
<p>As I showed in <a href="http://joostdevblog.blogspot.com/2021/03/finding-suitable-tool-for-animating.html">last week’s blogpost</a>, the basic idea behind animations in Blightbound is that a character is made up of parts (hands, torso, face, upper arms, lower arms, etc.). These parts move and rotate and the game plays that back directly, instead of using sprite sheets.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="291" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6Lsh_bfHjK7zl_1gTjhsjIhMFIDZByHQD5jmmUSCOg6gIb9LaAtw68QTsgCM09R-Oay5Xeo_F3ciJ-Mb3C-H48qo6Ye86xdl6dAk6bpB8XgKbh3rWjuSSvSL6zmWTW0iCd8JI5jYxQ2c1/s0/Skin+editor+-+Character+and+parts.jpg"/><br />
<i>Characters in Blightbound are animated using parts, and frame-to-frame variations on those parts. This shows some of the parts used in the animations of Malborys.</i></div></p>
<p>Since the game knows exactly what parts there are and where they are, there are a lot of fun things we can do with this besides simply playing back animations. How cool would it be to swap parts to create new characters, to swap weapons, to attach special effects to weapons and to attach effect-over-time animations to bodyparts? To achieve all of these things our artists made sure all characters have a similar structure, and I developed our Skin Editor.</p>
<p>The basic idea behind our Skin Editor is that it finds all the visible parts in all the animations for a rig and allows changing or hiding them. So a skin can change whatever it wants: a character’s head, weapon, shoulder, or even everything. When an animation is played back in-game, we inform it which skins are active and those are applied to modify the character’s looks during gameplay.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="305" src="https://www.youtube.com/embed/nJ7_hatND4Y" width="500" youtube-src-id="nJ7_hatND4Y"></iframe><br /><i>A demonstration of the interface and the various features of the Blightbound skin editor.</i></div></p>
<p>Skins allow us to create a new character by drawing new parts, without needing to create any new animations. This was an important goal for us, because for Blightbound we wanted quite a lot of characters. A core idea behind the game is that it should be a bit like Pokémon: gotta catch em all. There are a lot of playable heroes and the player collects those during gameplay. However, for <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a> it took us 8 years to get to 34 characters and here we needed more animations per character <i>and</i> more characters (enemies included). So the Awesomenauts workflow wasn’t going to work and we needed to apply more reuse instead. The Skin Editor made this possible.</p>
<p>Note that above I said we apply skin<i>s</i>, plural. Our skin system allows combining several skins, as well as changing which skins are active on the fly. A skin can add parts, but it can also remove or replace parts from the skin below it. This is pretty cool, because it allows us to do all kinds of cool things. For example, weapons are skins, so swapping a weapon means swapping a skin while keeping the base body skin the same.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="257" data-original-width="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOD3cKOjsogZDFaamze_lAWjchMVbISUFkj-acRM3bSilIIVqVLnq3xmzZOeEg18oKCjIy10S4odewf0LSwED_x6IuYYx0VFxCHFeRW9srRxm6eOda4QmDhFH3xvY7HUzDoD0-NkZiXNil/s0/Skin+editor+-+Swapping+weapons.gif"/><br />
<i>Weapons and shields are easily swapped by enabling and disabling additional skins.</i></div></p>
<p>Weapons are an obvious application of this, but we can do more outlandish stuff with this. If an enemy gets hit by a knife that applies a <i>bleed</i> effect (damage over time), then we would like to have an effect on the enemy for the duration of the bleed effect. In Awesomenauts we were heavily limited in these kinds of effects because the sprite sheet didn’t tell us where any of the limbs or feet of the character were. This meant status effects needed to be visualised with animations that are always centered on the character. In Blightbound we can do much better: we can have a knife sticking our of a leg, and the knife will move correctly with the leg. All it takes is adding a skin to the enemy that contains that knife.</p>
<p>Normally we put textures in skins, mostly body parts and clothing and weapons and such. But we also have a feature to attach <i>any</i> in-engine animation to a skin. This allows us to do things like adding sparkly particles to a staff, dripping blood to the knife, glows to the shackles, <a href="http://joostdevblog.blogspot.com/2016/09/creating-crisper-special-effects-with.html">trails</a>, and even physics capes. We also use this to attach gameplay dummies to skins, for example to make sure projectiles come out of the tip of the staff, no matter where that staff is in the current animation.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="195" data-original-width="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTEU29Av__iVhRsVVQDVp2srLdCgQ6nVVuhiQAcwi9zx1YFt_8j1o4eAFozPMTcZR2tu8nIhm2g-EZmLRNBr6_c968LjL2KPh75Jz7AX6bufcNeLujx7Go_3TdSixfNJ7yuIa6I7STFB0b/s0/Skin+editor+-+Slow+effect.gif"/><br />
<i>The skin system allows us to accurately attach visuals for status effects to the animation. Here the slow effect attaches to the legs. Also, the cape is a nice example of attaching a physics object to the character.</i></div></p>
<p>A fun but mostly unused feature I implemented is the scaling of parts. Skins can not just replace parts, but also change their size. We hoped we could use this to change a character’s silhouette, for example by giving one character longer arms and shorter legs. This feature also allows making all heads bigger (which is a common Easter egg in many games, but we didn’t add it to Blightbound).<p>
<p>While scaling worked fine from a technical perspective, in practice it was hard to make good looking characters this way so our artists ended up hardly using that feature. Also, a more complete implementation of limb scaling requires animation retargeting (for example to keep feet firmly on the ground when the ratio between upper and lower legs is changed), which is some pretty advanced tech that we didn’t have time to dive into.</p>
<p>So far it might seem like just having that skin editor enables all of these cool features. However, to make this work, all animations need to have consistent elements. For example, if we want to attach that knife to that underarm, then each animation that the character can play needs to have an underarm and it always needs to have the same name. In some cases we worked around this by adding empty visual parts to the rig, so that any characters that needed those parts could enable them. This is somewhat similar to adding attachment dummies to a skeleton in 3D animation.</p>
<p>Also, if we want to quickly reskin a character, then we should limit how many unique parts there are. In my previous post I mentioned that we do frame-to-frame animation on parts, for example by drawing several heads with different expressions. For every new character we add on this rig, we need to draw all of those heads. The larger the number of parts, the more work it is to add a new character that replaces all of those parts.</p>
<p>There are some tricks that we used to decrease the workload. For starters, our skinning system falls back to the default if variations don’t exist. If for example one character has a mask, then we don’t need to make copies of that mask for different facial expressions. If a character is less important then we can also just choose to not draw the facial expressions for that character, even if they wouldn’t be hidden by a mask.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="209" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnkKj49a3di63NaT1NHX9XEIv-eJfiK8DqxNC4Z0TSXrc6ZNAHKPWEytDLNp_bFMbbo0H3j6_sCtXlfJqd0_7rn90zqtCo8G0vc0dv6ROsZGEG3qzGe2cWYiwMcIaCrX3qHnPRjbHb-oDX/s0/Skin+editor+-+Heads.jpg"/><br />
<i>For each character we need to draw all the parts used in all their animations. For four characters in Blightbound this shows all the heads needed for the female rig. Note that some characters have one head fewer. That's okay because in such cases our skin system automatically falls back to the default.</i></div></p>
<p>Another thing we used is that not all characters use all animations. Enemies for example share some animations with heroes, but their animation set is a lot smaller. Enemies therefore only need to have the parts that are actually used in their animation set. For this same reason our animators had a lot more flexibility in adding parts whenever they made a character-specific animation: none of the other characters need to have those parts.</p>
<p>By carefully choosing which parts and variations are really needed, our artists managed to keep it all doable. Still, in total Blightbound currently has over 4,600 character parts. Together these form around 50 characters (players and enemies), 104 weapons and 45 shields.</p>
<p>This did require a lot of experimenting with exactly how a body is made up. While the basic parts may seem straightforward, there are a lot of subtle choices to be made. For example, feet are split in the front part (including the toes) and the back part, and the pelvis and torso are split. Also, some parts are in the rig twice: once in the front and once in the back, for more clothing possibilities.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="496" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE13o1x30q5UAh0o9x4eOVer-Ko5YkcqGiIdRKx7KbFXuqcEBs-bBcOQuJGZlfOb9o17XmFdQJ1bwOEAdpqaggHazrwrp-aG7dkXLWroFLelO-ehY0kdiLDHPHx-nJe8Uat9CSQvJk7B44/s0/Skin+editor+-+Specific+parts.jpg"/><br />
<i>Our artists spent a lot of time figuring out exactly how the rig should be split into parts to be able to do a lot of poses and clothing variations without introducing too many parts. For example, here we see that the belt is split into 3 parts and there are "waistflaps" in the rig.</i></div></p>
<p>This brings us to the biggest downside of this approach: it adds a <i>lot</i> of limitations to what our animators can do. For each animation they need to creatively reuse the existing parts as much as possible. They can add new parts when it’s really needed, but they need to be very conservative with this to avoid bloating the workload. The result is that animations are a bit less dynamic that in Awesomenauts and <a href="http://www.swordsandsoldiers2.com/" target="_top">Swords & Soldiers 2</a>. Also, our artists generally did not enjoy the extra challenge of these limitations.</p>
<p>Another downside is that reusing animations makes characters a lot more similar visually, and limits what we can do in terms of body types. Our artists did go out of their way to make the characters as visually unique as possible within the limitations of the rig, for example by adding variation through extreme headgear, capes and clothing.</p>
<p>To make characters feel more unique, our artists have made select unique animations for each hero. Especially the idle animations are different, but in some cases also the walk animations. That’s one of the nice things of reuse: during development you quickly have a full character in the game with all animations, and then later on you can replace specific animations to make them more unique.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="218" data-original-width="355" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjZCs1wlLcW7G9XFFmj4h-0l_WfqQO4mwpzNToZdPHWIR2yLrjM5OOiFZUslT2ZEMyjAso7DuTySLOAj3i_98juasf1glLdmEAam0AfVzfi8peYm_xHXoezXqXPNPaS3d0uaY88vdbj3I_/s0/Skin+editor+-+Unique+idles.gif"/><br />
<i>To make characters that use the same rig less samey, most have a unique idle animation.</i></div></p>
<p>Animation reuse is also great for prototyping: if for example a designer wants to try swapping skills around between enemies, they get an animation set for free to get a better idea of what gameplay feel that will have. In Awesomenauts on the other hand that often required an artist to make some extra concept frames for skill visualisation.</p>
<p>Before I finish this blogpost I would like to point out that the Skin Editor and the limitations we applied to be able to reuse animations are not necessary when using After Effects and Duik for animations. It’s perfectly possible to let go of all of those limitations and still get all the benefits that I discussed in <a href="http://joostdevblog.blogspot.com/2021/03/finding-suitable-tool-for-animating.html">last week’s blogpost</a>. In fact, our After Effects exporter is technically capable of exporting Awesomenauts characters without using sprite sheets.</p>
<p>Despite the downsides, the scope of Blightbound would not have been doable for us without the approach we used. The combination of the Skin Editor and the consistent body setup that our artists applied to all animations made a lot of cool things possible for Blightbound. We were able to make more characters then we could otherwise have, create swappable gear, add special effects to weapons and attach animations to body parts. In total, I think the result is pretty spectacular. Also, playing around with the Skin Editor is just plain fun!</p>
<p>To conclude, here’s a video that shows what happens when you repeatedly randomise all parts of a character:</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="375" src="https://www.youtube.com/embed/x0rMzeT1ZoA" width="500" youtube-src-id="x0rMzeT1ZoA"></iframe><br /><i>The Blightbound dev tools contain a feature to randomise skins. The results look both horrible and hilarious.</i></div></p>
<i>Special thanks to Ronimo artists Koen Gabriels, Tim Scheel and Gijs Hermans for providing feedback on this article.</i>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com4tag:blogger.com,1999:blog-3064325214589649535.post-28776019107666681342021-03-13T14:17:00.003+01:002021-03-17T15:53:01.131+01:00New song: The Remains of the Mountain<p>Here's my newest song! It's an atmospheric piece, more ambiance than real song. I think the atmosphere is pretty strong on this one, I hope you like it!</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/OeJrro8np1c" width="500" youtube-src-id="OeJrro8np1c"></iframe><br /><i>Visit <a href="http://music.joostvandongen.com/" target="_top">music.joostvandongen.com</a> for an MP3 download of this song.</i></div></p>
<p>This song is actually an improvisation I recorded back in 2014. It's four layers of cello and one layer of... a pan's metal lid! Because why not.</p>
<p>Back in 2014 I liked the result, but it was too rough to use. I didn't think I'd manage to capture the same feel if I were to extensively practice the piece and record it again, so I abandoned this piece. Since then I've learned a lot more about editing recordings and fixing issues. Especially, I recently bought Melodyne, which is a great tool for fixing incorrect pitch and timing in recordings. With this I managed to get this song to a point where I'm actually happy with the result.</p>
<p>Also, here's a little bit of advanced music theory that I applied in this song. This song contains a bunch of very long chords without any vibrato, so the exact pitch of the chords is very audible. The opening chord for example is a major third. If you make that pitch perfect for modern tuning, the chord is actually slightly out of tune. I explained that years ago in <a href="http://joostdevblog.blogspot.com/2014/08/the-gross-imperfections-of-tuning-in.html">this blogpost</a>, but I had never gotten around to actually applying that knowledge. Now, using Melodyne's precise pitch control, I finally could. I've pitched the top note of the opening chord slightly lower than it would be on a piano, given the major third chord just intonation (also called "pure intonation"). While it's possible to play like that right way, my cello skills aren't good enough to control the pitch I'm playing that precisely in a recording.</p>
<p>Similarly, the minor thirds, fifths and major sixths in this song are also just intonation. Unfortunately Melodyne couldn't figure out some of the chords, so I couldn't apply it everywhere.</p>
<p>Oh, now that I'm talking music: my album is coming out in just two weeks! It will release on streaming platforms (Spotify, YouTube and others), and I'll also sell it on CD, including a bonus disc without the narrator. Send an email to <a href="mailto:joost@joostvandongen.com">joost@joostvandongen.com</a> if you'd like to buy a physical copy. It doesn't contain The Remains of the Mountain, but it does contain 47 minutes of other awesome cello pieces I composed. I'm really looking forward to finally sharing it with the world!</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="300" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgj4nGZJiWhYBkuindv9vPNCzbVRhnQwbD3IB8Dv2OOxP7IAhgCnsce6zaIqIBFWJfBYn6FrTUurpJy0n71JjcWhDDX9jZlYMuDy3hHj8TAR9-BVXcGvxdqyRx82pJWeKBSV5VS_vZxKtMR/s0/The+Remains+of+the+Mountain+-+Album+photo.jpg"/><br />
<i>The CD edition of my album contains a 16 pages booklet with art by Marissa Delbressine, and a bonus disc with a version of the album without the narrator (so purely instrumental).</i></div></p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com1tag:blogger.com,1999:blog-3064325214589649535.post-77492236828357417202021-03-10T15:02:00.004+01:002021-03-12T09:53:21.573+01:00Finding a suitable toolchain for animating Blightbound’s 2D characters<p>For <a href="https://www.blightbound.com/" target="_top">Blightbound</a> our technical ambitions for the 2D animation system were quite lofty: we wanted high quality animation, screen-filling bosses, crisp character art, high framerate and swappable gear. This required a complete rework of our animation pipeline, since the sprite sheets we used in <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a> and <a href="http://www.swordsandsoldiers2.com/" target="_top">Swords & Soldiers 2</a> allow for none of those requirements, except for high quality animations. In today’s blogpost I’d like to explain the problems we faced, and what combination of tools we chose to solve them. This is the first half of a two-parter: next week I’ll discuss our skin editor and its implications on animation.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="289" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggjj65g7EnbolQXag_yXHge1dAbsTfMCZ52EyinK2BsOit93RG416mXSezU4WqtUlVh1-IZweNkqr43A8H1RJKclFNTvTuosum2qElOtPsUqO438fnHF8dAm9yZfXvQcgCEVnnLzA_peTb/s0/Blightbound+animation+tools+-+Huge+boss.jpg"/><br />
<i>Blightbound features huge screen-filling bosses that need to animate smoothly without taking up insane amounts of memory.</i></div></p>
<p>Traditionally 2D animation in games is done using sprite sheets. A sprite sheet is simply a big texture with all the frames for all a character’s animations in it. Sprite sheets aren’t limited to just character animation: they can also store other things, like special effects or plants. The frames might be in a grid, or spaced more efficiently like we did for Awesomenauts. In any case, it’s just a series of tightly packed images.</p>
<p>Sprite sheets are great because they allow for complete freedom. The animator can draw anything they like and it will just work. Extreme squash-and-stretch? Perspective changes? Morphs? Do as you please, to the game it’s all just images!</p>
<p>However, sprite sheets come with a few huge downsides. First is size. If you have a big character and want it to be crisp and high-resolution, then each frame is going to take up a lot of space. Having lots of large images is going to cost too much memory. In Awesomenauts this was indeed a problem for some of the characters. For Clunk to fit in one 4096*4096 sprite sheet (the maximum we chose for memory and compatibility reasons), we had to either lower the resolution a bit, or reduce the framerate. And that’s not even that big of a character! The high memory usage of sprite sheets means that screen-filling bosses either can’t be done, or need to have very few frames, or can’t be crisp.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="510" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8Xh7TnlpPTOxfm7yxbUMzduS_u4Pph9VxlInRgcGS6FQs-LLtn5zVprcYmfwNE6sMZeJlEi5KAlpEipxxgtvaSMVP8pCcGxA6tX58C83No8wjcWfLO2oYArItf6_cd-gfM31LSwQ_cWh2/s0/Blightbound+animation+tools+-+Clunk.jpg"/><br />
<i>In Awesomenauts, red Clunk occupies an entire 4k sprite sheet texture for all his animation frames. Clunk fit only after slightly downsizing him.</i></div></p>
<p>The second major downside of sprite sheets is that since it’s just images, it’s very hard to do anything with them except simply showing them. For Awesomenauts we’ve often talked about letting players customise characters by changing for example their hat or other parts, but simple sprite sheets make that incredibly hard. The engine would need to know where the hat is exactly, but the sprite sheet doesn’t contain that information. Nor does it tell us whether there are different perspectives of the hat in different frames, or whether anything is ever in front of or behind the hat.</p>
<p>I can think of some workarounds for this problem, but it’s all so cumbersome that’s it’s not practical to actually do. This is the main reason why Awesomenauts only contains skins that swap the entire look of a character, and no swappable hats or clothing: those would be completely new sprite sheets for each combination.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="500" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXoVqxtObm22pKAYWPj5U121lb9KKYqtCUx7EJWs48p3d7wuNrOYZEL3QB1Be1cdytcj48Gl7PCAkzoBhDiPt1y1Ugd6zqlvxOktkWL91f1Hucuv1NnnPlPHhyphenhyphenpTjUQbsYbDFTNmEsb8Rp/s0/Blightbound+animation+tools+-+Awesomenauts+skins.jpg"/><br />
<i>Since every skin change in Awesomenauts requires an entire new sprite sheet we decided to make full reskins instead of allowing the user to customise individual parts (like hats or weapons). These are the four looks for Ted McPain.</i></div></p>
<p>So, sprite sheets can’t give us four of our requirements (screen-filling bosses, crisp character art, high animation framerate and swappable items). What can we do instead? The obvious direction for a solution is to split a character in parts, and let those parts move relative to each other. Or even to go for full skeletal animation.</p>
<p>If you have a background in 3D animation, you might think “<i>well skeletal animation of course, it’s awesome!</i>” And in 3D it is indeed, but in 2D it’s a lot more limited. Because we’re restricted to the 2D plane, there’s a lot of animation that can’t be done with a standard skeleton in 2D. Rotating the head of the character away from the camera is super easy in 3D, but impossible with 2D skeletal animation. Swinging a sword vertically is easy, but horizontally is very hard because that requires 3D perspective. Wanting to circumvent these limitations, we opted for a combination of 2D skeletal animation and traditional frame-to-frame animation on parts where needed.</p>
<p>A common tool for doing part-based 2D animation is <a href="http://esotericsoftware.com/" target="_top">Spine</a>. Spine is used by a lot of games and we expected this to be our best option. We tried Spine and it was indeed quick and easy to use, as well as easy to integrate into our own engine. However, it turned out to be a bit <i>too</i> simple: Spine doesn’t allow swapping a part in the middle of an animation. This is needed if you want to mix skeletal animation with frame-to-frame animation, for example by switching to a different drawing of a head or hand. The workaround was to layer several skeletons on top of each other, but that was too clunky to work with. We reached out to Spine at the time, explaining this issue, and they confirmed this was the only way. Our evaluation was three years ago and we haven't tried Spine since, but according to <a href="http://esotericsoftware.com/blog/Rigging-new-poses-tutorial" target="_top">this post by them</a> their options for combining frame-to-frame with skeletal animation seem to have improved recently.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="281" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtVkfDG3e2eP5MaMeZXeCgYe01fkUwWwFqhZ6YUNf1J9-Q-llw2YfELRCKeD6obUdK0ktNYM8McZgAnI14RZfBbaH_iPZZaAFHIhqUy-AWwe8zl42Hwz_LIVn7_oWZUof7kNjUeu8JkC_1/s0/Blightbound+animation+tools+-+Spine.jpg"/><br />
<i>Spine by Esoteric Software is a 2D character animation tool for games for creating animations using parts, skeletons and deformations (screenshot taken from one of Spine's tutorial videos).</i></div></p>
<p>We also tried some other tools, including Blender and 3D Studio MAX, but those turned out to be too focussed on 3D to create a good workflow for 2D animation for us. Especially the nice skeletal systems they have became quite impractical when used for 2D animation.</p>
<p>So instead, we wanted to stick with After Effects. After Effects is mostly known as a tool for editing video and doing special effects and such, but it’s actually also just a really good general animation tool. Our artists happily used it for character animation in our previous games Awesomenauts and Swords & Soldiers 2. The basic idea is this: each part in an animation is a layer, and can be animated, linked and deformed freely. By turning layers on and off, you can do frame-to-frame animation on parts (like a hand opening and closing) or on the character as a whole.</p>
<p>I imagine After Effects would be a bad fit for full hand-drawn frame-to-frame animation, like in Cuphead, since After Effects doesn’t even allow drawing on layers directly (we draw all our parts in Photoshop). However, for our games it’s an excellent tool because we don’t want to redraw the entire character every frame anyway.</p>
<p>There was something missing though: After Effects is a great animation tool, but it’s not really tailored to 2D character animation. Good thing we already knew about the <a href="https://rainboxlab.org/tools/duik/" target="_top">Duik plug-in</a>. Duik adds the rigging features that are common in 3D animation to After Effects. Combined with the strong tools After Effects already has, it’s a really effective 2D animation tool for games.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="305" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG08X7g4Dl2ZjLB4AMCINNukanSXUrMFBK1s_AmSCpgx5VdyF4EVYlMkcb8lSshhQjUlBNI7fMnO5z-PXv8dN0IHgZCbw1aoQiU9DqWCxuo0lVphjtOF5eesLzg7pGmREDUNhLML3nvBdn/s0/Blightbound+animation+tools+-+Duik.jpg"/><br />
<i>Duik is an After Effects plugin that adds tons of 2D animation features (screenshot from <a href="https://www.youtube.com/watch?v=jw0oxO7KWEk" target="_top">this tutorial video by Motion Tutorials</a>).</i></div></p>
<p>I previously mentioned we wanted to mix skeletal animation with frame-to-frame animation. That part is actually really simple with Duik. The artist just links several drawings of a part to a bone and switches which is visible. This way we can change facial expressions during animations, as well as do things like open and close hands, pivot or distort a torso and switch facial expressions.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="309" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_w-Mr8b30yS8OEF8XD0viveDnZ5EDKNmhIniPWMGeKCwX9fNYn5JvWHulzFZQTWl-ClVJ6_3Bb_Kl3Qt33c8ZKqYj9Ro_FCHGjzZOKAFfPC61U2Yl3j3Ca8m2tqXq3tptaUNTka1AXj_R/s0/Blightbound+animation+tools+-+Parts.jpg"/><br />
<i>Thumbnails of most animation parts needed for one character in Blightbound. The various hands, faces and chests are for frame-to-frame animation on parts of the body.</i></div></p>
<p>Happy with After Effects+Duik as our animation tool, another important thing was missing: After Effects files can’t be played back in real-time engines. So I set about the task of writing an exporter from After Effects that exports all the hierarchy and animation data. I also implemented the in-game side of playing that back in real-time.</p>
<p>At it’s core, this is a surprisingly simple task. Each part in an After Effects animation is a layer and we can just export all the layers with their animation frames and play them back. Where I went wrong though, is that I wanted to emulate Duik’s systems in-game. I thought Duik only did basic two-bone inverse kinematics and implemented that in the engine. This worked with simple animations, but for complete characters the animations were completely broken in-game. When I looked deeper I learned that Duik actually has a ton of different animation systems and approaches. Mimicking all of those in-game was totally undoable.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="203" data-original-width="164" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggNz0VHk_obXniooKhKQHu-lvFMq80iAjfA1nKSudQFh5uWnKjsrUrXSBNp04KiuMS8xaFEiZdPH-qXsscQUUej30uCaWu5Q25MkSNDi8wE57sjphiE752YvWz76XEAsULkDaa6UVYtE96/s0/Blightbound+animation+tools+-+Broken+IK.gif"/><br />
<i>Duik has so many features that only supporting parenting and two-bone IK produced completely wrong results in-game, as can be seen in this 'beautiful' monstrosity. This was intended to be a normal walk animation, early during development of Blightbound.</i></div></p>
<p>Once I realised this, I went for an easy alternative: animation baking. I export the orientation, scale and position of each part at 30 frames per second, simply storing the values for each frame (unless they’re not changing). This is a lot more data, but compared to the size of textures it’s really negligible. I did keep the hierarchy of the bones, so parts don’t start to subtly 'float' compared to each other.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="491" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRjANwtuylluDpxrCJy3XD7DfsL6ERsotjgsSu0hQjXQDzqsU00urPbRHXaMBiNlJDbXImhGlW1_1dvUjlktxnabobUC7BOAiWn3eOPBH-RbXWm502HqlFMghfAmcXyAUDCfV8SUAXgz8J/s0/Blightbound+animation+tools+-+File+format.gif"/><br />
<i>Our custom file format is simply a text file with a long list of all parts and the information needed to position and animate them correctly, including parenting and keyframes.</i></div></p>
<p>I previously said we wanted high framerate. The game actually interpolates between these frames, so while they’re exported at 30fps, they’ll also run smoothly at 60fps, 144fps, or any other framerate. That’s also great for when slowing an enemy: in Awesomenauts, if you slow an enemy, you can see the low framerate of their slowed down walk animation. In Blightbound, movement remains perfectly smooth.</p>
<p>A note there is that whenever something needs to jump from one position to another instead of smoothly interpolating there, the artist needs to use a <i>hold</i> key. Our tool exports those and applies them correctly during playback. Overlooking this caused some bugs here and there, because artists aren’t used to needing to use hold keys when two frames are directly next to each other. In-game however there can be frames in between, so that case still needs a hold key.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="239" data-original-width="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwlstNNag1yxGPZ3HqRAYwLh5LwgWJuo8RRZRyU8Ceg0In-WyOj8IEW-iKeS323gKDGbeQUjy8pVTpObh5q4WGkkeOEMmcxM_9jlxz7J-EWO1OIScrVmCXxn2hiK6-_o692k8jKbgF_NfX/s0/Blightboung+animation+tools+-+Karrogh+animations.gif"/><br />
<i>A few animations that Ronimo animator Tim Scheel made for the Blightbound character Karrogh.</i></div></p>
<p>After Effects is a huge tool with tons of features, so it’s impossible to support them all in-game. Our exporter only supports what we actually need, and nothing else. This means our artists need to avoid using some After Effects features that they might want to use. In most cases this is fine, but one particular feature that we ended up not supporting due to a lack of time, is mesh deformations (also known as puppet pins). Being able to deform a part would have helped a lot, but we didn’t find the time to implement a good emulation of After Effects’ deformation features in-game. Quite a pity, and I wonder whether our artists have ever wished they had chosen Spine after all, since Spine supports deformations in-game out-of-the-box.</p>
<p>Our artists did apply a simple workaround for the lack of deformations. By doing them in Photoshop and saving them as different frames for a part, they work fine. Technically the engine then thinks it’s frame-to-frame animation, but it’s actually deformed instead of redrawn in Photoshop. This approach wasn’t used much because it requires a lot of handwork, especially when reusing animations on several characters, but it does get the job done when needed.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="254" data-original-width="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7NBNchyphenhyphenPUNxhyphenhyphenN1cGyZrnhU4aQokNDEDJkXlNgUWdIC1Y0DSxkdB4b-k92pNsl_0vtThY7e00E22MhzU4nj_PnWlEOtGryvp6yrY655TTwdc585wmcjWs7DZBx72ZmC9c6JtMnZxBq8C0/s0/Blightboung+animation+tools+-+Chest+deformation.gif"/><br />
<img alt="" border="0" data-original-height="192" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidUgCiTpoS9Ee2pD4xbCu_vTPXNHbY-Tm0aF0ChE0Jh_fVonn2lVaZbGIZSGQilcOH0EPUW2Ve4Z6DMfV8GEEM8WbzZotiWRfseGiB4bevVB6fYFmx2NiDGhuPGDy1hIbLe7EyaBwZkZSL/s0/Blightbound+animation+tools+-+Chest+deformation+frames.jpg"/><br />
<i>The chest deformation in this animation from Blightbound was made by deforming the chest part in Photoshop and then exporting it as separate parts.</i></div></p>
<p>From a memory perspective the result of our toolchain is pretty impressive. Whereas a single Awesomenauts character can take up 16mb of texture space (excluding skins and the blue team), all Blightbound characters and enemies together use only 65mb of texture space, spread out over 4,600 character parts. On top of that, Blightbound animations are much higher resolution and higher framerate and we can swap parts and weapons dynamically.</p>
<p>What we have so far is strong animation tools (After Effects + Duik) and a way to play animations back in-game. This is enough to make a playable game, but we wanted considerably more: easy reuse of animations between characters, equippable gear, attaching special effects to bodyparts and efficiently handling thousands of character parts. In next week’s blogpost I'll dive into how we achieved those goals using our own skin editor.</p>
<p><i>Special thanks to Ronimo artists Koen Gabriels and Gijs Hermans for providing feedback on this article.</i></p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com2tag:blogger.com,1999:blog-3064325214589649535.post-82008157839349315572021-02-21T14:49:00.005+01:002021-03-17T15:53:49.083+01:00Blightbound's approach to individual storytelling in a coop game<p>An interesting design challenge during development of <a href="https://www.blightbound.com/" target="_top">Blightbound</a> was how to combine personal storytelling with coop gameplay. In Blightbound three players play together, but they might be at different spots in the stories of their respective characters. How to make room for storytelling without spoiling stories for other players who might not be there yet, and without making players wait for each other? Today I’d like to dissect the approach we’ve used to solve this problem.</p>
<p><i>Before I continue, note that this blogpost will spoil some story moments. However, I’ve made sure to only take examples from early in each character’s story, so the videos in this post will only be a minor spoiler to the game.</i></p>
<p>Blightbound is a coop dungeon crawler, but unlike games like Diablo it doesn’t have a linear campaign. Instead, the player repeatedly plays a number of dungeons while learning each character’s story and gathering loot and more characters. In that sense it’s structured more like the end-game of Diablo, or like a looter shooter.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="341" data-original-width="501" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0OVUL9-rrnWs7g7wWJFB13Ama1_N0C_ZHHfO8XiOFZmbA_48_yu2Dcd5wkmj8rf6aMK8fjexpXuNtb9RurgjYhXr34xYP36KlFWtfHXVTkpNPxb4wmcUdoSxjUVPRZEHNBxlntGcwjNy8/s0/Coop+storytelling+-+Blightbound.jpg"/><br />
<i>Blightbound is a 3 player game, with both online and local coop.</i></div></p>
<p>Another important aspect of Blightbound is that it has a lot of heroes. Instead of maxing out one hero for dozens of hours, the player gets to unlock a bunch and is invited to try them all. We would like players to vary what character they play. For this reason we wanted to tell a lot of small stories, interweaved with gameplay, instead of telling one big story. Each character has their own little story they go through.</p>
<p>Each hero in Blightbound has an individual story that’s told through the dungeon runs with that character. When 3 players play together, they each play a different character so they’re supposed to get different stories. This is where the issues that I’m discussing today arise. Players shouldn’t see the stories that the other players are getting, because they might not have progressed to that point with that character yet (spoilers!), or might have seen that bit already. Also, Blightbound is a fast-paced game so we don’t want players waiting for each other’s cutscenes.</p>
<p>The solution we came up with is that the storytelling is entirely private. When one player gets a bit of story for their character, other players don’t notice this at all. They might even simultaneously be getting different stories for different characters!</p>
<p>Now how do we make that work without letting players wait for an invisible cutscene? The simplest solution is used a lot in Blightbound: dialogue while gameplay continues. The player gets served portraits, speech bubbles and voice acting while the gameplay continues. So there’s no need to stand still and watch a cutscene.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/xt9-T1Y5WcQ" width="500" youtube-src-id="xt9-T1Y5WcQ"></iframe><br /><i>Two examples of basic story beats during gameplay.</i></div></p>
<p>This does introduce a problem: getting extensive dialogue during combat is going to be very distracting and the player likely won’t be able to follow the text while focussing on the fight. Luckily, we needed some pacing anyway. A dungeon that’s 15 minutes of constant combat is both too intense and boring. So we should introduce some quieter moments anyway, and we make dialogue happen during such moments as much as possible. This way players can keep exploring but also have the mindspace to digest the storytelling.</p>
<p>If the player keeps moving, who is that dialogue with then? Here we’ve tried to vary it as much as possible. The simplest ‘dialogues’ are inner monologues of the hero. In other cases there’s a dialogue with an an NPC who’s standing in the level. Here too the other players can’t see this non-player character. To avoid waiting, the player can just keep walking: the dialogue starts when interacting with the NPC, but after that the player can run away and the dialogue will continue.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/HdUgMt4CnFg" width="500" youtube-src-id="HdUgMt4CnFg"></iframe><br /><i>Gameplay continues during dialogues, so teammates don't have to wait for you.</i></div></p>
<p>To spice things up, we’ve added a fun trick here. The player is playing with two others who are random other heroes. To make the dialogues more dynamic, these other heroes will actually respond to it. But 21 characters all responding to all the story moments of all 21 other characters is way too many combinations. So instead we’ve defined a bunch of standard responses that each character has unique versions of. These are referred to in the dialogue scripts and then inserted dynamically during gameplay.</p>
<p>We have a total of 11 types of such standard responses and each character has their own line for each type. This way the responses can fit their personality. For example, these three lines show how different characters fill in the symphathy response:</p>
<ul><li>"<i>I feel your pain.</i>"</li>
<li>"<i>You have the clan's sympathy.</i>"</li>
<li>"<i>Would a moisturizing salve help?</i>" (lol wut)</li></ul>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="265" data-original-width="433" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM6jrtCW8pDJzE0LEWGz8wjo5moHCheeyX7LahrEPFz8kcw5keqseEpeK-J5NOAQE21Uqwfs3z9lxC3I51Uc25mRlG9TfyX88YYlCo43NRoRCsQwCv52MOYd-kn2bgwUtvRy2PjgjglyIt/s0/Coop+storytelling+-+Reactions.gif"/><br />
<i>All eleven types of responses for one of the playable heroes.</i></div></p>
<p>What we have so far is cool, but still rather basic: all storytelling is done through dialogues and monologues and that’s it. From there we’ve looked into how we could spice things up without adding pauses. We should also not introduce too much work: Blightbound has more than 100 such story moments so efficiency is important.</p>
<p>The first element that adds some variation is how story beats are triggered. In some cases it’s simple: enter an area that’s marked and the storytelling starts. Some story events can trigger in any such area, while others need to take place in specific dungeons since they’re linked to that setting.</p>
<p>The more interesting ones require some form of interaction. For example, the mage Korrus looks for vases to investigate, so you need to spot them and interact with them. Other characters see someone standing in the dungeon and need to interact with the character, or see a hallucination. When there’s a hallucination hanging in the level, it’s only visible to the player who’s story beat this is for. To their teammates, it’s just a regular spot in a dungeon. Again we’ve made sure that we only use short and simple interactions, so that your teammates don’t need to wait for you.</p>
<p>One of the more fun types of story events are elite enemies. Some heroes need to fight specific characters to progress their story. To make this work, we’ve made special elite versions of some enemies that only trigger as part of someone’s story. The party of 3 players fight the elite enemy together. The nice thing here is that to your teammates, it’s just another elite enemy with some special skills (we have plenty of those outside story moments as well), while to you this specific enemy is a story moment and triggers dialogue. So this is a coop battle that is also a single player story moment. Quit neat, I think!</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/AdVKoDIz9m8" width="500" youtube-src-id="AdVKoDIz9m8"></iframe><br /><i>An example of a story beat in which we encounter an elite enemy.</i></div></p>
<p>Unlocking new heroes to play is a big part of Blightbound’s progression system. Here too a goal was to add some variation. Many heroes are simply found and rescued from a dungeon, but some others can only be unlocked by paying the merchant, by making your village prosper, or by finishing the story of another character.</p>
<p>For the simplest case, where a hero is rescued from a dungeon, we again ran into the problem of this being a coop game. My teammate might already have saved the hero that I’m rescuing, how does that work? To solve this problem, we’ve introduced the concept of survivors. These are basic characters that you can’t play. When you rescue a survivor, you get a little prosperity bonus to your village and that’s it. Now whenever one player is unlocking a hero by rescuing them in a dungeon, the other players see this as rescuing a generic survivor. This way it never looks like a teammate is reviving thin air: there’s always someone lying on the ground, ready to be saved. It might just happen to be a different character for each player.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/y9b0aAM9z2w" width="500" youtube-src-id="y9b0aAM9z2w"></iframe><br /><i>Unlocking a hero compared to rescuing an anymous survivor.</i></div></p>
<p>One more nice trick that I would like to mention is one that we’ve so far unfortunately not finished implementing (Blightbound is still in Early Access on Steam). Since levels have these areas that are ideal for triggering story beats (no combat, some space for exploration), it would be nice to do something with that even when there’s no story beat for your specific character triggering in that run. So Roderick (the writer on Blightbound) has written a bunch of dialogues and banter that add some world building and personality building, but aren’t tied to any moment in the story. This way we can always trigger something. Since this is really a non-essential bonus feature we haven’t gotten around to actually implementing these lines yet, but I really like this feature so I can only hope that we’ll find the time to add this at some point.</p>
<p>Before concluding this blogpost I’d like to also have a short look at the implementation. With 21 heroes all having story moments and shouts and banter, Blightbound has a LOT of voice lines. There are more than 100 story events and over 6,000 voice files, ranging from short barks to several sentences. Working efficiently with such large volumes requires some proper tools, so <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a> programmer Jeroen Stout (known for having made <a href="https://store.steampowered.com/app/94000/Dinner_Date/" target="_top">Dinner Date</a> before joining Ronimo) implemented a system he calls Voice-A-Tron.</p>
<p>Voice-A-Tron was tailor-made for Blightbound and it’s a very neat tool that provides a bunch of features, including:</p>
<ul><li>A spreadsheet that automatically presents all lines in two formats: per character and as it appears in dialogue (so alternating between lines of different characters).</li>
<li>Some simple scripting rules that allow defining dialogues, what portrait to use, where to trigger context-sensitive responses, triggering animations and even triggering related achievements and unlocks.</li>
<li>A system that automatically executes these scripts in-game, so that our game designers need to do less work to implement story beats.</li>
<li>Special objects that can be placed in levels to control where and when story beats are triggered.</li></ul>
<p>Using Jeroen’s Voice-A-Tron system, <a href="https://twitter.com/HeerRood" target="_top">Roderick Leeuwenhart</a> wrote and defined all the story beats. Roderick is the writer for all Blightbound dialogues, as well as a series of <a href="https://www.blightbound.com/stories/" target="_top">short stories set in the Blightbound universe</a>. The next step was that Ronimo game designer Thomas van der Klis did the actual implementation, for example defining where story events can trigger and creating special items and elite enemies.</p>
<p>The result of all this work is that in Blightbound, each character has their own story beats and these are told without interrupting the flow of gameplay and without spoiling teammates. At the same time the system is simple enough that it was doable to implement for all 21 heroes in Blightbound. While Blightbound isn't a storytelling game at its core, I feel this adds a lot of personality and purpose to the experience.</p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-32393845074473132312020-12-06T15:35:00.004+01:002020-12-07T13:16:41.579+01:00Softening polygon intersections in Blightbound<p>Our new game <a href="https://www.blightbound.com/" target="_top">Blightbound</a> features many types of foggy effects: mist, dust, smoke and more. Such effects are often made with planes and particles, allowing us to draw fog and effect textures by hand and giving us maximum artistic control. However, one issue with this is that the place where fog planes intersect with geometry creates a hard edge, which looks very fake and outdated. My solution was to implement <i>depth fade</i>. This is a commonly used technique for soft particles, but we use it on lots of objects, not just on particles.</p>
<p>In today’s blogpost I’ll explain how depth fade rendering works. I’ll also show just how widely this technique can be applied, by going through a bunch of examples from Blightbound.</p>
<p>First, let’s have a look at what problem we’re trying to solve here. When putting partially transparent planes in the world, the place where they intersect with other objects creates a straight cut-off line. Sometimes that’s desired, but often those transparent planes represent volumetric effects. They’re not supposed to look like flat planes, but that’s just the easiest and most efficient way of rendering them. This is fine when there are no intersections, but when there are then the hard lines where they touch other objects break the volumetric illusion.</p>
<p>There’s a simple solution for this that’s used in a lot of games: depth fade. The idea is to simply fade out the plane near the intersection. This produces an effect similar to how real fog works: objects that go into the fog seem to smoothly fade out. However, actually figuring out all polygon intersections takes too much performance, so we want a rendering trick instead.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="531" data-original-width="501" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg1JCDkqfn2m1ARGRV9IiYbFtgeFg-hnm3XzImiYU8DoHOfZeuuWHpxEgImueR9VIeZKhlAEQUeWptxWVzp49-oZhwhitMUVoUe7cZCiImBhn7bDJus7hdhnphYTn8JW5UuIGd02vmvt-F/s0/Depth+Fade+-+With+without.jpg"/><br />
<i>This screenshot from Blightbound shows a fog plane just above the ground. In the top image it is rendered in the standard way, resulting in hard intersections with the characters, rocks and cart. At the bottom the intersections are smoothened by depth fade.</i></div></p>
<p>The trick to rendering with depth fade is to first render all normal geometry, excluding any transparent objects. This fills the depth buffer, so for every pixel we know what distance it has from the camera. Then when rendering the objects that need depth fade, the pixel shader looks up the distance in the depth buffer and compares that to its own distance. If these are close to each other, then we assume that we’re near an intersection and fade out this pixel. The nearer, the stronger the fade out, until the object is entirely invisible at the point of intersection.</p>
<p>This technique has a few neat bonus features on top of just smoothing out intersections. By simply setting the distance over which the fade occurs, we can modify the density of the mist. Also, objects don't need to actually intersect with the fog plane to get depth fade applied. Being just beneath the fog plane also makes the effect visible. Thus depth fade is more than just a way to smoothen intersections.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="263" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6iU2J-5JIVwvEmP8larHb4BxmRYRhQmAWQO6JSqN1J-zA6cGJPSSzKT92Mnt5Oxwe7zWPc9i0XkaxAuA3FT7NyBY7Ufd5-JDtH6GONb-CqWhCpjrbNtfZGpAg_cP9EDDE1nrCENJdG3lW/s0/Depth+Fade+-+Varying+density.jpg"/><br />
<i>The fog's density setting determines the width of the smoothing of the intersections. At a very high density the smoothing is almost lost. At a very low density the fog almost disappears because the ground is now also considered 'close' to the fog plane.</i></div></p>
<p>While this technique is traditionally mostly used for particles, it can easily be used for all objects with transparency. Since the world of Blightbound is covered by the blight (a thick, corrupting fog) we have a lot of types of fog in our game, including many fog planes and particles, as well as smoke and special effects. Our artists can apply depth fade rendering to all of those, not just to particles.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="281" src="https://www.youtube.com/embed/biowwsr7WRo" width="500" youtube-src-id="biowwsr7WRo"></iframe><br /><i>Depth fade is also great for hiding the seams of moving objects, like this fog wall.</i></div></p>
<p>A nice property of depth fade is that it doesn't cost all that much performance compared to traditional alpha blending. For each pixel of a particle or fog plane that we render, it costs one extra texture look-up (in the depth buffer) and a distance calculation. Compared to more advanced volumetric techniques, like voxel ray marching, that's a very low price. Since the performance impact of depth fade is low, our artists can use this technique on many objects, not just on the few that really, really need it.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="359" data-original-width="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJC-nVjABaOfou1S3nre8uhtePAHOlFsdjPHI3qDYSxP3oXLhskVrBVpqKuCsF2mwySK-FJqtFwaNqggwRop7ctfVRSWoOJdnfwzq7zxBihfdCHyuPzHpeZr76BHYJi-ZjJwCA6ppx4oO4/s0/Depth+Fade+-+Torch.gif"/><br />
<i>Depth fade can also solve problems with camera facing glow planes. The glow on this torch is always oriented towards the camera, but that makes it intersect with the wall behind it under certain angles. Using depth fade, the intersection can be hidden. This animation shows alternating with and without depth fade.</i></div></p>
<p>When I implemented depth fade, I thought I was being pretty clever: I had only ever seen this technique used for soft particles, not for generic object rendering. However, while searching the web a bit to write this blogpost, I found out it's actually a standard feature in the Unreal engine. For Unity I only found the option on particles, but it might exist in a more generic form there as well.</p>
<p>Now that we know how depth fade works, let’s have a look at a bunch of example uses from Blightbound. Special thanks to my colleague Ralph Rademakers, who made most of the levels and is thus the prime user of depth fade in Blightbound. Ralph gave me a nice list of cool spots to show:</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="281" src="https://www.youtube.com/embed/KH5_Kckg3bU" width="500" youtube-src-id="KH5_Kckg3bU"></iframe><br /><i>A compilation of examples from Blightbound where depth fade is used to great effect, showing both with and without depth fade.</i></div></p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="558" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxP_Im6jyKyNlFlKrnhwjuKRsuv3lytwUrfwHsWpfOUFd6-fcoLRnwhW74SknxvNpV30JD25CYmB230BRknNqeFbh-a96Tc2swaeOXk3S6EYcHPYv4qUgeWkC1dkK4T2ITmdWsOZiMLciA/s0/Depth+Fade+-+VFX.jpg"/><br />
<i>Another application of depth fade is to hide seams of VFX with the world. In this example the smoke effect intersects with a black ground plane.</i></div></p>
<p>When I initially implemented depth fade in Blightbound, I thought it would mostly be used on fog planes that float just above the ground, to give the impression of heroes walking through a low hanging, milky fog. As soon as our artists got hold of this technique however they started using it on tons of other objects. This is to me one of the most fun parts of building graphics tech: seeing how much more artists can do with it than I had originally imagined!</p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-47299032140130122602020-11-25T17:46:00.005+01:002021-03-17T16:15:24.712+01:00Arcane Glamour LIVE NOW! Blightbound's biggest update yet!<p><div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="542" data-original-width="501" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvlXdc3nqTwzrzw4mM8ysyHoTu2qSg1UMoDsqcJj90wd0Q7CeSsy4L7nVZDSPOy9F-zcDafqn-2u9bF4np-ZNX11Dhwpfuwhz3RtQbpLJP1w0q-_emT1I2nSZf9guYePlUodSwJp7b8SlQ/s0/Blightbound+Arcane+Glamour.jpg"/></div></p>
<p>Today we've launched our biggest update for <a href="https://store.steampowered.com/app/1263070/Blightbound/" target="_top">Blightbound</a> on Steam yet! I'm really proud of what we've achieved with this one, since it not only adds a lot of cool stuff, but also makes big improvements to existing things in the game. Menus have been overhauled, the tutorial has been improved and many minor issues have been fixed. Also, some features that limited players and didn't really achieve their goals have been removed: blight, notoriety and limitations on character select.</p>
<p>Our previous major update is less than two months away and I think it's pretty impressive how much we've cranked out in that time. Now for the most important thing: I hope our players will like the new changes and improvements!</p>
<p>The new character in this update, Roland of Stendhall, also comes with a short story about how he joined the refuge. I had a lot of fun reading how vain Roderick Leeuwenhart depicts him. You can read the story (as well as the other ones) here: <a href="https://www.blightbound.com/stories/" target="_top">I, Roland of Stendhall</a>. I'm especially font of Roderick's invention of the word <i>magesplain</i>: "<i>The geologist saw all sorts of difficulties in this plan and was keen to magesplain them to me.</i>"</p>
<p>You can find the full list of changes in <a href="https://www.blightbound.com/game-updates/arcane-glamour-0-5/" target="_top">the patch notes</a>.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/EwJKxzxJlWE" width="500" youtube-src-id="EwJKxzxJlWE"></iframe></div><br /></p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-73621513326070909572020-11-15T16:55:00.006+01:002020-11-17T21:29:25.993+01:005 years below minimum wage: the financial history of Ronimo<p>Starting your own game company is fun and exciting, but it’s also challenging. It takes courage and skill, but above all: patience and perseverance. Some become successful quickly, but in many cases it takes years to achieve financial success and actually make a decent living out of your own game company. It might take long to make your first product or get your first deal, and that first achievement might only be a stepping stone towards a next step that brings financial stability. Today I’d like to show an example of just how long that can take by sharing the financials of the first five years of <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a>, the company I co-founded with 6 friends nearly 14 years ago.</p>
<p>TLDR: The very short summary is this: it took us 2 years to make any money from Ronimo at all, 4 years to earn (almost) our country’s official minimum wage and 6 years to receive a more decent monthly salary from our own company. During that period we were near bankruptcy twice. Why did it take so long? Read on and you shall know!</p>
<p>A note before I continue: this blogpost is partially about how long it took us to “make a decent living”, but the cost of living differs hugely per country. The Netherlands is a wealthy country so cost of living is relatively high. A quick internet search <a href="https://www.numbeo.com/cost-of-living/rankings_by_country.jsp" target="_top">shows</a> that cost of living is much higher in some countries and only half in others. Since most revenue is worldwide, the same sales might mean financial stability in one place, but not enough to pay the rent in another.</p>
<p>Also, for anyone used to reading US dollars instead of euros: if you just replace the € sign with a $ sign, you’re in the right ballpark (especially given that the exchange rates between dollars and euros have varied a lot over the years).</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="238" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1-UUHp5BC6hMvB5NsH1kWStgEEh5oxZqny4iG4Y499sxkyZUlDWpGR5Akj0-qKVVacgWMYWxtwdy55_3A9CDNQJJpeWsPXWDVyO3xFZp6xT8bo_iLVlqvmxVpzrk2fxo1KqWypT7NHa0R/s0/Financial+history+of+Ronimo+-+Header+-1.jpg"/></div></p>
<p>In our second year of studying at the Utrecht School of the Arts our classmate Fabian Akker brought up the idea of starting a company together, with a group. Around that time we had done a couple of school projects that had failed quite miserably, so my first thought was: “we suck, let’s not.” However, the third year was to bring the first major game project, so we figured that if we could make something awesome there, then maybe we could also start a company making our own games.</p>
<p>The resulting game was <a href="http://blob.oogst3d.net/" target="_top">De Blob</a>: a huge success! We put it online and got attention from gaming press and even had some publishers contacting us, wondering whether they could buy the rights to De Blob.</p>
<p>(Note that De Blob was not exactly made by Ronimo: of the 9 students who made De Blob, only 5 were part of the 7 founders of Ronimo.)</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="237" data-original-width="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5OWJt1Zp8D-JU9iugRnN4QQmrTCF8sCWMTaRG8PIGiIw_wzOFhXXxqpWFkHdygfiJta3ZAgvrSlADikcWB1Uq2ayZd4OuDZ0g8wUF9pFSxQM-oV2XiD_HbbQEtQeH_eN2B1hRc7eeCKlD/s0/Financial+history+of+Ronimo+-+Header+0.jpg"/></div></p>
<p>Convinced by De Blob’s success, we decided to really go through with starting our own company. However, each of us still had to do a 7 months graduation project. We combined them and made starting Ronimo our graduation project. Getting school to approve of that was a bit of a struggle, but once they did, we even got our own office inside school.</p>
<p>At the time, 'indie' as it's known today hardly existed and we had definitely never heard of it. We thought the only way was to make retail games and that required funding from a publisher. So we set out to make a pitchable prototype: <a href="http://joostdevblog.blogspot.com/2012/10/the-history-of-snowball-earth-now.html" target="_top">Snowball Earth</a>. This was intended to be a Nintendo Wii game and we hoped to find publisher funding once we had graduated. At this point Ronimo didn’t make any money at all, but that was okay since we were still students.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="238" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaQdWowwNzzB8sVp3b8b2v-hzD7dF5dZt8BcNwDI_aKB9qWeN5VLqsLxWirUPquUICugX7ss4QnrIIzAoXYFAFvq2N16hpVpDwhfVY22h8_upFV9_FO98qCKNdDVlSxAZy3BWMZRwu3yYb/s0/Financial+history+of+Ronimo+-+Header+1.jpg"/></div></p>
<p>September 2007. We were so focussed on pitching to publishers that we did our graduation stuff on the side and crunched for what came a few weeks later: Games Convention in Leipzig, Germany! There we pitched to at least a dozen publishers. Some were interested and continued conversations with us afterwards. Hopeful, we continued work on the game, looking to improve it and increase our chances of signing a deal.</p>
<p>Our very first presentation was for a then pretty famous person from a big company. He was so excited that… he feel asleep during out presentation. Jet lag. Or disinterest. Or both. When we woke him up, he proceeded to try to sell us his own middleware and hardly looked at our game.</p>
<p>By this time we had graduated and had moved to our own office in Utrecht. A very small office for 7 people, but it was cosy and exciting. What we didn’t have, however, was money. We did some minor work-for-hire jobs, but since we weren’t fully committed to that, we hardly made any money there. Just enough to pay the rent of our office, but definitely not enough to provide ourselves with any income.</p>
<p>This is something I've seen quite a lot: studios who want to make their own games and finance that with work-for-hire rarely succeed at both. Either they hardly make any money from the work-for-hire, or they spend so much time on that that they can hardly focus on their own game. Often the result is that the game takes many years to build and turns out mediocre because of the lack of focus and time. The reason for this is simple: doing work-for-hire well and making it lucrative is <i>hard</i> and it's rare for that to work as an aside, especially for inexperienced recent graduates.</p>
<p>So, we didn’t make any money and we weren’t students anymore. How did we not starve? This varied amongst the founders. First of all, in September 2007 we managed to sell all the rights to De Blob to THQ, a then major publisher that’s now defunct. (Note that THQ Nordic is a different company that later bought the rights to the name and games of THQ, including De Blob.) For this we were each paid a nice amount (can’t disclose it due to NDA unfortunately), enough to pay the rent for quite a while. However, only 5 of the 7 Ronimo founders were part of the De Blob team, so 2 others didn’t have this.</p>
<p>Six of the founders had an additional source of income: the now defunct WWIK government subsidy. This paid recent art graduates around €600 per month. That’s less than half of the official minimum wage in the Netherlands at the time, but enough to not starve. To live cheaply, three of Ronimo’s founders rented an apartment together with one more person.</p>
<p>I personally didn’t get WWIK because I had some savings and thus didn’t qualify, so I went even cheaper: I kept living with my mum until I was 26 years old. I have a lovely mum though so I totally didn’t mind. Thanks, mum!</p>
<p>This is also a good moment to mention how privileged we are to be doing this in the Netherlands. In many places in the world all of this would have been much harder.</p>
<p>So, how did the pitching go? A few publishers were interested and one even flew over to do due diligence: judging whether we would really be able to make the full game. In the end none of them actually offered us a deal because Snowball Earth was too unique and we were too inexperienced to be trusted with that much money. We were asking for €1.5m development budget. Not much for the big game we envisioned, but definitely too much to give to a bunch of students who had so little clue about business and production processes.</p>
<p>Snowball Earth was too big a game to finish without funding, so we ended up cancelling it altogether. Years later we did release our prototypes, which you can still find <a href="http://joostdevblog.blogspot.com/2012/10/the-history-of-snowball-earth-now.html" target="_top">here</a> together with videos and screenshots.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="237" data-original-width="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3r2urGymHLkZyjGz0nxX7t1a30nnHS6UTmySsXK8uu60eiMeEimHk_zygDogm7JLB4UeUiwpp8yxXCv0oQs2JkWVcgna5RhFWFJiP_lSq1qDc0so546kIHBJQ0_1Pm-6ujfRQWgmaZofT/s0/Financial+history+of+Ronimo+-+Header+2.jpg"/></div></p>
<p>What next, then? By this time indie was on the rise and we had managed to get Nintendo Wii devkits. We decided to make something small that we could finish and publish ourselves: <a href="http://www.swordsandsoldiers.com/" target="_top">Swords & Soldiers</a> for WiiWare (the predecessor of the current Nintendo eShop).</p>
<p>We estimated we could make this game in 3 months. One year later, we finished and launched it. I’m still impressed that we managed to make something of that size and quality in just one year, and I’m even more impressed that we were stupid enough to think we could make something like that in just 3 months...</p>
<p>Throughout this year we still didn’t make any money, but we did hire interns. In the Netherlands internships are a standard part of many schools and are not paid like normal jobs. So for only €200 per month we could have a game student work for us full-time. Despite that low compensation, those interns were getting more money from Ronimo than we were! On average, we had 2 or 3 interns at a time helping with development.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="238" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8cF8hVSi8LUmzYeJGXJfe_PaNQ1nM7xjGte-ygqaXHGoRbqKkkZYbxeqkwA5a3jFoV4Sxxpt-x34MdBAVUnW9gEKWYzz0dh-oh1mP-ReDPvTNate2W2mtU5gnykn5ZJq_Aj4lPX0_08LV/s0/Financial+history+of+Ronimo+-+Header+3.jpg"/></div></p>
<p>In May 2009 Swords & Soldiers launched on Nintendo Wii. It got critical acclaim, reached the #1 selling spot on WiiWare in Europe and #3 in America. In total it sold 30k copies and made €146k during the first year (and very little on WiiWare afterwards). A big success for us at the time, but not that much money in retrospect.</p>
<p>In August 2009, after 2.5 years of working full-time with seven people, we were finally able to pay ourselves a monthly income. A whopping €600 per month! Oh wait, that’s super little… but it certainly felt like a big step forward!</p>
<p>Something we hadn’t realised yet at the time is the importance of porting our games to different platforms. That is, until Sony offered us money to make a PlayStation 3 port of Swords & Soldiers, including multiplayer.</p>
<p>To make this port and continue work on our next game OMG Space! (which would later be renamed to <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a>) we needed more programmers. Up until this point I had been the only programmer at Ronimo (besides interns) and that wasn’t enough to make a port and a new game. We hired two programmers. Unlike us, those coders were paid real wages (though not very high ones). And so, while we the founders finally made more than our interns, we instead now had employees who made way more than us.</p>
<p>In September 2010 Swords & Soldiers released as a downloadable game on PlayStation 3. Unfortunately it didn’t make break even, so the only money we made from this was the initial porting budget we got from Sony.</p>
<p>Now that we realised that porting is a super important source of revenue, we also ported Swords & Soldiers to Steam and released that in December 2010. Making a port is only a fraction of the effort of making a full game, and every new platform is a new roll of the dice: a new chance at success. And indeed, while the PS3 version hardly sold, the Steam version would make us €120k in its first year and €35k in its second year.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="237" data-original-width="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9sVniM7oswMRBaVYPnHZ1hYEjz_x_AQRayLqISTuTwDCjj4bzyW_G8Fx3dtPpPOZ_XkVmw-T1BLddXV5k-x6yB5DphpPqosKlWDGQcnUxSS5mEOUXDC8twy5M11J_qNMiv6Q09KqywxOI/s0/Financial+history+of+Ronimo+-+Header+4.jpg"/></div></p>
<p>Now that we had employees and paid ourselves a little bit, we had significant monthly costs. Too much to carry ourselves, so we were looking for a publisher for Awesomenauts. Near the end of 2010 this was becoming dire: we were only a few months away from being out of money altogether.</p>
<p>We were saved when we signed a publishing deal with DTP (yet another company that doesn’t exist anymore). The total development budget we got from them was €300k. Not much for a game of this size, but it was a lot for us! As is common, we received that money spread out over milestones and not all at once.</p>
<p>Awesomenauts was a very ambitious project, with complex multiplayer and simultaneously launching on two platforms that were new to us (Xbox 360 and PlayStation 3). We needed more programmers to pull that off. Good thing the budget we got from the publisher allowed us to grow a bit more. In the first half of 2011 we hired two more programmers and a producer, bringing the team’s total size to 12 full time employees. On top of that we usually also had 3 or 4 interns working with us.</p>
<p>The funding also allowed us to finally pay ourselves almost minimum wage: €1400 per month. Still less than our employees got, but at least we felt like we were finally making real money.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="237" data-original-width="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYy-5TG9oO_afyH8B9p2Rqx7SlRvuHlM6u8tk7pmfJXwOJZ-0eBQLzaGJlvoP3r-FG01zQT04EbPFoeYNgfsF4V5F-qbj4M5fLisilNzOsTIZXuanMF025FXPBYcjH5U2rzUUqYHfeL76s/s0/Financial+history+of+Ronimo+-+Header+5.jpg"/></div></p>
<p>In March 2012 we managed to secure some additional income: Swords & Soldiers was included in the Humble Android Bundle and this made us €37k. Towards the end of the year it got included as a bonus in another Humble Android Bundle, making us another €10k.</p>
<p>This money was needed desperately, since Awesomenauts had seen numerous delays at this point. I don’t remember the exact original planned release date, but I think in total the console release got delayed by around half a year. The publisher didn’t give us extra budget for that, so we had to make do with the money we had.</p>
<p>In May 2012 Awesomenauts finally launched on Xbox 360 and PlayStation 3. But not before our publisher DTP went insolvent a mere week for launch. This made everything extremely complex and we didn’t know whether we would see any royalties at all. We got lucky: we had some unreleased DLC they wanted so we managed to strike a deal with the trustee for the insolvency so that the DLC would be released and we would still get royalties.</p>
<p>Nevertheless, Awesomenauts initially didn’t sell all that well on consoles and it took long before we got any royalties at all. We were nearly out of money but had one more card to play: a Steam port of Awesomenauts. Finances were so tight that we couldn’t pay ourselves anymore for a short period. We continued to pay our employees though, so only the founders were hit.</p>
<p>Then in August 2012 Awesomenauts launched on Steam and this version turned out to sell way better than the console versions. We were saved! And we had gotten lucky again with our publisher: since DTP was insolvent, they couldn’t pay for development of the Steam port of Awesomenauts, and thus we got the full rights to that version.</p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="237" data-original-width="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWgHCWJAyswukM55VlHpx4UFRolpPzyRb_7opWfOlCfiRXu2ye7jXQssBERm9eSuJJYIKFE2yGpw2JIM1YjyWKog2udpUJ_aWrpB861OxrxkHKmS0tqfX3oxpWHr2Y9sZi7XParnz7v1Ky/s0/Financial+history+of+Ronimo+-+Header+6.jpg"/></div></p>
<p>Awesomenauts kept doing very well so we supported it for 5 more years with tons of additional content. It also allowed us to finally switch what type of company we were: we switched from being a V.O.F. to a B.V. These are Dutch legal terms so let's not go into the details here. What it comes down to, is that a V.O.F. is strongly tied to the owners’ personal finances. If the company goes bankrupt, so does the owner personally. Being a B.V. is much safer, since now the company can go bankrupt without giving creditors the right to come after your personal belongings as well.</p>
<p>Being a B.V. does come with a requirement here in the Netherlands: unless you have good reason not to, the company needed to pay the active owners at least €2300 per month (after taxes). So in February 2013, six years after we started the company, we finally started to make a wage significantly higher than minimum wage. And even then it wasn’t that much: this excludes some insurances that are standard for employees but not for owners, and for me personally as a programmer: I’m pretty sure I could have made more had I worked elsewhere.</p>
<p>As far as I can tell, most game startups take several years to become financially successful. I think it might have taken us longer than most, but we made it at all and that’s already special. In fact, since the 'indiepocalypse' happened a few years ago most people who start a game company never manage to make a living at all (as I've previously said: <a href="http://joostdevblog.blogspot.com/2015/09/the-future-of-indie-is-amateur.html" target="_top">the future of indie is amateur</a>). With Ronimo we were lucky that we happened to start our company at a time when indie was hip and happening and it was relatively easy to reach players. Today, competition is much tougher than it was when we started, so chances of success are lower as well.</p>
<p>What’s the moral of this very long story? It’s simple: to start a game company, you don’t need just skill, vision and bravery, but also perseverance and a willingness to make little money for a long while.</p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com14tag:blogger.com,1999:blog-3064325214589649535.post-29300759326726901152020-11-06T13:39:00.001+01:002021-03-17T16:16:00.363+01:00Combining 2D and 3D in Blightbound's VFX<p>An important focus during development of <a href="https://www.blightbound.com/" target="_top">Blightbound</a> is that we we wanted to achieve a 2D look but have 3D movement and a 3D camera. A particular challenge are special effects: we had tons of <a href="http://joostdevblog.blogspot.com/2016/09/creating-crisper-special-effects-with.html" target="_top">experience with 2D special effects</a>, but now the special effects also needed to communicate depth. For example, how far does that area-of-effect damage reach exactly? In this blogpost I will show a number of tricks we used to combine 2D and 3D in the Blightbound VFX.</p>
<p>This blogpost is based on an conversation I had with <a href="http://www.ronimo-games.com/" target="_top">Ronimo</a> VFX artist Kees Klop. Unfortunately Kees won’t be staying at Ronimo: for budget reasons we can’t keep him on after November. So, if you’re looking for a stellar VFX artist, be sure to send him a message on his <a href="https://www.artstation.com/smearkees" target="_top">Art Station</a> or <a href="mailto:KeesKlop97@hotmail.com">email</a>.</p>
<p>Let’s start by having a look at the Gravity Well skill that some of the mages have. This is a spell that draws in all the enemies near it, making for an excellent combo with area-of-effect attacks by the Mage’s teammates. Like many of the VFX in Blightbound, this effect combines several types of geometry. Here's what it looks like, and a breakdown of some of its elements.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/J3CNgiIJ_fo" width="500" youtube-src-id="J3CNgiIJ_fo"></iframe><br /><i>A video of the Gravity Well effect in-game and in our animation editor.</i></div><br /></p>
<p><div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="1156" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwxYZ4MJRAmbu-cGG7U8SfKBPfJdADIiiJqyJJmm1wHyn7_7i21QHJoXGOysIHDHeTafRpKCUVpwz-31jS15BCrbZoM-NtiiBqp3LJa6-GBDiyJWqLxxxQmN68fQStmdUHwE3ZtnKfy_-4/s0/Blightbound+VFX+-+Gravity+well+elements.jpg"/>
<img alt="" border="0" data-original-height="227" data-original-width="412" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhtyAyauW1fUoMky86vyR-nd3nJfqdzbjb7M_-dB7Z03sztDFFvSmuXXHnA1v30SRk1JwKytdvmo9UNHbXxERQcbOaYSY0TdLbWiqV2CX5g6_M8zgDvtrXWMa6xy8V7ZLJvwBu5sH7YeMN/s0/Blightbound+VFX+-+Swirl+mesh.gif"/></div></p>
<p>The next effect I would like to discuss is the Deck of Daggers skill that some rogues have. Several knives are thrown, and those that hit get stuck in the enemy for a while, causing damage over time. These knives are rotated out of the enemy's plane to add depth. It's a subtle effect, but having many of such subtle 3D effects in the game in total adds a lot of depth to the 2D drawings.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/WiWcWhn3Ik8" width="500" youtube-src-id="WiWcWhn3Ik8"></iframe><br /><i>The Deck of Daggers effect or, as Triss would say it: "I'm a fan of knives!"</i></div></p>
<p>Also, our animation tech helps here: since Blightbound plays skeletal animation in real-time (as opposed to rendering it down to spritesheets as we previously did), objects like these knives can really stick to a body part and move along with it. While that's an obvious option to have on 3D characters, it's a lot less common to be able to do this with 2D animation without using a rather stiff animation technique. Our animation workflow however is a topic for a separate, future blogpost.</p>
<p>One of the most screen-filling effects in the game is the victory at the end of a dungeon, after defeating the dungeon's boss. Here we see a combination of many elements, including one that's not used often in our special effects because it's so all-encompassing: colour grading. The colours of the whole scene get changed during this effect.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/tBJ6S39I5t0" width="500" youtube-src-id="tBJ6S39I5t0"></iframe><br /><i>The victory effect in-game and in our animation editor. Blight (a corrupting mist) is an important theme in Blightbound. Since this effect marks the end of a successful run, it sucks in and dissolves a lot of mist.</i></div><br /></p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="251" data-original-width="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7vDyD5xakAbTJu5diiu4FYgV4BweXyQLbNi1_Px9l-gt7BUhOWMBl5mXlECuYkmLVPYhBUdi5szlNZVkpYLgpdUlXiKTf_WEe-xzsIOF_FGUMTYAvHXHEEmyZbafL3VZ3SKLSgfHeb2wd/s0/Blightbound+VFX+-+Planes+under+angles.gif"/><br />
<i>Many special effects in Blightbound are made 3D by overlapping flat planes under various angles.</i></div><br /></p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="196" data-original-width="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuQtK71p4DI3ayThFWrJIjSllfkzJxyrVoj4tEvmDAOubKYq8iGGsKPkI5ql-ei2wt4ORLyoXP-aoHjAyeRDPZ_aUBQ0r_nW0-X3Iyk-3yScL331ogHrFJP0y7WT8_LfADLDkTZ2E5E5Mv/s0/Blightbound+VFX+-+FX+Pack.gif"/><br />
<i>A lot of the visual effects also feature bits of frame-to-frame animation. Many of those were made by Ronimo while many others were taken from the <a href="https://videohive.net/item/rtfx-generator-440-fx-pack/19563523" target="_top">RTFX Generator</a> pack, including this particular one.</i></div></p>
<p>The warrior's Warcry ability shows another technique for combining 2D and 3D. Warcry is an area of effect ability that buffs teammates. Since the range of the ability is very important, the starting point here is a circle on the ground. However, that's very flat and becomes less readable when sticking through things like grass or small stones. So to make the effect more 3D, a vertical cylinder with an animating swirl is added.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/6FKKk3prSMg" width="500" youtube-src-id="6FKKk3prSMg"></iframe><br /><i>The Warcry skill in-game and in our editors.</i></div><br /></p>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="173" data-original-width="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgabOqH8vQ6p_pM5o9-mbHYjZgBLYKSM_htJLTrtmKvuBMST83XtLeYuEmg1ZAbN1dbUa2tkpzTXZ2fnKPkNrMMRjsG2Nf69qENznyTqGfZWJfCgyQb-aVIL54pgSwAocYSSGElNsTtSNJR/s0/Blightbound+VFX+-+Tamed+Wolf.gif"/><br />
<i>Here's a little teaser: update 0.5 (coming this November) adds the new Tamed Wolf sword to Blightbound. A special perk of this sword is that when the warrior uses his shield, his teammates are also shielded. This effect visually overlaps with the Warcry skill. As you can see here, this shield effect makes the verticallity above the circle even stronger.</i></div><br /></p>
<p>On to the assassin's Chakram ability! This is a large projectile that flies, hangs still for a while and then comes back. Unlike most other projectiles it's visible long enough that it's much more than just a flash. Also, it deals damage in an area of a meter or two, so it's quite large.</p>
<p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/S717ayZqmXQ" width="500" youtube-src-id="S717ayZqmXQ"></iframe><br /><i>The Chakram skill in Blightbound.</i></div><br /></p>
<p>The Chakram is a horizontally flying circular thingy. With the relatively low camera of Blightbound it was seen under too extreme an angle, making it look too flat. We didn't want to turn it into a 3D model though since we wanted to maintain the 2D, handpainted feel of the graphics. The solution is simple: the Chakram is tilted towards the camera a bit. This is subtle enough that it feels like the Chakram is horizontal, but it adds just enough angle that it looks a lot less flat. This is a technique that we use a lot in Blightbound.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="428" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjppfkj9blLpz_6Nhg0z3R01lG5aJVhYgDekXHB_lG_Je7a67_dPbmzclonO11J8cp9YySbaD6dm6HR3fXveO5TsUsNHxTnVy_pST1IGHeX1H8FshRkvte50XQ8kPeeYt1a6jsi0VtG1uJ0/s0/Blightbound+VFX+-+Tilted+characters.jpg"/></div>
<p><div class="separator" style="clear: both; text-align: center;"><img alt="" border="0" data-original-height="213" data-original-width="476" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVn58S4MFREw08GVctsCh11LzS3lgrvI1nISBJsXW9R2yfkEm1KwC632tgaosY0eyxpxmwLOBQpGjyGLyIWe-FP4OwHizKwIQqSbuEIHvPgE7mZk_lZpjCwse3isPkhZDdbnJkCmOvnpSI/s0/Blightbound+VFX+-+Chakram.gif"/><br />
<i>While the main graphic of the Chakram is entirely flat, it's made more spatial by animating the pitch and adding particles and swooshes that move out of the plane.</i></div></p>
<p>The special effects shown in this blogpost were all made by Kees Klop, whose work I wanted to celebrate today. However, he is not the only special effects artist who worked on Blightbound: <a href="https://vimeo.com/46219758" target="_top">Koen Gabriëls</a> and <a href="https://www.artstation.com/scytha" target="_top">Luuk van Leeuwen</a> also made a lot of VFX. Koen did most of the early work of establishing the style for the Blightbound effects. Currently Koen and his intern <a href="https://www.artstation.com/ayrthonvdklippe" target="_top">Ayrthon van de Klippe</a> are working on making VFX for upcoming Blightbound updates.</p>
<p>Finding the right combination of 2D and 3D in the VFX for Blightbound was quite a search during early development of Blightbound. Our artists ended up combining a lot of different techniques, including hand-drawn art, frame-to-frame animations, meshes, particles, intersecting planes, screen distortions and even colour grading. I think the end result works really well in-game: it looks good, fits the style and communicates the gameplay well.</p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com1tag:blogger.com,1999:blog-3064325214589649535.post-49573042839896002652020-10-24T15:39:00.007+02:002021-03-17T16:16:17.185+01:00Bending Blightbound's world to lower the horizon<p>In 3D games perspective is often treated as a given; a law of nature. But it doesn’t have to be that way: with some shader trickery or clever modelling, perspective can be manipulated to achieve certain compositions that may not be realistic, but look more interesting and are still convincing to the player. One such example is how we kept the horizon on screen in our new game <a href="https://www.blightbound.com/" target="_top">Blightbound</a> by subtly bending the world.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="383" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG5Ph4MC2iNKU8hNQmqNMi0_7DI1HOinOBoZXfLgW3fyMQar762ciB1EAnJS9RzF1yflfEWpZ8DE9pNX-QLucid1URchiIyH5PR86r0AGxafIiGGB1Pvn0pQZvEc44Jjp8JJcaM_C-y0zv/s0/World+bend+-+Blightbound.jpg"/></div>
<p>At <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a> we come from a world of 2D games. In 2D, composition can be whatever you like. That’s why our art director Gijs Hermans may sometimes want to ignore standard perspective rules and instead looks at what he wants to achieve visually. Thus early in development Gijs came to me and said he wanted the camera to look down quite a bit, but still have the horizon in view. In fact, he wanted the horizon to be quite a bit below the top of the screen. His reasoning was that visuals look much better when you don’t see just the floor most of the time. Het position of the horizon is an important tool for shaping a composition.</p>
<p>The origin of this request is a clash that often happens in game development: pretty visuals versus gameplay clarity. Our artists spend a lot of time on achieving both goals simultaneously. A very successful example of this is the way gameplay objects and backgrounds are drawn in a different style in our previous game <a href="https://store.steampowered.com/app/703880/Swords_and_Soldiers_2_Shawarmageddon/" target="_top">Swords & Soldiers 2</a>, as I described in <a href="http://joostdevblog.blogspot.com/2015/05/making-gameplay-stand-out-against-rich.html" target="_top">this blogpost</a>.</p>
<p>In a game where depth matters, like Blightbound, a low camera is problematic because it makes it difficult to see whether you are standing in front of an enemy or behind them. A high camera solves this, but a high camera removes the horizon from view, making the image a lot more boring.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="680" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO-mlmmbHlO1xq1aycVfKggSMAamnsgVmqKr3-nLC3WiYbjI7Fd-kENCtUkP2LDf1tUcE3G7heLaX6JR9mjFsiSMc2a6hD7KGEIHu0NtVpU3l-dnGJQJNLTAB5BRHlgYN3ozBFy5cZ7W8X/s0/World+bend+-+Diablo.jpg" /></div>
<p>When Gijs came to me with this request, I thought of two possible solutions: either give the camera a wider field-of-view, or bend the world to move the horizon down. We tried the easiest solution first: wide field-of-view. However, it turned out this needed to be set so wide that the entire perspective looked skewed. Extreme field-of-view often isn’t very pretty and it definitely wasn't in Blightbound.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="670" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiiFp5U4HBOXJoTjPQSmwxNWgdbxI-M5tiEo4m9H9qzfCizLrQHtcDEUdDPa6KN1_Xezif0CW0IfgqY48jDouaq3sEdZ4XW7xmNfsXxCuLO7c6id57SkcVG_LIimDfgMNc_819YGKGXHLb/s0/World+bend+-+FoV.jpg" /></div>
<p>The alternative I came up with is bending the world down the further it is from the camera. This is an effect that’s used in a bunch of games to create a sense that the world is very small, making the world feel cutesy and funny. However, Blightbound is intended to be a dark fantasy game, definitely not something cute and funny, so we didn’t want anything that extreme. I figured that with some tweaking it might be possible to achieve a more subtle version of this that still keeps the horizon in view but doesn’t have the funny vibe.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="234" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfZDpo6WaMtdf11AVjPQtirZ5DYp8pqGDZg4Hx9TcsjSMqgR6iE3CIaF_Ra3eiMDkgH9YwjgZr83GvVWzZoZZllQof1AmejLk5RPPaJaE_Ti0JC19JKfmgYOPGCBnRHtmohq6-ecoooygn/s0/World+bend+-+Deathspank.jpg" /></div>
<p>My implementation of this effect is quite simple. In the vertex shader I bend down the world depending on the Z-position of the vertex in the world. The nice thing of implementing it this way is that our gameplay code and level design tools can assume a flat world, making them a lot simpler. The bending only exists during rendering, so gameplay logic doesn't need to take it into account.</p>
<p>A minor challenge in implementing this bend is how to handle lighting and shadows. When the camera moves forward and the world bends, we don’t want the lighting on objects to change, since that would make the bending very obvious and would make the player focus on the backgrounds instead of on the gameplay. Also, objects in the background shouldn't be more bright because they are rotated towards the light by the bend. My solution was to calculate all lighting, shadows and fog as if there is no world bend.</p>
<p>Also, a little technical note: since the bend happens on the vertices, objects need to have enough vertices. A big square plane for the ground with no vertices in between can’t be bent. Occasionally this caused bugs where a small object would float above a big object because the big object didn’t have enough vertices to be bent correctly.</p>
<p>The bend effect is quite fun to see in action when set to an extreme value. However, any kind of geometric deformation is quite noticeable when the camera moves, so we chose to fix the bend in the world instead of letting it move with the camera.</p>
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/ksdtB5h7pHc" width="500" youtube-src-id="ksdtB5h7pHc"></iframe><br /><i>A few different settings for the bend, including the final one used in Blightbound.</i></div>
<p>As you can see in the video, the bend effect is kept quite subtle in Blightbound. We didn’t want that cutesy/funny effect at all, since this is intended to be a dark fantasy game. Our level artist Ralph Rademakers tweaked the effect and the camera a lot until he got it to a point where it felt like there was no bend at all, just a natural camera. However, if you compare with and without bend, you can see that the bend makes a huge difference in what you actually see. And that’s exactly how it was intended: achieve the desired composition but don’t make it look like anything weird is going on.</p>
<div class="separator" style="clear: both;"><img alt="" border="0" data-original-height="320" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjohnizY60oOU_l7-MK0wbFJanrwxka4oRmP88x3qNIRwa3j-L85OgmMdLKQjmw3cZzqEDWgldvlPwFf6DDHgSSRpzmky9t7HiGELfh83q0nAGok4WtXJqtkc87wgD8xqItpYdhgnIhQabs/s0/World+bend+-+with+without.jpg"/></div>
<p>And then came the fog! The bend effect was implemented when we hadn’t figured out the lore of the world yet. We didn’t know then that we would want to have so much fog. In fact, the working title of the game used to be AwesomeKnights instead of Blightbound! Once we finally decided on the lore we knew that the world of Blightbound is covered in “blight”, a corrupting fog. To match that, Ralph added a lot of fog to all the levels. This creates a great atmosphere, but… hides the horizon!</p>
<p>Does that make the world bend useless? No, definitely not. It's still used in quite a few levels to change the perspective and have a more horizontal view on the background, even if we can’t see as far as before. It’s a more subtle tool than originally intended, but still a very useful tool.</p>
<p>I think the bend effect we used here is a wonderful example of the kind of graphics programming I enjoy most: looking at what’s needed from an artistic standpoint, and then making tech that achieves that. I’m personally not very interested in realistic rendering: 3D is just a tool to make cool art, whatever the shape or type. The bend technique used here makes no sense whatsoever from a physical standpoint, but it adds to making Blightbound a prettier, more compelling game.</p>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com2tag:blogger.com,1999:blog-3064325214589649535.post-11972021269730145112020-10-18T20:25:00.011+02:002021-03-17T16:19:02.696+01:00Screen Space Reflections in BlightboundAn important focus during development of our new game <a href="https://www.blightbound.com/" target="_top">Blightbound</a> (currently in <a href="https://store.steampowered.com/app/1263070/Blightbound/" target="_top">Early Access on Steam</a>) is that we want to combine 2D character animation with high quality 3D rendering. Things like lighting, normal maps, <a href="http://joostdevblog.blogspot.com/2010/09/depth-of-field-blur-in-proun.html">depth of field blur</a>, soft particles, fog and real-time shadows are used to make it all gel together and feel different from standard 2D graphics. One such effect I implemented into our engine is SSR: Screen Space Reflections. Today I’d like to explain what SSR is and what fun details I encountered while implementing it into our engine. <br /><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/Q7HAwllB1Kc" width="500" youtube-src-id="Q7HAwllB1Kc"></iframe></div><i><div style="text-align: center;"><i>A compilation of places with reflections in rain puddles in Blightbound.</i></div><div><br /></div></i></div>Reflections in games can be implemented in many ways. The most obvious way to implement reflections is through raytracing, but until recently GPUs couldn’t do this in any reasonable way, and even now that GPU raytracing exists, too few people have a computer that supports it to make it a feasible technique. This will change in the coming years, especially with the launch of Xbox Series X and Playstation 5, but for Blightbound that’s too late since we want it to look good on currently common GPUs.<br /><br />So we need something else. The most commonly used techniques for implementing reflections in games are cubemaps, planar reflections and Screen Space Reflections (SSR). We mostly wanted to use reflections for puddles and such, so it’s important to us that characters standing in those puddles are actually reflected in real-time. That means that static cubemaps aren’t an option. A pity, since static cubemaps are by far the cheapest way of doing reflections. The alternative is dynamic reflections through cubemaps or planar reflections, using render-textures. These techniques are great, but require rendering large portions of the scene again to render-textures. I guessed that the additional rendercalls and fillrate would cost too much performance in our case. I decided to go for Screen Space Reflections (SSR) instead. <br /><br />The basic idea behind SSR is that since you’re already rendering the scene normally, you might as well try to find what’s being reflected by looking it up in the image you already have.<div><br /></div><div class="separator" style="clear: both; text-align: center;"><img border="0" data-original-height="419" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUoNYQxM_6nR2d-XAedX4UFyXqB3YCK6bdNQSeFlHIPghyphenhyphen5n6Xe-o1QTX44_FllYcVajb_9VgPlSg7bvjXoXoPmAF4yC13U_fIkx7hg3KI9WHB8r3G5A_rj37CU3qp4xg5ZcoPRKEMmBKD/s16000/SSR+-+Screenshot.jpg" /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div>SSR has one huge drawback though: it can only reflect things that are on-screen. So you can’t use a mirror to look around a corner. Nor can you reflect the sky while looking down at the ground. When you don't focus on the reflections this is rarely a problem, but once you look for it you can see some really weird artefacts in reflections due to this. For example, have a look at the reflections of the trees in <a href="https://youtu.be/SE6R3ZGlxHc?t=258" target="_top">this video</a> of Far Cry 5.<br /><br /><img border="0" data-original-height="351" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbzDGoJt1uUGsV745d5YOsPzaOrj_Wl0XTmZjLfJ3Sd-s5sOKkxBEObjstxC4qdRsA_xSr8p4T5K_-flK5qmAE9i1FW67iJfPLYopIKQs5daolW2XRa_oKcFMGZl8yY3mzlm8mqbzKCNep/s16000/SSR+-+Far+Cry+5.jpg" /><i><br /></i><br /></div><div>So we’re looking up our reflections in the image of the scene we already have, but how do we even do that? The idea is that we cast a ray into the world, and then look up points along the ray in the texture. For this we need not just the image, but also the depth buffer. By checking the depth buffer, we can look whether the point on our ray is in front of the scene, or behind it. If one point on the ray is in front of whatever is in the image and the next is behind it, then apparently this is where the ray crossed the scene, so we use the colour at that spot. It’s a bit difficult to explain this in words, so have a look at this scheme instead: <br /><br /></div><div class="separator" style="clear: both; text-align: center;"><img border="0" data-original-height="1279" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlRTQxpRv1BNR9h4tcO_PbFvr2d8GO0FLdfXzOXKc8XYD-U1D1XLElDJx10_CcWN7gFXAwQy7Y8xa0tJKTgY2w5gJOecr0JbEFTqytXBEBVhovtn2PY066dw6aPrIP1OrlBouOzIKxqlqJ/s16000/SSR+-+Explanation.jpg" /></div><div><br />Since SSR can cast rays in any direction, it’s very well suited for reflections on curved surfaces and accurately handles normal maps. We basically get those features for free without any extra effort.</div><div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" height="281" src="https://www.youtube.com/embed/V1n9RYPSo-g" width="500" youtube-src-id="V1n9RYPSo-g"></iframe></div><i><div style="text-align: center;"><i>A demo </i><i>in the Blightbound engine </i><i>of SSR, with a scrolling normal map for waves.</i></div><div><i><br /></i></div></i></div><div>At its core SSR is a pretty simple technique. However, it’s also full of weird limitations. The challange of implementing SSR comes from working around those. Also, there are some pretty cool ways to extend the possibilities of SSR, so let’s have a look at all the added SSR trickery I implemented for Blightbound.</div><div><br />First off there’s the issue of transparent objects. Since the world of Blightbound is covered in a corrupting mist (the “blight”), our artists put lots of foggy layers and particles into the world to suggest local fog. For the reflections to have the right colours it’s pretty important that these fog layers are included in the reflections. But there are also fog layers in front of the puddles, so we can't render the reflections last either.</div><div><br /></div><div>The solution I chose is simple: reflections use the <i>previous</i> frame instead of the <i>current</i> frame. This way we always look up what's being reflected in a complete image, including all transparent objects. The downside of this is of course that our reflection isn't completely correct anymore: the camera might have moved since the previous frame, and characters might be in a different pose. However, in practice the difference is so small that this isn't actually noticeable while playing the game.</div><div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><img border="0" data-original-height="342" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKLyewK3jRym4pB9oeR2yUTHht7SaxXm3mVErUEjzZbOBh96cyTKdaVi06AE3QGE-Cb2jFsUI1eEjcK-BOFr48pg3vgwm_v-s_SttwLy3s894zhMStQYrSWXPNcd9wji70NBUDEWeHFPCB/s16000/SSR+-+Previous+frame.jpg" /></div><div><br /></div><div>Transparent objects pose another problem for SSR: they're not in the depth buffer so we can't locate them correctly. Since Blightbound has a lot of 2D animation, lots of objects are partially transparent. However, many objects can use alpha test. For example, the pixels of a character's texture are either fully transparent of not transparent at all. By rendering such objects with alpha test, they can write to the depth buffer without problems.</div><div><br /></div><div>This doesn't solve the problem for objects with true transparency, like smoke, fog and many other special effects. This is something that I don't think can be reasonably solved with SSR, and indeed we haven't in Blightbound. If you look closely, you can see that some objects aren't reflected at all because of this. However, in most cases this isn't noticeable because if there's an opaque object closely behind it, then we'll see the special effects through that. While quite nonsensical, in practice this works so well that it seems as if most explosions are actually reflected correctly.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><img border="0" data-original-height="234" data-original-width="484" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCTAmja_FMOWj2hj36XnW53orOXes6J4bZ8hdgAqGnY49CBv1fZmk8nkA5IKgLiIOKi3tHlQ17v89yFrIvYPFPwez83S428uNgWhyphenhyphenisMi17K29Tt6HO51KLRYCzein5SGoNlG2gNTNTQ1I/s16000/SSR+-+No+alpha+reflections.gif" /></div><div style="text-align: center;"><i>Transparent objects like this fire aren't in the depth buffer and thus can't be found for reflections. However, if another object is close behind, like the character on the left, then the transparent object is reflected through that. The result is that it seems as if many special effects are properly reflected.</i></div><div><br />Having perfectly sharp reflections looks artificial and fake on many surfaces. Reflections in the real world are often blurry, even more so the further the reflected object is from the surface. To get reflections that accurately blur with distance I've applied a simple trick: the rays get a slight random offset applied to their direction. This way objects close remain sharp and objects get blurrier with distance. Artists can tweak the amount of blur per object.</div><div><br /></div><div>However, this approach produces noise, since we only cast one ray per pixel. We could do more, but that would be really heavy on performance. Instead, to reduce the noise a bit, when far enough away I also sample from a low-resolution blurry version of the scene render-texture. This is a bit redundant but helps reduce the noise. Finally, by default in Blightbound we do supersampling anti-aliasing (SSAA) on the screen as a whole. This results in more than one ray being shot per screen-pixel. Only on older GPUs that can't handle SSAA is this turned off.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><img border="0" data-original-height="574" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRHo00fOEF1wO1pJ6EQ9rS9dkkvlcNK8h6z_bK28VtyUbfB_sKdm6eXo7vuX7ng0H5Q5QVb2fzOeP4JE_ccSi5-aH3l5_aml9s1ysnvO8el_GyP5hwAMbkdmXyBMbHMYkEjHDGendXzn5Z/s16000/SSR+-+Blur.jpg" /></div><div><br />Another issue is precision. For really precise reflections, we would need to take a <i>lot</i> of samples along the ray. For performance reasons that's not doable though, so instead we make small jumps. This however produces a weird type of jaggy artefacts. This can be improved upon in many different ways. For example, if we would render the reflections at a lower resolution, we would be able to take a lot more samples per ray at the same performance cost. However, with how I implemented SSR into our rendering pipeline that would have been quite cumbersome, so I went for a different approach which works well for our specific situation:</div><div><ul style="text-align: left;"><li>More samples close to the ray's origin, so that close reflections are more precise.</li><li>Once the intersection has been found, I take a few more samples around it through binary search, to find the exact reflection point more precisely. (The image below is without binary search.)</li><li>The reflection fades into the fog with distance. This way the ray never needs to go further than a few meters. This fits the world of Blightbound, which is basically always foggy.</li></ul><div>The result of these combined is that we get pretty precise reflections. This costs us 37 samples along a distance of at most 3.2 meters (so we never reflect anything that's further away than that from the reflecting surface).</div><div><br /></div><div>Any remaining imperfects become entirely unnoticeable since blur and normal maps are often used in Blightbound, masking any artefacts even further.</div><div><br /></div><img border="0" data-original-height="574" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiLM2ZFm9BulZjx2VJwpA_wX1Jb9KzhJYSv9rBB0AIve7smE-COPoijdw_HrD8RmmFEbVL1W8nQJn-HOW3DRKkOwHJtOlzAXl-WEnAI59VbjptuaYzHml6y0Jnm2dV5fPMoxnW6sHKyQPE/s16000/SSR+-+Samples.jpg" /><br /><br />A challenge when implementing SSR is what to do with a ray that passes behind an object. Since our basic hit-check is simply whether the previous sample was in front of an object and the next one is behind an object, a ray that should pass behind an object is instead detected as hitting that object. That's unintended and the result is that objects are smeared out beyond their edges, producing pretty ugly and weird artefacts. To solve this we ignore a hit if the ray dives too far behind an object in one step. This reduces the smearing considerably, but the ray might not hit anything else after, resulting in a ray that doesn't find an object to reflect. In Blightbound we can solve this quite elegantly by simply using the level's fog colour for such failed rays.</div><div class="separator" style="clear: both; text-align: center;"><br /><img border="0" data-original-height="195" data-original-width="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE6QHKqn3f5HsjYU2qfWQkNf0LcG1Drl8CDjsmLgmUW_Pl36iSd9n1yF_3MjwBmuBfFOEovPjxeDE9KPrD9f9owPLHCaUDEPExKf1mjNIBQugd-Wv0hBYS9cTxFiT54dRWfnbd11HKPeIz/s0/SSR+-+Smearing.gif" /></div><div style="text-align: center;"><i>By default, SSR produces these kinds of vertical smears. Assuming objects have a limited thickness reduces this problem greatly, but adds other artefacts, like holes in reflections of tilted objects.</i></div><div style="text-align: center;"><br /></div><div>This brings us to an important issue in any SSR implementation: what to do with rays that don't hit anything? A ray might fly off the screen without having found an object, or it might even fly towards the camera. Since we can only reflect what we see, SSR can't reflect the backs of objects and definitely can't reflect anything <i>behind</i> the camera. A common solution is to have a static reflection cubemap as a fallback. This cubemap needs to be generated for each area so that the reflection makes sense somewhat, even if it isn't very precise. However, since the world of Blightbound is so foggy I didn't need to implement anything like that and can just fall back to the fog colour of the area, as set by an artist.</div><div><br /></div><div>The final topic I would like to discuss regarding SSR is graphics quality settings. On PC users expect to be able to tweak graphics quality and since SSR eats quite a lot of performance, it makes sense to offer an option to turn it off. However, what to do with the reflecting objects when there's no SSR? I think the most elegant solution is to switch to static cubemaps when SSR is turned off. Static cubemaps cost very little performance and you at least get some kind of reflection, even if not an accurate and dynamic one.</div><div><br /></div><div>However, due to a lack of time that's not what I did in Blightbound. It turned out that just leaving out the reflections altogether looks quite okay in all the spots where we use reflections. The puddles simply become dark and that's it.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><img border="0" data-original-height="470" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_Ycpd8ttWLdGP5Sz_WHNA7qQbNLfMZtMsrDTqxWEB22Iv0sAuJSV4bYgnKSkjbw4W-uqCMZZb55a5EUhs5ujumaz3xSHOq7cD351EUw0V6aV9RC4MbNPa-l70ZETSgFT1qcevr1Xmep3z/s16000/SSR+-+Setting+off.jpg" /></div><div><br /></div><div>For reference, <a href="http://www.proun-game.com/Oogst3D/BLOG/SSR%20-%20Ronitech%20shader%20code.txt" target="_top">here's the shader code of my SSR implementation</a>. This code can't be copied into an engine directly, since it's dependent on the right render-textures and matrices and such from the engine. However, for reference when implementing your own version of SSR I expect this might be useful.</div><div><br /></div><div>SSR is a fun technique to implement. The basics are pretty easy, and real-time reflections are a very cool effect to see. As I've shown in this post, the real trick in SSR is how to work around all the weird limitations inherent in this technique. I'm really happy with how slick the reflections ended up looking in Blightbound and I really enjoyed implementing SSR into our engine.</div></div>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com3tag:blogger.com,1999:blog-3064325214589649535.post-41323724551883825462020-09-07T14:27:00.006+02:002021-03-31T09:30:05.501+02:00The games that inspired me mostA few years ago I was asked by a videogame magazine what games inspired me most. I had a lot of fun compiling a short list for them. Today I've updated that list. These aren't necessarily my favourite games (although they're close): Doom II isn't on this list for example. I'm going to focus not on why I had fun with a game, but why it <i>inspired</i> me, how it taught me something new. They all have some unique aspects that changed how I look at games and game development.<br />
<br />
<b>Command & Conquer</b><br /><br />As a kid I was so much a fan of Command & Conquer that I even rebuilt some of its units with Lego. I started playing around with 3D computer graphics when I was only 13 years old and C&C was my big inspiration. I wanted to make 3D as awesome as in the cut-scenes for this game. Especially the video where a flame tank drives into a town and torches everything is still vividly in my mind. Many of the game designs that I wrote down on paper at this age were for RTS games inspired by C&C. <br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFy4tzo71rQyf2yimr9wiRC2tZ7RRVg01kDIMb3AG4NCW0vXCMl2Ep_nZLKCb4XO-re3nbs2BfGE3LwAN84b3vyxLTpqUgYcItvbCzsFxTCJ37ylERVIkZwk4S13da8yGT6f_yy4QU-MYS/s500/Most+inspiring+games+-+Command+and+Conquer.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="313" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFy4tzo71rQyf2yimr9wiRC2tZ7RRVg01kDIMb3AG4NCW0vXCMl2Ep_nZLKCb4XO-re3nbs2BfGE3LwAN84b3vyxLTpqUgYcItvbCzsFxTCJ37ylERVIkZwk4S13da8yGT6f_yy4QU-MYS/s16000/Most+inspiring+games+-+Command+and+Conquer.jpg" /></a><br /><br /><b>Star Control II</b><br />
<br />
This is easily my favourite game of all time. Great music, crazy humour, fun combat and a rich universe with deep backstories and tons of personality. What is most special though is that this is one of the few games I know where information and exploration are intertwined so strongly. Everything is there at the start of the game, but the universe is way too big to find things without knowing the coordinates of interesting planets. Gathering information and even buying it is a key feature here. In combination with the lack of invisible walls this makes exploration extremely rewarding and quite different from most open world games.<div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKPX2FQoXByhNSbHmQebteIUO8jxH1fxtXGxZAM88YDqJZGkLJm3lbncwM_LIvikbF4QlubZy39_7akrEUaqoDEq0AYXTIlA6Rwyc7yTv6QvPYJH47fcpblUiNCweXa6KePNxA5iJru8H_/s500/Most+inspiring+games+-+Star+Control+II.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="448" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKPX2FQoXByhNSbHmQebteIUO8jxH1fxtXGxZAM88YDqJZGkLJm3lbncwM_LIvikbF4QlubZy39_7akrEUaqoDEq0AYXTIlA6Rwyc7yTv6QvPYJH47fcpblUiNCweXa6KePNxA5iJru8H_/s16000/Most+inspiring+games+-+Star+Control+II.gif" /></a></div><br /><div>An interesting aside is that in the newly released Star Control: Origins (which I really like, by the way) some players complain about the universe being so empty that grinding through planets is boring. The problem here is that modern players have been taught that it's useful to randomly wander around the world, because most open world games these days make sure there are interesting things everywhere. That's fun of course, but that means that in a game like Fallout information isn't very important: by randomly walking around you'll likely find everything (although that does cost a lot of time). Star Control's exploration is totally different because the universe is so much bigger. I think the problem in Star Control: Origins is purely expectations: it isn't clearly communicated to players that this game is different.</div><div><br /></div><div>Another aspect of Star Control II that has greatly influenced me is the music. Each alien race you encounter has a theme song that captures the personality of that race. Music in many games (as well as movies) mostly serves to set the mood and influence the viewers emotions. But I like music that takes the foreground and really adds to the personality of the game. Inspired by the alien themes from Star Control II, I pushed for having character theme songs in our game <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a> as well. This resulted in <a href="https://sonicpicnic.nl/en/" target="_top">Sonic Picnic</a> making an amazingly diverse soundtrack for Awesomenauts, adding tons of personality.<br />
<br /><b>Bioshock</b><br />
<br />
In most games the story and the gameplay are told intertwined but are not truly related. Not in Bioshock: here the gameplay and the story revolve around a common theme. Both add meaningful insights to the concepts of freedom and choice that are explored. Bioshock is not just a marvellously fun game; it also made me ponder the philosophical themes it explores. Especially the twist halfway the game felt incredibly smart and exciting. I felt like I had personally fallen victim to exactly what had happened to the character in-game. One of the few games with true philosophical depth.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg69J4stPdTqvtUXEwM8EXrU2XqMZssKbjXMRKQ58kjZAf0Gv7hbbllRcXIqMNVKzXsWLKQKEV8H571mlR4LAEmUvON9ymcmErkBHueBuy8EuE38gNYroG4fzcURTY-pt9S6639q0ytpbLP/s500/Most+inspiring+games+-+Bioshock.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="328" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg69J4stPdTqvtUXEwM8EXrU2XqMZssKbjXMRKQ58kjZAf0Gv7hbbllRcXIqMNVKzXsWLKQKEV8H571mlR4LAEmUvON9ymcmErkBHueBuy8EuE38gNYroG4fzcURTY-pt9S6639q0ytpbLP/s16000/Most+inspiring+games+-+Bioshock.jpg" /></a></div><br /><div><b>World of Goo</b><br />
<br />
World of Goo is the ultimate example of how much creativity is needed to extend a simple and original concept to a full game. It seems to me like many of the participants of gamejams think that coming up with something original is the highest goal in game design. But much more difficult is to develop that original concept from a gimmick into a full game. World of Goo started out as a gimmicky mini-game and ended up as a glorious game. It adds enormous diversity and depth without adding a lot of features or complexity. This is true mastery of game design.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwG4LhQL8w8qVC53FHpYSBvSn1x2VYXvnoCaJWQRdVdPVjhi7rYcaGgVPeOZVbokj6aKuCT6Sb-1laSpOesniRhikbfenWShc5lmMnzD182t-zzfboltocr5qBmBvpcrU3qPWBiswiT-9t/s500/Most+inspiring+games+-+World+of+Goo.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="382" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwG4LhQL8w8qVC53FHpYSBvSn1x2VYXvnoCaJWQRdVdPVjhi7rYcaGgVPeOZVbokj6aKuCT6Sb-1laSpOesniRhikbfenWShc5lmMnzD182t-zzfboltocr5qBmBvpcrU3qPWBiswiT-9t/s16000/Most+inspiring+games+-+World+of+Goo.jpg" /></a></div><br /><div><b>Deus Ex</b><br />
<br />
The original Deus Ex is a great game in general and the combination of RPG + FPS is pure gold for my taste in games. However, the most unique thing in this game to me is the ending. Usually when games have different endings, they are very black-and-white. There are the good ending and the evil ending. Or maybe there were extra challenges and then there are a good ending and a super good ending. Not in Deus Ex: here the three endings all have up- and downsides. It's not clear which would be the best for humanity and the options are clever enough that I spent considerable time pondering each. Deus Ex has similarly deep philosophical thoughts as Bioshock, but while Bioshock is about the game manipulating the player, Deus Ex is about the player manipulating the world.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG4D5teQ8cEBbajpnGM27BXsRpBk8Yo3Z8kmZYgSDwfg4VJm5SijJj4XOrE6nwAF3dBh39hJC1a9M2_FUEehjJhX0YvGs8-oVs-7caIBRO1_DVhWSx6aOSQpzw9BvhBjiJiq4kncDpKeNF/s500/Most+inspiring+games+-+Deus+Ex.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="348" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG4D5teQ8cEBbajpnGM27BXsRpBk8Yo3Z8kmZYgSDwfg4VJm5SijJj4XOrE6nwAF3dBh39hJC1a9M2_FUEehjJhX0YvGs8-oVs-7caIBRO1_DVhWSx6aOSQpzw9BvhBjiJiq4kncDpKeNF/s16000/Most+inspiring+games+-+Deus+Ex.jpg" /></a></div><br /><div><b>Dear Esther</b><br />
<br />
A core aspect of game design to me is that a game should be fun without the graphics and the polish. If a game is already fun with just boxes, then it will be even better when visuals and sound are added. Dear Esther is a fantastic example of a game that proves me wrong. In fact, there's hardly any gameplay. But the storytelling, the music and the visuals all add up to an incredible experience. Dear Esther is also interesting in that it suggests a lot and explains very little. I played this game with my wife and we were constantly discussing what it all meant. The game continuously pushed our thoughts into different directions with new snippets of information.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXzUXSx6_khqqSnSE3_NW3pT6LLDLVlZZ6GkImRavoAEQ0A09jRp8na2VyvFQLFiOqrczSy5f1OAMfP-QrGa6vDQV2V3i471Itg1KrDPCvZicDZHMES4BeDGAVUHiqUk46aB2-DS7HiBR4/s500/Most+inspiring+games+-+Dear+Esther.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="355" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXzUXSx6_khqqSnSE3_NW3pT6LLDLVlZZ6GkImRavoAEQ0A09jRp8na2VyvFQLFiOqrczSy5f1OAMfP-QrGa6vDQV2V3i471Itg1KrDPCvZicDZHMES4BeDGAVUHiqUk46aB2-DS7HiBR4/s16000/Most+inspiring+games+-+Dear+Esther.jpg" /></a></div><br /><div><b>Railroad Tycoon</b><br />
<br />
I am a big fan of trains and always want to see more of them in games. I fondly remember Railroad Tycoon, Transport Tycoon and Sid Meier's Railroads. As a teen I wrote tons of pages of notes on an RTS that resolved around building railroads to transport resources. Trains could be armed to defend them and gather the resources needed to build an army. I doubt that game will ever happen, but anything with trains makes me all giddy with excitement. In fact, most of the game ideas I come up with today still have room for trains somewhere. I hope that in a few years I will finally have made at least one game that actually features trains!<br />
<br />
<b><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglXTox5wXm0DmalNWAKvMU6x24iz3jWWZY1UVdXQIqnUhzj0hfX2PiWSPJRMUCqLPWxy_EIXZcusOu2MUG9grL_jb70uiqaU-iX8nKaggyfLrcMrbdQibrQvLqF9vHKznbxIeZtjn2dq0k/s500/Most+inspiring+games+-+Railroad+Tycoon.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="360" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglXTox5wXm0DmalNWAKvMU6x24iz3jWWZY1UVdXQIqnUhzj0hfX2PiWSPJRMUCqLPWxy_EIXZcusOu2MUG9grL_jb70uiqaU-iX8nKaggyfLrcMrbdQibrQvLqF9vHKznbxIeZtjn2dq0k/s16000/Most+inspiring+games+-+Railroad+Tycoon.gif" /></a></div><br />Ori And The Blind Forest & Rayman Origins</b><br />
<br />
I'm grouping these two games together because they have done a similar thing: they have both raised the bar for 2D art in games. 2D art is sometimes seen as lesser than 3D art, but Ori and Rayman have shown that it's possible for a 2D game to have the appeal of a big AAA production. At <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a> we have studied the animation, special effects and level art in these two games in detail to see what techniques we could apply to our own games.<br />
<br />
<b><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKov6lgWjzwL028IaTTCoF1W_mLnaczqmsdyHpHQdJ8BgukuvXvlha20SeRNUqwopvTzKcCiz_hfUh4SBJd5wjz9j7v4HXZDfW6bvbwnSkPEK80GDg8-Pt3XGdiI50rrF_MU0dkBcEyWi9/s500/Most+inspiring+games+-+Rayman+Origins.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKov6lgWjzwL028IaTTCoF1W_mLnaczqmsdyHpHQdJ8BgukuvXvlha20SeRNUqwopvTzKcCiz_hfUh4SBJd5wjz9j7v4HXZDfW6bvbwnSkPEK80GDg8-Pt3XGdiI50rrF_MU0dkBcEyWi9/s16000/Most+inspiring+games+-+Rayman+Origins.jpg" /></a></div><br />Braid</b><br />
<br />
Of all the games in this list, Braid has probably influenced me most, and on several levels. For starters, Braid introduced us to the concept of self-publishing and indie development. Xbox Live Arcade had been around for a little while already but Braid, World of Goo and Castle Crashers really showed us the potential of indie and self publishing. When we started Ronimo we thought we needed to make disk based full price games. This was however not a path we were succeeding at so when we realised that we could do what these games were doing, we adjusted our plans and made a smaller game on our own instead. This became our first commercial release: Swords & Soldiers on Nintendo Wii.</div><div>
<br />
Braid also influenced me on a more personal level. My interpretation of Braid's story is that it's not about an actual princess, but about the danger of looking for perfection. The main character has a girlfriend, but he breaks up with her because she isn't perfect. So he looks for the perfect woman, his 'princess'. But he doesn't find her because no one is perfect. The result is that he's alone and doesn't have his actually quite wonderful girlfriend anymore. In the epilogue the game also mentions other examples of the dangers of obsessing over perfection, like a scientist looking for the perfect science but creating the nuclear bomb as part of the Manhattan Project.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtIl6pXInWAre67BVxT5yNk-FxuvlQlU7U87gR7OPKYlaG4GDqR_JxGUC0AAAVx3BEjlJBFxHl1geLn4hvdgEeEFzcyjeM4Wicw5Ij1734aL0zJxeLw2yk5lQsIipPVsmW56tw_pQhysB0/s500/Most+inspiring+games+-+Braid.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="242" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtIl6pXInWAre67BVxT5yNk-FxuvlQlU7U87gR7OPKYlaG4GDqR_JxGUC0AAAVx3BEjlJBFxHl1geLn4hvdgEeEFzcyjeM4Wicw5Ij1734aL0zJxeLw2yk5lQsIipPVsmW56tw_pQhysB0/s16000/Most+inspiring+games+-+Braid.jpg" /></a></div><br /><div>I don't know whether the story was truly meant like this, but this interpretation has greatly influenced me in my view on both creativity and life. Perfection is an impossible goal so striving for it only hampers you. Perfectionism causes you to spend too much time looking for an even better game concept to make, or endlessly iterating your game instead of releasing it and making another, or breaking up with your partner instead of making it work. Braid has truly changed my mindset in what to strive for in life and work.</div><div>
<br />
So, that's it: the games that inspired me most! What games changed your view on games or the world?</div>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com2tag:blogger.com,1999:blog-3064325214589649535.post-13215251427923021482020-08-09T15:30:00.002+02:002020-08-09T15:30:48.685+02:00Three nasty netcode bugs we fixed around Blightbound's launchIn the weeks before and after the Early Access launch of our new game <a href="https://www.blightbound.com/" target="_top">Blightbound</a> we've been fixing a lot of bugs, including 3 very stubborn netcode bugs. They weren't any fun while we were looking for them for days, but now that we've found and fixed these they're actually quite intriguing. So today I'd like to share 3 of the more interesting bugs I've seen in the past few years.
<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9KTxiAyEAV3nA5t2pM4XqDCpYL_tI-B5QXfcZ5SaePM7kmJbIRMzFa5Fau0wKtZ_T6_KzE-YYpDHtnIHMTMO4Ov3QpOHAg3iDAKOsMQ4_WCgNTQ1qGDBFMycc75gtPcVqqmO4FqSojmEL/s500/Netcode+bugs+-+Blightbound.jpg" style="display: block; padding: 1em 0px;"><img border="0" data-original-height="326" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9KTxiAyEAV3nA5t2pM4XqDCpYL_tI-B5QXfcZ5SaePM7kmJbIRMzFa5Fau0wKtZ_T6_KzE-YYpDHtnIHMTMO4Ov3QpOHAg3iDAKOsMQ4_WCgNTQ1qGDBFMycc75gtPcVqqmO4FqSojmEL/s0/Netcode+bugs+-+Blightbound.jpg" /></a>While these bugs mostly say something about issues in our code, I think they're also nice examples of how complex low level netcode is, and how easy it is to make a mistake that's overlooked for years, until a specific circumstance makes it come to the surface. All three of these bugs were also in the code of our previous game <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a>, but none of them actually occurred there due to the different circumstances of an Awesomenauts match compared to a Blightbound party.
<br />
<br />
The one thing all three of these bugs have in common is that they were very hard to reproduce. While they happened often enough to be game-breaking, they rarely happened in testing. This made them very hard to find. For the first two we found a way to reproduce them after a lot of experimenting, while for the final one we never got it ourselves until we had figured out the solution and knew exactly how to trigger it. Finding that one without being able to see it was some solid detective work by my colleague Maarten.<br />
<br />
<h2>Endless loading screens number 1</h2>
<br />
This bug occasionally caused clients to get stuck in the loading screen forever. After adding additional logging we saw that the client never received the HostReady message. This is a message that the host sends to the clients to let them know that loading is done and they should get into the game. The client was forever waiting for that HostReady message. Upon further investigation it turned out that the host did actually send the message, but the client received it and then threw it away as irrelevant. Why was that? <div>
<br />To answer that question, I need to give some background information. An issue with the internet is that it's highly unreliable. Packets can be lost altogether and they can also come in out-of-order or come in very late. One odd situation this can cause, is that a message from a previous level can come in once you're already in the next level, especially if loading times are very low. Applying a message from the previous level to the next level can cause all kinds of weird situations, so we need to recognise such an outdated message and throw it away. We do this with a simple <i>level ID</i> that tells us which level the message belongs to. If we get a message with the wrong level ID, we discard it.<div><br /></div><div>That's simple enough, but we saw that both client and host were in the loading screen for the next level. Why then would the client discard the HostReady message as being from the wrong level? The reason turned out to be in our packet ordering system. Some messages we want to process in the order in which they are sent. So if one message goes missing, we store the ones after it and don't process them until the previous missing one is received and handled.</div><div><br /></div><div>The bug turned out to be in that specific piece of code: the stored messages didn't store their level ID. Instead, when they were released, we used the level ID for the message that had just come in. This went wrong when a message from the previous level went missing and came in a second or two too late. By that time the HostReady message had already been received, but had been stored since it needed to be processed in order. Since the level ID from the previous room was used for all out-of-order messages, the HostReady message was processed as if it came from the previous room. Thus it was discarded.</div><div><br /></div><div>I imagine reading this might be mightily confusing, so hopefully this scheme helps explain what went wrong:</div><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBDFrUSCk6349GQoxTZ_v3RgSV2z7w1kJ4eHZ9bPzHx8DQAe3Chv_7Dklk8YLr7zu3CqItf27pW2TzRl6aRqYJO2Yv3-1e5-y5xnMyj6WKS1Rjiayp2syLrPbTf2tnGQ0Fwm4cDBGooEFE/s737/Netcode+bugs+-+out-of-order.gif" imageanchor="1" style="display: block; padding: 1em 0px;"><img border="0" data-original-height="737" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBDFrUSCk6349GQoxTZ_v3RgSV2z7w1kJ4eHZ9bPzHx8DQAe3Chv_7Dklk8YLr7zu3CqItf27pW2TzRl6aRqYJO2Yv3-1e5-y5xnMyj6WKS1Rjiayp2syLrPbTf2tnGQ0Fwm4cDBGooEFE/d/Netcode+bugs+-+out-of-order.gif" /></a></div><div style="text-align: center;"><br /></div><div>Once we had figured this out, the fix was simple enough: store the level ID with each message that is stored for later processing, so that we know the correct level ID when we get to it.</div><div>
<br />
<h2>Endless loading screens number 2</h2>
The second loading screen bug we had around that time had a similar cause, but in a different way. When a client is done loading, it tells the host so in a ClientReady message. The host needs to wait for that. Similar to the bug I described above, the ClientReady message was received but discarded because it was from the wrong level. The cause however was a different one.</div><div><br /></div><div>Sometimes the client starts loading before the host, for whatever reason. Since loading times between levels are very quick in Blightbound, the client can be done loading before the host starts loading. Once the client is done loading, it sends the ClientReady message. However, if the host isn't loading yet and is still in the previous room, then it discards the ClientReady message because it's from the wrong room. A moment later the host starts loading and when it's done loading, it starts waiting for the ClientReady message. Which never comes because it was already received (and discarded).</div><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_IOnGlmvzugmu2L3ROG6_9Q2PLgrw0j6cK3YEeQEhcO3EheUxlEVBPfiwabsv9YcgVwCTU27ThCSa-K11Pqha7doS7SHwTqWJ6-fPAn1dHc32aWJMseTuE2Owear0Du7Aq7AlbhW1VfAS/s500/Netcode+bugs+-+client+too+early.gif" imageanchor="1" style="display: block; padding: 1em 0px;"><img border="0" data-original-height="339" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_IOnGlmvzugmu2L3ROG6_9Q2PLgrw0j6cK3YEeQEhcO3EheUxlEVBPfiwabsv9YcgVwCTU27ThCSa-K11Pqha7doS7SHwTqWJ6-fPAn1dHc32aWJMseTuE2Owear0Du7Aq7AlbhW1VfAS/d/Netcode+bugs+-+client+too+early.gif" /></a></div><div><br /></div><div>Here too the solution was pretty straightforward. We first changed the level ID to be incremental (instead of random) so that we can see in the level ID whether an incorrect message is from the next or the previous room. If it's from the previous room, we still discard the message. But if the message is from the next room, we store the message until we have also progressed to that room, and then process it.</div><div><br />
<h2>The big desync stink</h2>
<br />The final netcode bug I'd like to discuss today is rather painful, because unlike the others it still existed at launch. In fact, we didn't even know about it until a day after release. Once we knew it existed it still took us days to find it. In the end this one was fixed in update 0.1.2, six days after launch.</div></div><div><br /></div><div>So, what was the bug? What players reported to us was that randomly occasionally the connection would be lost. In itself this is something that can happen: the internet is a highly unreliable place. However, it happened way too often, but never when we tried to reproduce it, not even with simulated extremely bad connections. Also, we have code that recognises connection problems, but this bug didn't trigger that code, so the game thought it was still connected and kept playing, with very odd results.</div><div><br /></div><div>After a few days a pattern started to emerge: many players reported that this always happened once they had notoriety 3 or 4, when a legendary item was attainable. We didn't think that the bug was actually linked to notoriety or legendary items, because these are quite unrelated to netcode. Instead, we suspected something else: maybe the bug happened after playing together for a certain amount of time.</div><div><br /></div><div>With this hypothesis in hand we started looking for anything where time matters. Maybe a memory leak that grew over time? Or, more likely: maybe some counter that looped incorrectly? As I described in the above issues, netcode can have many types of counters. I already described the level ID counter and the counter for knowing whether a message is received in-order. There are others as well.</div><div><br /></div><div>The thing with data that is sent over the netwerk is that it needs to be very efficient. We don't want to send any bytes more than necessary. So whenever we send a counter, we use as few bits as possible. Why send a 32 bit number when 16 bits will do? However, when using smaller numbers they will overflow more quickly. For example, a 16 bit number can store values up to 65,535. Once we go beyond that, it loops back to 0.</div><div><br /></div><div>Often looping back to 0 isn't a problem: the last time we received the lower packets is so long ago that we won't have to expect any overlap with the last time we used number 0. However, we do need to handle the looping numbers correctly and not blindly throw away number 0 because it's lower than number 65,535.</div><div><br /></div><div>And this indeed turned out to be the problem. One of the counters we used was a 16 bit number and after about one hour it looped back. In that particular spot we had forgotten to include code to handle that situation. The result is that from there on the game received all messages but discarded them without applying them. Like in the cases above, the solution was simple enough to implement once we knew what the problem was.</div><div><br /></div><div>One question remains: why wasn't this a problem in Awesomenauts? For starters, Awesomenauts matches are shorter and the connection is reset after a match. So the counter never reaches 65,535. In Blightbound however the connection is kept up in between dungeon runs, so if players keep playing together the number will go out of bounds. But there's more: if the bug would have happened in Awesomenauts, the game would have thought it was a disconnect and would have reconnected, resetting the counter in the process. In Blightbound we determine connection problems in a different way, causing the connection to not be reset in this particular case.</div><div><br /></div><div><br /></div><h2 style="text-align: left;">A lesson relearned</h2><div><br /></div><div>Netcode being hard is not new to us and getting weird bugs is inherent to coding such complex systems. However, there is one step we did for Awesomenauts that we didn't do here: auto testing. Since Blightbound uses a lot of netcode from Awesomenauts and Awesomenauts has been tested endlessly, we thought we didn't need to do extensive auto testing for this same code in Blightbound. This was a mistake: the circumstances in Blightbound turn out to be different enough that they cause hidden bugs to surface and wreak havoc.</div><div><br /></div><div>We're currently running autotests for Blightbound to further stabilise the game. This already resulted in another netcode fix in <a href="https://www.blightbound.com/game-updates">update 0.1.2</a> and several obscure crash fixes that will be in the next major update.</div><div><br /></div><div>To conclude I'd like to share this older but still very cool video of auto testing in Awesomenauts. It shows four computers each randomly bashing buttons and joining and leaving matches. The crazy movement of the Nauts is fun to watch. For more details on how we implemented auto testing in Awesomenauts, have a look at <a href="http://joostdevblog.blogspot.com/2014/06/finding-bugs-through-autotesting.html">this blogpost</a>.</div><div><br /></div>
<iframe allow="autoplay; encrypted-media" allowfullscreen="" frameborder="0" height="281" src="https://www.youtube.com/embed/X1JtbZIzEUw" width="500"></iframe><br /><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;"><br /></div>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-90821632775316464172020-08-04T21:03:00.003+02:002020-08-05T10:58:26.148+02:00Blightbound OUT NOW! Early Access on Steam!Last Wednesday our new game <a href="https://store.steampowered.com/app/1263070/Blightbound/" target="_top">Blightbound</a> launched on Steam in Early Access! This is a super exciting moment as this is our first new IP to release in 8 years. We've been developing Blightbound for nearly 3 years now and it's really special to finally have the game live and see the community play it! Here's our launch trailer:<br />
<br />
<iframe allow="autoplay; encrypted-media" allowfullscreen="" frameborder="0" height="281" src="https://www.youtube.com/embed/WAENshLjbBE" width="500"></iframe><br />
<br />
We have big plans for this game in Early Access. As the <a href="https://www.blightbound.com/roadmap" target="_top">roadmap</a> shows we have a ton of things in development to improve and expand the game. Since this is an Early Access release, there are plenty of fixes and improvements to be made to the game and the first two <a href="https://www.blightbound.com/game-updates" target="_top">hotfixes</a> have already released.<br />
<br />
Through many years of expanding <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a> we've gained a lot of experience running a live game and responding to the community and we plan on applying all of those lessons here. Robin and I did a talk on <a href="https://www.youtube.com/watch?v=Frycqo2f6JY" target="_top">Games As A Service</a> a few years back at Steam Dev Days and it's fun to be able to get back to that.<br />
<br />
For example, during the first period of Awesomenauts live-ops we didn't really brand our patches and didn't distinguish between fixes and content drops. Here we're doing that right away: hotfixes happen in between and don't contain new content, while major updates get a name and branding and a strong dosis of new stuff to keep players interested and bring players back who had seen it all already. Updates will even come with their own accompanying short stories, written by Roderick Leeuwenhart. The launch story, named "<a href="https://www.blightbound.com/stories" target="_top">Forging Ahead</a>", is already live on our website and more will follow in the coming period.<br />
<br />
Now that the game is out there, I'm also able to write more about it. In the coming period I hope to find the time to talk about how things were built, since there are tons of interesting topics to discuss! We've even already encountered our first set of blog-worthy networking bugs, so I think I'll start there in my next blogpost.Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-15321652521132109952020-06-14T10:58:00.002+02:002020-09-08T20:04:03.043+02:00Blightbound gameplay revealed!Yesterday during the PC Gaming Show the gameplay for our new game Blightbound was revealed! We've been working on this game for nearly 3 years now, so it's really cool to finally show it to the world.<br />
<br />
<iframe width="500" height="281" src="https://www.youtube.com/embed/D6Fu1uReqfU" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><br />
<br />
Blightbound is a multiplayer dungeon crawler that tasks three heroes to venture down from their mountain refuge to face the abominations of the Blight - a mysterious and corrupting fog that enshrouds the land.<br />
<br />
I've personally been having a lot of fun with the tech for the characters. Since <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a> characters are sprites they can't be big and they can't be really high framerate: that would just use too much texture memory. We wanted to fix these problems for Blightbound so I've implemented a new system that does allow us to do screen-filling bosses at high framerate. I've also implemented tech for doing real-time lighting on 2D characters with real volume and depth, instead of just lighting them as flat cut-outs as would be the obvious way to light 2D elements in a 3D world.<br />
<br />
And that's just a few of the things I've personally worked on. <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a> is currently 29 people so there are tons of interesting things the rest of the team has been making for Blightbound! This is by far the biggest game we've made so far and I'm really happy with how it's all turning out.<br />
<br />
Last month we also released a story trailer:<br />
<br />
<iframe width="500" height="281" src="https://www.youtube.com/embed/b2GKhxVYELE" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><br />
<br />
There's a lot of interesting development stuff so I hope I can find the time to write a series of blogposts on specific aspects of Blightbound development in the future.Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-37601596659857791292020-06-09T14:42:00.003+02:002020-06-09T14:42:54.890+02:005 tips for reducing stress as a game company ownerBeing a company owner can be a stressful occupation. Your decisions can make the company successful or run it into the ground. There's plenty one can worry about: the game market is constantly changing, so what's the best strategy to follow? How to handle when a co-owner wants something different than you? Mistakes can cost you both your livelihood and your dreams: after all, most people who start a game company do so because they have a passion for doing their own thing. Oh, and if you have employees, you're responsible for their fate as well!<br />
<br />
While such topics can indeed cause a lot of stress, I have been relatively relaxed under all of that for the past 13 years. So I was wondering: do I have any mental tricks that help me cope with all of it? Turns out I do! Here are 5 things that I do that help me experience less stress. I hope sharing these can help make entrepreneurship a slightly more chill experience for others as well.<br />
<br />
Before I continue I should mention that there are many other factors that determine how stressful it is to run a business. For example, I've always made sure to live slightly cheaper than I could afford so that I could build up savings for cases of economic hardship. This post is not about such financial choices. This post is also not about how a successful game launch or signing a good publishing deal will alleviate stress. Nor is it about raging communities review-bombing your game over a single removed feature or seeing company finances being only a few months from bankruptcy. At <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a> we've experienced all of these things and much more over the past 13 years and while the things I'll discuss in this post have definitely reduced the stress a lot for me personally, it's been an emotional rollercoaster nevertheless! This post however is about coping with the day-to-day, constant pressure of running a business.<br />
<br />
Also, one more side note: I wrote most of this post half a year ago and held back on posting it because one of my colleagues got a burn-out just before I got around to publishing this article. This post isn't about that colleague at all, but it seemed rather insensitive to post anything about stress right after that so I shelved this one. Now that that's a little bit less recent I feel I can post this. In a way it's even more reason to post this, since it shows just how stressful things can be!<br />
<br />
<h3>1. Figure out why the worst-case is still nice</h3><br />
To me the most important element of being relaxed when I'm afraid things might go wrong, is to figure out why the worst case would actually still be pretty nice. This way regardless of whether something is a success or not, I can always be happy about it. One of the easiest examples for this is that if your game fails to sell well, at least you can be proud of finishing and releasing your own game. That's pretty amazing by itself!<br />
<br />
The point where this made the biggest difference for me, was when we started Ronimo. Something I wondered about back then was: what if we would work on a game for a year or two but then can't find a publisher so it would end there? No game released, no income for two years, company gone. That's pretty bad, right? Well, actually, to me back then even that scenario wasn't a nightmare. Making games was (and is) my dream job and making my own games with my friends is one of the best things in the world. In the worst case I would still have done the coolest thing for a year or two. That's pretty neat even if it hadn't been a success!<br />
<br />
Another example of this way of thinking is more recent. The owner of another studio told me they were really stressed out over the idea that if their company would go bankrupt, their employees would loose their jobs. That's a huge responsibility and indeed a horrible thing if it happens! However, even here I would argue that the worst case still has a silver lining. If you had never started your company, those people wouldn't have had that job in the first place. Even if it ends, you as the studio owner have provided them with an awesome job for years. You'll have given them a chance to gather a lot of experience that will go on their resume and with which they can get their next job. This may sound crude and even though it stinks if it ends, being able to have done that even for a few years is already an amazing thing to have achieved!<br />
<br />
<h3>2. Better to make a wrong decision than no decision</h3><br />
An easy trap to fall into when being responsible for big decisions is to analyse them into infinity. "<i>Maybe if we gather some more information, we can make a better choice.</i>" "<i>Maybe if we discuss it a bit longer, we'll all agree on the next decision.</i>" While it's certainly true that important decisions need to be researched and discussed thoroughly, it's also important to <i>act</i>. Try things. Experiment. Don't get stuck in decision paralysis.<br />
<br />
As Asimov wrote in his Foundation series (which just so happen to be among my favourite books):<br />
<br />
"<i>To succeed, planning alone is insufficient. One must improvise as well.</i>"<br />
<br />
Often it's better to try something and see whether it works, than to endlessly think about what the best choice is. In game design this is an obvious rule that most people know: prototype, experiment, test, iterate. What you may not realise is that this same mindset can be applied to business as well. The key here is to not just act, but also constantly evaluate whether what you're doing works. If it doesn't, then change it. Don't be afraid to make mistakes and don't be afraid to admit that you've made a mistake. It's far better to fix it afterwards, than to pretend it didn't happen.<br />
<br />
For example, we released many updates to <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a> and often we would debate how to communicate about them. What would be the best marketing strategy for an update? However, far better than that was to simply try things and if it didn't work, try something different with the next update.<br />
<br />
Another example is a lot more mundane. At Ronimo our daily lunch with the entire team is a coveted tradition (pro-Corona, that is). However, now that we're growing it becomes impractical to let the entire team lunch at the exact same time. So it was suggested that we should spread the lunch period so that people don't all lunch at the exact same time anymore. Some of the owners of the company (including me) really disliked this idea since it seemed to go pretty strongly against Ronimo's very DNA. However, instead of debating this forever, it was decided to just give it a try and evaluate afterwards. Now that we've tried this, it turns out this not only solves the overcrowded lunch, but also solves the issue that the same cliques formed daily at the lunch table. Now that people are moving in and out of the lunch, where people sit is much less static. Even I now think the spread lunch period is an improvement! If we had tried to make a final decision on this topic before trying it, then I doubt it would have happened at all.<br />
<br />
<h3>3. Ask lots of advice</h3><br />
Whatever you're doing, someone is bound to have tried something similar before, especially when it comes to the business side of running a game studio. Hearing their experiences is an invaluable source of information for making better decisions yourself.<br />
<br />
You may think the games industry is pretty closed off, with all those NDAs (Non-Disclosure Agreements), press embargoes and secretiveness around new games. However, towards fellow devs many game studios are a lot more open. I've often emailed other studios, asking them how they approached something, and often I got really in-depth answers, sometimes even including offers for Skype calls. Of course this is easiest if you know someone at the studio or know someone who can introduce you, but in some cases I've even cold-emailed someone I didn't know at all and still got an insightful answer. And if you think that only goes for indie developers, think again: I know some people at AAA studios and even they were happy to give us advice on topics we struggled with ourselves.<br />
<br />
Just keep in mind: be respectful of other people's time and don't go prying just out of curiosity. If you have a real question, ask it and learn from their experiences.<br />
<br />
You may wonder how to do something back for people who share their knowledge. Often that's difficult because in many cases the person who gives advice is more experienced than you are or might just not be in need of your own knowledge. In my opinion that's fine. Instead of doing something for them, <i>pay it forward</i>: help someone else when you can and ask nothing in return.<br />
<br />
<h3>4. Don't feel responsible for everything</h3><br />
A common pitfall when running your own company is that you feel responsible for <i>everything</i>. After all, it's your own company, or at least it partially is. While this may work at first, it's also a great way to get a burn-out, especially as the company grows. Once you employ a dozen people, it's impossible to check all the details of everything they do. Trying to do so costs too much time and distracts you from your own work. You'll simply have to trust them to do their work well and only check on some parts of it.<br />
<br />
My own approach to this is that when a new programmer joins our team, during the initial period I review all their code. Then, as they get more experienced with our way of working and thus the amount of feedback I give decreases, there comes a point where I rarely check their code anymore at all. The key in my experience is that while that first period might be time-consuming and maybe even frustrating for both parties, it sets clear expectations as to what I expect in terms of code quality, working method and coding style.<br />
<br />
Letting go can be really hard. The boss of another studio recently had a nice way of explaining why you need to do so anyway. He said something along these lines: "<i>Previously I did everything myself. Now I employ dozens of people and don't have the time to code much myself anymore. This was frustrating, until I realised that all those people are working for me. Previously I could spent months making one thing. Now I tell all those people what to work on, and a few months later many things are done. Much more than I could ever do on my own. In a sense, while I don't do those things myself anymore, I've gotten more productive than ever.</i>"<br />
<br />
<h3>5. Accept that things won't always go your way</h3><br />
Most people who start a game company do so with a few co-founders: often there are 2 to 4 founders. In our case we went a little over-the-top and started the company with no less than 7 founders, all with equal ownership rights over Ronimo Games. I've often been asked how we managed to make this work: seven captains on a ship is a whole lot and they're bound to all steer the boat in a different direction. That's bound to produce a lot of friction.<br />
<br />
The reason this has worked for us for over a dozen years now, is that having such a big group of founders meant that we immediately ran into disagreements but needed to make decisions anyway. So we decided that if we don't agree on something, we'll just decide by voting. In practice that means that a lot of times we make decisions that I personally don't agree with. Realising this early on also made me accept this early on. Once you've accepted that many decisions will not be exactly what you want them to be, it becomes a lot easier to cope with this.<br />
<br />
I expect smaller groups of founders will often have this problem to a lesser degree: it's easier for 3 people to share the same opinion than for 7. However, that also means that when you don't agree, a group of 3 founders might also be more likely to get into a fight over it, resulting in lots of frustration and stress. So I think that even for smaller groups of founders, it's crucial to accept early on that even though it's your own company, it will not always go according to your own plan.<br />
<br />
Note that this mindset will also help when dealing with employees. To make talented people shine, you have to give them some room to express their own creativity and ingenuity. This also means occasionally letting something happen even though you disagree with it. As a boss you may technically have the right to force your own decisions on your employees, but sometimes it's better not to.<br />
<br />
Regardless of your mindset, there's bound to be stress involved when starting and running your own (game) company. However, the things I've listed in this post have greatly helped me cope with it all and have made me relaxed most of the time. What are your tricks to reduce stress and stay chill?Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com2tag:blogger.com,1999:blog-3064325214589649535.post-45295164905214537622020-05-24T18:14:00.003+02:002020-05-24T18:14:48.370+02:00Then the Halls Were Empty... and I Turned It On!I've finished a new song! It's an instrumental that tells a little story. This composition is the centrepiece for my album: here the gate that it's all about is opened for the first time, into who-knows-where. After this the real drama starts: the next song is about how the entire facility needs to be destroyed in order to stop creatures from flooding in!<br />
<br />
<iframe width="500" height="281" src="https://www.youtube.com/embed/3ixQTpiQ86M" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><br />
<br />
The first 2 minutes of this song actually started as the soundtrack for a cancelled <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a> game, all the way back in 2012. I wrote a few short pieces for that and this one made it in. I started by building a rhythm from workshop sound effects, like a tape-measure sliding back in, and then composed the rest from there. While the atmosphere worked really well with our game prototype, the rhythmic sound effects turned out to be problematic: the game also had real sound effects and that didn't combine well. So I simply removed the rhythmic part from my song and then it sounded good in the game. I think this is a beautiful example of how creativity and iteration work: the things you make serve a purpose in the process, even those that get scrapped in the end.<br />
<br />
When that game was cancelled, this track went into the fridge. Nevertheless it remained one of my favourite tracks and I came back to listen to it quite often. I wanted to do something with it, but didn't know what. Back then it was only 1:50 minutes long and that felt too short to be 'finished'.<br />
<br />
Then I heard <a href="https://www.youtube.com/watch?v=Is_2Ng2-yIY" target="_top"><i>Home By The Sea</i></a> by Genesis. I'm a huge fan of Genesis so it's not rare for me to listen to their music, but this particular time I suddenly realised that I could try doing the same structure for my own song. Home By The Sea is basically two songs in one: it starts as a pop song but halfway it quiets down and then at 5:07 a big beat sets in and it becomes an amazing instrumental. I wanted a similar transformation in my own song! So I tried emulating that vibe, but I failed and it doesn't sound anything like the original. In this case however it did capture something else: I really liked the resulting sound! To me that's another great example of how creativity can work: take an inspiration and then morph it into something completely different to make it your own.<br />
<br />
I continued from there, turning it into a 6:25 minutes long piece. That actually makes it my longest composition since I was in a prog-rock band over 15 years ago.<br />
<br />
For the title I drew some more inspiration from Genesis. The original title of my song was "<i>And Then The Halls Were Empty</i>", but the more active second part didn't fit that quiet title anymore, so I needed to add something. Genesis has a wonderful pair of songs called "<i>Unquiet Slumbers for the Sleepers...</i>" and "<i>...In That Quiet Earth</i>". I figured I could do something similar with the title of my song, hence the ellipsis (...) in my title. (Note that the second half of the title also sounds a whole lot like another Genesis song, but that's actually a coincidence that I didn't notice until I started writing this blogpost.)<br />
<br />
The inspiration for the final bit (starting at 3:44) comes from the song <a href="https://youtu.be/9eld5QZobRU?t=206" target="_top"><i>Prelude 1</i></a> by Floex and Tom Hodge. Here the result is closer to the inspiration, but I feel my composition is different enough that it's become its own thing. I actually met Floex (Tomáš Dvořák) at a conference a few years ago and was fan-boying to the max, since his soundtrack for Machinarium is one of my favourite game soundtracks. Especially the second half of <a href="https://www.youtube.com/watch?v=dy8HXFrqpCI" target="_top">The Glasshouse With Butterfly</a> is mind-blowingly beautiful. Turns out Tomáš Dvořák is also a very friendly guy to talk to. :)<br />
<br />
Since I've started the tradition of creating cello sheet music for all of my songs, I've done so for this one as well. From the perspective of the cello this isn't my most interesting composition, but if you'd like to play the cello parts, you can find sheet music and an MP3 to play along to (without the cello) on <a href="http://music.joostvandongen.com/" target="_top">music.joostvandongen.com</a>. This website also has sheet music for all my other compositions.<br />
<br />
This song actually completes the line-up for my album, which will be called "<i>The Ageless Gate - A Cello Tale</i>". All 13 songs are now complete, making for a grand total of 47:03 minutes of music. The only steps left now are mixing/mastering and making things like a cover and booklet, since I want to make a proper CD out of this one (as well as put it on streaming services like Spotify, of course).Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-641952200956111142020-03-01T12:11:00.001+01:002020-09-08T20:04:20.179+02:00How we made particles twice as fast through cache optimisationCache optimisation is one of the most hardcore, low-level topics in game programming. It's also a topic that I haven't been very successful with myself: I tried optimising for cache efficiency a few times but never managed to achieve a measurable improvement in those specific cases. That's why I was quite intrigued when our colleague Jeroen D. Stout (famous as the developer of the experimental indie game <a href="https://store.steampowered.com/app/94000/Dinner_Date/" target="_top">Dinner Date</a>) managed to make our particles twice as fast. What's the trick? Jeroen was kind enough to tell me and today I'll share his approach. Since it's such a hardcore topic, I'll start by giving a general overview of what cache optimisation is in the first place.<br />
<br />
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHlZqWizjab5AbTeUvP2dffWzJlNbvd983-zabjEF11avkyHrt3OTssQYj8XxtRKTUshyARjJeQhtVnxG6dUXAezpDdKaquXPCBxXBoWZytT7ScwaneVEFGVboq_vjs48IW1D5-T-NmGTi/s1600/Cache+optimisation+-+Dinner+Date.jpg" data-original-width="500" data-original-height="364" /><br />
<br />
Let's have a look at computer memory, or RAM. Computers these days have gigabytes of very fast memory that's used to store whatever the game or program needs to use on the fly. But is that memory truly so fast? Physically, it's a separate part of the computer. Whenever the processor needs to get something from memory, it needs to be transported to the CPU. That only takes a tiny bit of time, but a modern processor can perform <i>billions</i> of operations per second. At those kinds of speeds, a tiny bit of time is actually a lot of operations that the processor could have done during that time. Instead, it's waiting for something to come out of memory.<br />
<br />
This is where cache comes in. Cache is a small amount of even faster memory that's directly on the processor and is thus a lot faster to access than normal memory. So whenever something is already in cache, the processor doesn't have to wait for it (or at least not as long) and can keep working. According to <a href="https://medium.com/software-design/why-software-developers-should-care-about-cpu-caches-8da04355bb8a" target="_top">this article</a> cache can be up to 27 times faster than main memory.<br />
<br />
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYDwQe4iuZBqUwBB8ChZ_x9KZ72IeoEj_xR2z7keJ0VUXfVcql6cYqrNimwPjEnzILmJcwtcKTksURHt7ym2BnGWmB2xHq28Ds8rJDPEJ_qA0JHmPcSO3jqcguKAOhNf3Cafc3NjHeX9CX/s1600/Cache+optimisation+-+CPU+and+RAM.gif" data-original-width="500" data-original-height="188" /><br />
<br />
As programmers we generally don't have direct control over what's in cache: the processor tries to utilise the cache as efficiently as possible by it's own volition. However, depending on how we access memory, we can make it a lot easier for the processor to use cache efficiently. This is where cache optimisation comes in.<br />
<br />
The goal of cache optimisation is to structure our code in such a way that we use cache as much as possible and need to wait for memory as little as possible. Whenever the processor needs to get something from memory and it's not already available in cache, that's called a <i>cache miss</i>. Our goal is to avoid cache misses as much as possible.<br />
<br />
To be able to avoid cache misses, we need to know a little bit about how cache works. I'm no specialist in this field, but we only need a small bit of knowledge to already understand how a lot of cache optimisations work. These are the basic ideas:<br />
<ul><li>Data is transferred from memory to cache in blocks. So whenever you're using something, the memory directly around that is likely also already available in cache.</li>
<li>Cache is often not cleared immediately. Things you've just used have a good chance of still being available in cache.</li>
<li>The processor tries to predict what you'll use next and get that into cache ahead of time. The more predictable your memory access, the better cache will work.</li>
</ul><br />
These three concepts lead to a general rule for writing code that's efficient for cache: <i>memory coherence</i>. If you write your code in such a way that it doesn't bounce all over memory all the time, then it will likely have better performance.<br />
<br />
Now that the basics are clear, let's have a look at the specific optimisation that Jeroen did that halved the CPU usage of our particles.<br />
<br />
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinwv9JqCkyi3uHwQlMR9gAsHLa0hKztBSHRULR9xY7xGwC8aTh-LnXZPtz2IIRS_FiVn_JyZmOUMpq3Rkbx8XqutzImGM7PrFrwMYxnTPW8HcMT8w_ABpADp08UXKO_knUfz65qCRLt8Xc/s1600/Cache+optimisation+-+Particles.jpg" data-original-width="500" data-original-height="341" /><br />
<br />
To avoid dumping huge amounts of code here, I'm going to work with a highly simplified particle system. Please ignore any other inefficiencies: I'm focusing purely on the cache misses here. Let's have a look at a very naive approach to implementing a particle system:<br />
<br />
<table bgcolor="#eeeeee" border="0" cellpadding="10px" cellspacing="0px"><tbody>
<tr><td><pre>struct Particle
{
Vector3D position;
};
class ParticleSystem
{
std::vector<Particle*> particles;
void update()
{
for (int i = 0; i < particles.size(); ++i)
{
particles[i]->position += speed;
if (shouldDestroy(particles[i]))
{
delete particles[i];
particles.erase(particles.begin() + i);
--i;
}
}
while (shouldAddParticle())
{
particles.push_back(new Particle{});
}
}
};
</pre></td></tr>
</tbody></table><br />
This code is simple enough, but if we look at it from a cache perspective, it's highly inefficient. The problem is that every time we create a new particle with <span style="font-family: "courier new" , "courier" , monospace;">new</span>, it's placed in a random free spot somewhere in memory. That means that all the particles will be spread out over memory. The line <span style="font-family: "courier new" , "courier" , monospace;">particles[i]->position += speed;</span> is now very slow, because it will result in a cache miss most of the time. The time the processor spends waiting for the particle's position to be read from memory is much greater than the time that simple addition takes.<br />
<br />
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEian9fv1EkXl38mM4sGOU3BVNCFehtNurYrkxV0Vp-33b-BHjf2DKEreQLdEWuZGWjx0SX1el_lt_DURrew9zgKxf6SAqTMNB_ObzYyFjk0-PS8rt734oGrUGt3dS6R-kY2mrnfdWa5Gkfv/s1600/Cache+optimisation+-+Basic+implementation+memory+layout.gif" data-original-width="500" data-original-height="324" /><br />
<br />
I knew that this would give performance problems, so I immediately built the particles in a more efficient way. If we know the maximum number of particles a specific particle system can contain, then we can reserve a block of memory for that on startup and use that instead of calling <span style="font-family: "courier new" , "courier" , monospace;">new</span> all the time.<br />
<br />
This results in a bit more complex code, since we now need to manage that block of memory and create objects inside it using <i>placement new</i>. In C++, <i>placement new</i> allows us to call a constructor the normal way, but use a block of memory that we already have. This is what the resulting code can look like:<br />
<br />
<table bgcolor="#eeeeee" border="0" cellpadding="10px" cellspacing="0px"><tbody>
<tr><td><pre>struct Particle
{
Vector3D position;
};
class ParticleSystem
{
unsigned char* particleMemory;
std::vector<Particle*> particles;
int numUsedParticles;
ParticleSystem():
numUsedParticles(0)
{
particleMemory = new unsigned char[maxCount * sizeof(Particle)];
for (unsigned int i = 0; i < maxCount; ++i)
{
particles.push_back(reinterpret_cast<Particle*>(
particleMemory + i * sizeof(Particle)));
}
}
~ParticleSystem()
{
delete [] particleMemory;
}
void update()
{
for (int i = 0; i < numUsedParticles; ++i)
{
particles[i]->position += speed;
if (shouldDestroy(particles[i]))
{
//Call the destructor without releasing memory
particles[i]->~Particle();
// Swap to place the dead particle in the last position
if (i < numUsedParticles - 1)
swap(particles[i], particles[numUsedParticles - 1]);
--numUsedParticles;
--i;
}
}
while (shouldAddParticle() && bufferNotFull())
{
//Placement new: constructor without requesting memory
new(particles[numUsedParticles]) Particle{};
++numUsedParticles;
}
}
};
</pre></td></tr>
</tbody></table><br />
Now all the particles are close to each other in memory and there should be much fewer cache misses when iterating over them. Since I built it this way right away, I'm not sure how much performance I actually won, but I assumed it would be pretty efficient this way.<br />
<br />
Nope.<br />
<br />
Still lots of cache misses.<br />
<br />
In comes Jeroen D. Stout, cache optimiser extraordinaire. He wasn't impressed by my attempts at cache optimisation, since he saw in the profiler that the line <span style="font-family: "courier new" , "courier" , monospace;">particles[i]->position += speed;</span> was still taking a disproportionate amount of time, indicating cache misses there.<br />
<br />
It took me a while to realise why this is, but the problem is in the <span style="font-family: "courier new" , "courier" , monospace;">swap</span>-line. Whenever a particle is removed, it's swapped with the last one to avoid moving all particles after it one forward. The result however is that as particles are removed, the order in which we go through the particles becomes very random very quickly.<br />
<br />
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih7oSbrVqpWwIVv9atkO_LP3wLkuPw9wgjnhAavKEEhEyDGlDAJKhM7Jaj_4jIKh7yuFR7ZMHZRurf_O8-QZOmjKwtpeOwXDdltJ0YmDadpWVgikDvOQeYVHrypfyOiRJ9BmmixbubN4l7/s1600/Cache+optimisation+-+One+buffer+but+bad+ordering.gif" data-original-width="500" data-original-height="268" /><br />
<br />
The particles in our example here are really small: just a single <span style="font-family: "courier new" , "courier" , monospace;">Vector3D</span>, so 12 bytes per particle. This means that even if we go through the particles in random order, we might occasionally still be staying in the same cache line. But a real particle in the Secret New Game (tm) that we're developing at <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a> has much more data, like speed, scale, orientation, rotation speed, vibration, colour, and more. A real particle in our engine is around 130 bytes. Now imagine a particle system with 100 particles in it. That's a block of memory of 13,000 bytes. Hopping through that in random order is much more problematic for cache!<br />
<br />
Thus, Jeroen set out to make it so that updating particles goes through memory linearly, not jumping around in memory at all anymore.<br />
<br />
Jeroen's idea was to not have any pointers to the particles anymore. Instead we have that big block of memory with all the particles in it, and we store the indices of the first and last currently active particles in it. If a particle dies, we update the range of living particles and mark the particle as dead. If the particle happens to be somewhere in the middle of the list of living particles then we simply leave it there and skip it while updating.<br />
<br />
Whenever we create a new particle, we just use the next bit of memory and increment the index of the last living particle. A tricky part here is what to do if we've reached the end of the buffer. For this we consider the memory to be a ring buffer: once we reach the end, we continue at the start, where there's room since those particles will have died by now. (Or, if there's no room there, then we don't create a particle since we don't have room for it.)<br />
<br />
The code for this isn't that complicated, but it's a bit too much to post here. Instead, I'm just going to post this scheme:<br />
<br />
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg116ZJTMB4TmtvYaJ1gXHiHVjZUtUOW9ax00pCSJr7vl9egaWd8daYarl2mRbVeB9TUPn2r2ZW-GYa6TDv-W9rxBx8y0rj80IJvdvSAQ5hRNd6LytWHIDB59I0sGBdOo9YaXQBSGefcxjR/s1600/Cache+optimisation+-+Ring+buffer.gif" data-original-width="500" data-original-height="240" /><br />
<br />
Compared to my previous version, Jeroen managed to make our particles <i>twice as fast</i> with this approach. That's a pretty spectacular improvement and shows just how important cache optimisation can be to performance!<br />
<br />
Interestingly, my first hunch here is that this optimisation is a bad idea since we need to touch all the dead particles in between the living ones to know that they're dead. Worst case, that's a lot of dead particles. In fact, when looking at computational complexity, the worst case has gone from being linear in the number of currently existing particles, to being linear in the number of particles that has ever existed. When I studied computer science at university there was a lot of emphasis on Big O Notation and complexity analysis, so to me this is a big deal.<br />
<br />
However, as was mentioned above, accessing cache can be as much as 27 times faster than accessing main memory. Depending on how many dead particles are in the middle, touching all those dead particles can take a lot less time than getting all those cache misses.<br />
<br />
In practice, the lifetimes of particles don't vary all that much. For example, realistic particles might randomly live between 1.2 seconds and 1.6 seconds. That's a relatively small variation. In other words: if there are dead particles in between, then the ones before them will also die soon. Thus the number of dead particles that we need to process doesn't become all that big.<br />
<br />
The big lesson this has taught me personally, is that cache optimisation can be more important for performance than Big O Notation, despite that my teachers at university talked about Big O all the time and rarely about cache optimisation.<br />
<br />
<i>EDIT: Several commenters on Twitter and Reddit suggested an even simpler and faster solution: we can swap the dead particles towards the end of the list. This removes the overhead of needing to skip the dead particles and also removes the memory that's temporarily lost because dead particles are in the middle. It also simplifies the code as we don't need to handle that ring buffer anymore.</i><br />
<br />
For further reading, I would like to again recommend <a href="https://medium.com/software-design/why-software-developers-should-care-about-cpu-caches-8da04355bb8a" target="_top">this article</a>, as it explains the principles behind cache lines very well and shows some clever tricks for optimising to reduce cache misses.<br />
<br />
As a final note, I would like to also stress the <i>un</i>importance of cache optimisations. Computers these days are super fast, so for the vast majority of code, it's fine if it has very poor cache behaviour. In fact, if you're making a small indie game, then it's probably fine to ignore cache misses altogether: the computer is likely fast enough to run your game anyway, or with only simpler optimisations. As your game becomes bigger and more complex, optimisations become more important. Cache optimisations generally make code more complex and less readable, which is something we should avoid. So, use cache optimisations only where they're actually needed.<br />
<br />
Have you ever successfully pulled off any cache optimisations? Are there any clever tricks that you used? Please share in the comments!Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com4tag:blogger.com,1999:blog-3064325214589649535.post-14042760950688858632020-02-16T21:18:00.002+01:002020-02-16T21:20:53.482+01:00New song: Approach of the Derelict Research StationHere's my newest song: <i>Approach Of The Derelict Research Station</i>! This one is not just my newest song, but also one of the oldest: it's an evolution of a song that I wrote some tens years ago, then called <i>Space War X9</i>.<br />
<br />
Two years ago, when I decided that the songs I was writing at that time should form an album together, I wondered what else should be on it. I've always been quite fond of Space War X9 and wanted to include it, but it was lacking an important ingredient: cello! On my album I want all the songs to feature my cello in a prominent role. However, back when I made Space War X9 I had no idea how to record my cello in a way that made me happy with the results, so I mostly composed purely electronic music.<br />
<br />
Adding cello was an interesting challenge: the tonality of Space War X9 turned out to be rather odd and none of it had been written with an additional instrument in mind. Still, somehow the cello ended up being the lead instrument through most of it. Listening to the new version, it now feels weird that it once lacked cello, since the cello is now the lead instrument during most of the song.<br />
<br />
This song is also the first one to be released with narration. On my album all the songs will tell a story together. Voice actor Chris Einspahr has graciously lent his voice and I love how he acts. His voice also blends very well with the music. Check it out:<br />
<br />
<iframe width="500" height="281" src="https://www.youtube.com/embed/Wqe_6A0LoYk" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><br />
<br />
At the end of the song there's a bit of crazy cello improvisation. I often do these kinds of intense gliding notes during jam sessions but this is the first time I dared include one in a real song. I'm quite happy with how that turned out, and it nicely captures the craziness of the fight portrayed at the end of the song.<br />
<br />
If you'd like to play this song yourself and give your own twist to the crazy ending, you can find cello sheet music for it on <a href="http://music.joostvandongen.com/" target="_top">music.joostvandongen.com</a>, as well as a version of the song without the cello, to play along it.<br />
<br />
The art in the video is by <a href="https://www.artstation.com/spacenithal" target="_top">Karen Papazian</a>, who allowed me to use her existing piece "Not much left". While it wasn't originally drawn for this song, it perfectly fits what I imagined the setting to be.<br />
<br />
Finally, I should mentioned the samples I used here. I found these samples on <a href="https://freesound.org/" target="_top">FreeSound.org</a> and it's great that most audio on this website requires nothing more than attributing the original artists and then you can use it. The samples used in Approach Of The Derelict Research Station were made by 211redman112, foxraid, lezaarth, TMPZ_1, Ideacraft, Deathscyp, rene___, steshystesh, jonccox and lollosound. (Gotta love the kinds of named people give themselves on the internets!)<br />
<br />
This leaves only one song to finish for my album, almost there!Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com0tag:blogger.com,1999:blog-3064325214589649535.post-17906855864217986172020-02-02T16:37:00.000+01:002020-02-02T16:37:16.911+01:00Five important realisations about game balanceThe games we've so far made at <a href="https://www.ronimo-games.com/" target="_top">Ronimo</a> have all featured a heavy emphasis on competitive multiplayer. Designing, testing and iterating these games, especially our biggest hit <a href="https://www.awesomenauts.com/" target="_top">Awesomenauts</a>, has taught us many things about balancing. Today I'd like to share some of the most important lessons we've learned along the way.<br />
<br />
<h3>1. Overpowered is much worse than underpowered</h3><br />
At first glance one might think that in game balance, underpowered and overpowered are equally bad: they both mean something is badly balanced and needs to be improved. This is true, but in practice overpowered things turn out to have way more impact than underpowered ones. <br />
<br />
The reason for this is that players tend to flock to whatever is strongest and use only that. For example, Awesomenauts has 34 characters. If 3 of those would be <i>under</i>powered, then most players wouldn't play those, leaving 31 valid characters. That's still plenty of choice and variation. On the other hand, if 3 characters were <i>over</i>powered, then players would play only those 3 and would ignore the rest. That would make the game very repetitive and turn stale quickly.<br />
<br />
This knowledge can be used as a crude tool in cases where no better solution is available. For example, if something is overpowered but only under certain circumstances, then you might choose to nerf it until it's okay under those circumstances only and is underpowered in all other situations. This way at least it isn't dominating the game anymore.<br />
<br />
<h3>2. Variety always adds imbalance</h3><br />
A game with just one weapon on just one symmetrical map will pretty much automatically be balanced. Even if only because all players are in exactly the same situation. Such a game would however probably not just be balanced, but also be <i>boring</i>. So we need to add variety: more weapons, more maps, more items, more builds, more everything. Maybe even asymmetrical maps. The key thing to realise when doing this, is that as the game becomes more complex, 'perfect' balance becomes ever more difficult to achieve. This quickly gets to the point were 'perfect' balance is impossible, and every bit of variation you add makes the game a bit more unbalanced.<br />
<br />
Let's look at a really simple example: walking speed. Let's say some characters are fast and others are slow. This gives the slow characters a disadvantage that can be balanced by giving them more health and damage. However, now we also add maps of different sizes. On a bigger map, the disadvantage for the slow characters will be bigger than on a small map. This is because if the arena is small, slow characters can get to the other side fast enough anyway. No amount of health or damage tweaks will fix this, since it differs per map.<br />
<br />
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicfoyiq6Urpii2FzwdPQo37fcnyICI3P0tcFaBrOgNdVrJSzTIGPv101YiPNC2aEcsptPLbUXyCBCbB2V8vaCtHAeBY0cF25et91WILIo0AnUdqWQZfXlUzaDW8pmkhRdO1Kf0ox3DRc9o/s1600/Balance+realisations+-+Awesomenauts+character+variation.jpg" data-original-width="500" data-original-height="376" /><br />
<br />
One solution to this can be found in our game <a href="http://www.swordsandsoldiers2.com/" target="_top">Swords & Soldiers 2</a>. There in matchmade online matches, we only use certain maps: the ones that we feel are most balanced. On the other hand, when you invite a friend to play, you can choose from <i>all</i> maps, including a bunch of pretty weird ones. Those might be less balanced, but they add a lot of spice and fun. Depending on how much you want to appeal to players with a competitive mindset, you can choose to include those varied but imbalanced maps, or not.<br />
<br />
<h3>3. Competitive players often dislike randomness and luck</h3><br />
When Awesomenauts launched, the game had random crits, which dealt a lot of extra damage. This added surprise and suspense: every hit might be extra strong! It also means that even if the opponent is better than you, you might occasionally win because you got lucky. This makes a game a lot more friendly for beginners. An extreme example of this can be found in Mario Kart: this game includes a lot of randomness. Combined with a bunch of catch-up mechanics, Mario Kart is a game where occasionally a n00b can beat a pr0.<br />
<br />
However, randomess also adds <i>bad</i> luck: sometimes you clearly outplay an opponent and still lose, because the enemy got lucky and landed several crits in a row. In a sense this might feel nice: since the opponent clearly just got lucky, you don't need to blame yourself for losing. Many competitive players however don't want this to factor into the equation. They want a very simple thing: the best player should win. "<i>If I practice more and get better, then I should </i>always<i> win.</i>" In the years after release many players in the Awesomenauts community got better and more competitive, to the point where a lot of players really wanted the random crits to be removed from the game. For this reason we ended up changing crits into a predictable system where simply every third hit deals more damage.<br />
<br />
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiil5nAYK4xQA44Ewbdm3iFFaMu8c_vS98Sa9olpD8_iFma-E9gYJQ0t_TzY5SiMye6gPcEuGTm4SLx-2JwIfMIy4KrMqIhhAe3n2mPj00d9s4z4cFfKYnpyKh5MSug0yyaNcM1bfLLn7PO/s1600/Balance+realisations+-+Swords+and+Soldiers+damage+symmetry.jpg" data-original-width="500" data-original-height="435" /><br />
<br />
<h3>4. Balance automatically becomes worse over time</h3><br />
Even if you think the balance in your game is in a good place, by simply leaving it as it is for a while, it will deteriorate. The reason for this is that as time passes, players get better at the game, learn new tricks and talk to each other. This changes how the game is played, thus also changing how the balance is experienced. Usually not for the better: as time progresses and no balance tweaks are made, balance usually becomes worse.<br />
<br />
One example we've seen with Awesomenauts was that at some point after a few months of stable balance, one specific team discovered a new tactic that was super strong. This tactic had been possible for months, but somehow no one had found it yet. This tactic was then first used in a tournament, where that team gloriously beat everyone else and won. After the tournament, news spread like wildfire and suddenly this tactic was used in almost every match. We had no choice but to quickly do a balance patch specifically to nerf this one particular tactic. (The fact that our game is deep enough that players can discover new tactics this way is one of the things I'm most proud of in all of my career as a gamedev.)<br />
<br />
Another example of balance getting worse over time might not even be caused by something actually being way too strong. Maybe there's something that's just slightly overpowered, so mildly that it really doesn't matter. As time passes, players write guides and talk about the best tactics. They will point each other at this subtle advantage, causing more and more people to use it. Even if the advantage is really small, or, even more extreme, even if the advantage doesn't exist and players are just imagining it, this still ruins the game for the simple reason that everyone starts doing the same thing. This makes the game predictable and boring.<br />
<br />
Sometimes you get lucky and players start responding to that imbalance. Maybe an underpowered character happens to be really strong in that particular situation. Since that situation now happens so often, that underpowered character is suddenly super strong in most matches, causing lots of players to choose him. This makes the dominant strategy shift naturally from one thing to another, adding variation and fun. I've been told some games in the Super Smash Brothers series have balanced excellently for this: as soon as one character becomes dominant, its counter becomes extra interesting and lots of players start playing the counter, at which point the counter of the counter becomes useful, etc. This causes the balance to slowly but constantly shift.<br />
<br />
<h3>5. 'Perfect' balance is impossible</h3><br />
The final point I'd like to share today is both soothing and intensely frustrating: <i>for any game that has significant complexity and variation, perfect balance is impossible</i>. This is a soothing thought in the sense that it makes you realise that even if you were the best game designer in the world, your game would still not have perfect balance. It's also frustrating, because of course the goal of the game designer is to make the balance really good. Knowing that the balance will never be truly fantastic makes balancing a frustrating experience.<br />
<br />
So, why is 'perfect' balance not possible? I've already mentioned above that as more variation is added, it becomes impossible to make all options equally strong under all circumstances. But there's more. What about players of different skills? Some characters/weapons/maps are bound to be more difficult to play than others. The result is that for beginners, the balance will be different than for pros. And what about simply different tastes? Some players prefer fun and variation, while other players prefer predictability and skill. The balance can't make both groups perfectly happy. Combined, all of these elements make it impossible to achieve 'perfect' balance.<br />
<br />
This post has shared some of the things we've learned through the years about balance. What are your most valuable or most surprising insights regarding balance?<br />
<i><br />
PS. Some of the topics in this blogpost have been discussed in more detail in previous blogposts. If you'd like to read more, have a look at the following posts:<br />
<ul><li><a href="http://joostdevblog.blogspot.com/2014/01/the-surprisingly-many-subtleties-of.html">The surprisingly many subtleties of designing crits</a></li>
<li><a href="http://joostdevblog.blogspot.com/2015/03/the-downsides-of-gameplay-variation.html">The downsides of gameplay variety</a></li>
<li><a href="http://joostdevblog.blogspot.com/2019/08/beginner-balance-versus-pro-balance.html">Beginner balance versus pro balance</a></li>
</ul></i><br />
Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com6tag:blogger.com,1999:blog-3064325214589649535.post-3226110182080271772019-10-27T20:03:00.000+01:002019-10-27T20:03:04.644+01:00New song: A Century Flies ByI'm slowly inching closer to finishing my album and today I have tangible proof of this: a new song is finished! This one is called A Century Flies By and, as the title suggests, it's an intermezzo on my album in between two time periods. This one brings the story from the middle of the 20th century to the 21st century.<br />
<br />
<iframe width="500" height="281" src="https://www.youtube.com/embed/3tzn0xReXIQ" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><br />
<br />
The violin in this song was played by Mijnke van der Drift and the drums were played by <a href="https://www.johnmaasakkers.nl/" target="_top">John Maasakkers</a>. I already knew that instruments like violin and my own cello need to be real, but now that I've worked with real drums on one of my songs I also know that computer drums are just unacceptable in comparison. Or at least, they are when I make them: making computer instruments sound natural and good is an art in itself and it's not one I've mastered or want to put the time in to master. I'd much rather work with real musicians and instruments. Mijnke and John did a great job and I thank them for their contributions. I expect you'll hear both of them in more of my songs later on.<br />
<br />
Sheet music for cello and violin can be found at <a href="http://music.joostvandongen.com/" target="_top">music.joostvandongen.com</a>. This also includes recordings of the song without the cello, without the violin and without both, to play along to. If anyone ever happens to play one of my songs, then I'd love to hear from them as that would be really awesome!<br />
<br />
This song is the brother of my previous one: A Century Sails By. I really liked that one and wanted to extend it into a longer song. Thus today's new song started out as the second half of A Century Sails By. However, I just couldn't get the two halves to feel like one song. Around the time when I was stuck on how to make both halves gel with each other I happened to listen to Arena's awesome album <a href="https://open.spotify.com/album/7K0oCFUJOuPVFQOAFAUSzG" target="_top">Songs From The Lion's Cage</a>. In between the longer songs on this album there are shorter ones called Crying For Help 1 to 4. I really like this idea of having intermezzos on an album that are linked to each other and figured I could do something similar here. So I split the two halves of A Century Sails By and made them separate short Songs on the album.<br />
<br />
Since they're so strongly tied to each other, here's A Century Sails By again for comparison:<br />
<br />
<iframe width="500" height="281" src="https://www.youtube.com/embed/N9Cp1Ah0XPk" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><br />
<br />
Only two more songs left to finish for the album, and then a lot of work around making it a real album instead of just a list of songs. Things that still need doing include final mixing and mastering, the cover, making a little booklet and maybe hiring a narrator for the story bits. The two final songs that I still need to finish are among the most ambitious of the album and they have nice long names, so I figured I'd end today's post with a little teaser in the form of their titles:<br />
<br />
<ul><li>Then the Halls Were Empty... and I Turned It On!</li>
<li>Approach of the Derelict Research Station</li>
</ul>Joost van Dongenhttp://www.blogger.com/profile/00569566310604620045noreply@blogger.com2