Summer Punchball — Breakdown


Júlio Rodrigues ·

What started as a portfolio piece evolved into something much bigger. Selected as probably the easiest idea to implement out of a dozen I had on my Red Notebook of Game Design ideas, it happened to be really tricky to materialize, no different from all the development stories myself and everybody else already heard. Summer Punchball is opening doors that I've only dreamed opened and presented an incredibly rich learning environment.

This post contains affiliate links to the tools used to build this game. By purchasing these tools through the links here listed you help the blog to pay the server bills and the author to buy some bacon.

For those who haven't played the game

If you want to play the game before reading this post, Summer Punchball is available now in Google's PlayStore.

Project's objective

When this project started, it had the single objective of showing potential mobile game developer employers my technical and creative skills on game development. And, as usual, it has evolved to something else much bigger, I’ve started to care for it. I’ve started to have fun with it, thinking, “wow, that’s actually fun, I think I have something in my hands”. As I’ve always tried to learn game and level design, but was never into modding, the practice of those skills is really hard to attain. I was thrilled that I would finally be able to work on something that’s not a clone, something I could call "a creation". Not that the project is entirely original, I don’t think such thing exists, but it was the fruit of two weeks of intense investigation of different game design ideas, playing those inside my head and opening myself up to several new games that I could get my hands on on Android, and of course, watching footage of people playing old games on YouTube.

After hearing all the horror stories about developers creating games to no players, the moment I got a playable prototype, even with horrible art, I put it in front of my family and friends. And to my surprise, they wouldn’t stop playing until they could get all the coins from the demo stage. This fact alone was more than enough to replenish all my energies spent on figuring out how to mix kinematic and simulated objects on a physically simulated game.

Since my aim was still to create a demo to be able to be hired without needing to go through tough interview processes as I’m terrible at those, and I’ve been focused on studying art for the last 18 months, I’ve planned that the game would need to be beautiful within the realm of my still in early development artistic skills and within limitations of cheap mobile phones—meaning: if the game runs and looks good on a phone powered by an Adreno 306, then it’s fine.

The project objective has evolved from being something only to demonstrate my skills to an actual project with real chances of being published, thus I’ve started to invest some money outsourcing tasks that were (and still are) beyond my skillset, skills like music composition and sculpting. I was lucky to find a composer and sound designer that understood the project and produced a catchy main track and even better effect music for when the player wins a level. For sculpting and UI I’ve hired an old friend and we reached a deal that worked for both of us. Since I’ve wanted to retain complete creative control, we didn’t start a partnership on this project.

Who should read this

Anyone that’s trying to understand how the author thinks and solves problems and wants to know his capacity of expressing thoughts in written language. People interested in learning about what was the process of creation of Summer Punchball, a physics action puzzle game for mobile devices can also learn a lot from this document, both production, and design-wise.

How was the ideation process that led to the final game design chosen

Initial game design idea.

To expand what’s been said in the previous section, this idea was the winner of several ideas I had sketched on my game design sketchbook based on the following criteria:

  • It should feel that I’m capable of delivering it without too much learning involved
  • The game design has to have at least one novelty, it can’t be a clone
  • It feels fun to play inside my head
  • Looks like to exist a public that would like and understand the game easily

There were other strong candidates, like some game variations I was creating on a really old title called Araiguma Rascal, or a semi idle auto shooter game based on the Icarus greek story. During this investigation, I’ve also concluded that I didn’t want to work on yet another puzzle game (puzzle games comprise ~90% of my game development history), that filtered a few more ideas. Some were difficult to implement at a first glance, others would require too much art. Hence, Summer Punchball, codename Windbuchse, was the winner.

Windbuchse game design itself came from me watching a video of impossible Super Mario World stages, it actually changed quite a lot since that initial first idea but it still has the balance of an object as the main motif of the game.

How were the first gameplay tests done

The first tests with people playing the game were done rather quickly, in the first three weeks I believe, it was Christmas, so I thought: “cool, a lot of test subjects ahaha”. No, I didn’t think that, but I could? Anyway, I’ve asked people from my family—gamers, and non-gamers if they would like to play this new project I had been working on the last month, and they all said yes (my family loves me, thank you family). To my surprise, they all understood the game without a tutorial and without me giving explanations to them since I’ve told them that I was doing a test of how people would react to the game and if they would be able to understand it, to test if the game is easy to play.

The most interesting thing was to see that each person liked a different thing about the game, my grandma really liked the final “yuuhuu” shout at the end, she was also really fond of the fact that she could collect “beautiful coins”. Some people said nice things about the colors, and other simply kept replaying it until they could get all the coins in a single run, have in mind that it was before (way before) I’ve implemented the winning choreography, so people were just naturally trying to get all the coins.

I’ve also noticed that they enjoyed learning how to best control the glove and that’s something that would require a lot of polishing, I couldn’t get this wrong.

Since we were at the end of the year, and the disease that shouldn't be named hasn’t kicked in yet, I got a lot of opportunities to get my game on the hands of different people, when the conversations started to warm down, I was always ready to start talking about this project, a few people declined saying that they were not much into gaming, but all of them were interested in hearing my "quitted the job to start to study and make games" story.

Giving chance to chance: the game objective implying the beach theme

Using the maxim that art should follow gameplay, the beach scenery has been reached. But how? Turns out that not a lot of spherical objects kinda float under normal gravity conditions. The only thing that remotely looked like the movement this game needed was a beach ball, thus the beach theme. If I’m totally honest with myself and you, I need to admit that the game being set on space would also work, but I’d rather have it on a beach. I was born and raised in a seaside town, I still feel the delight of playing in the beaches of Guarapari with my friends—ingrained in my memory.

Level Design Process

The level design process had a chaos component some times, but most times it was quite traditional. In the beginning, I was capable of just plunging a lot of stages directly on my drawing notebook, with the time passing this activity started to show itself challenging, a little more preparation and structure would become necessary.

That’s when I’ve started to work around themes. Instead of working on levels directly, first I would develop a central idea I’d like to explore and then did variations on it on the notebook, this worked quite well. On games with bigger levels each level would contain one of those central ideas, but on this game scale it was possible and necessary to make each idea span multiple different levels—Summer Punchball has levels that can last only a few seconds.

After getting the sketches for the levels done on paper it was time to model them using Blender. I’ve experimented with different methods for modeling these levels, from using a plane and cutting out a big ngon, to sculpting, to a more traditional topology-concerned workflow. In the end, I saw myself combining the ngon with sculpting, using the new voxel remesher functions and some traditional modeling to clean and optimize the geometry.

Main Influences

If you never saw Everything is a Remix by Kirby Ferguson—I’m afraid you should. He—a filmmaker—and countless art scholars believe in the idea that no art exists in a vacuum, and Summer Punchball isn’t an exception. The only thing I knew I didn’t want to do was to do a clone. Drinking from the right sources is essential. But what sources? Well, I’m really into Japanese game design and art (pop art). Most of what I’ve played my entire life has been made by them, but that’s not the entirety of my ideas well. Of course, being born and raised in the west I’ve been exposed to the western culture and I’ve certainly played a lot of other things. To try to shorten what is already a really unnecessarily long paragraph I’ll list using a bullet list:

  • Super Mario World
  • Cut the Rope
  • Dr. Mario World
  • Angry Birds 2

Constantly refactoring the codebase while learning new Unity programming patterns

Although I thought I was ready when I started, in reality, I wasn’t. This has been a deep learning (oh) experience for me. Fortunately, there were only a few problems that I couldn’t find solutions online or that I couldn’t rely on my past experience as a web and android applications developer to solve. Reading a lot of source code I was able to change that. I've always been into reading source code, that's how I've evolved from "I know some java" to "I believe I know useful bits of java", thanks to the extraordinarily well made and easy to use JetBrains jump to source (decompiling byte code if source is not available) functions.

Textbooks in general fail to communicate the extent to which real-world code has to go to make sure that it works in all the different scenarios the code might need to deal with, all sorts of needs and software/hardware platform realities. Not that these books don't make us aware of these situations but it's just too hard to explain in abstract terms what it really takes, and open source fills this gap really nicely.

Since Unity has started to open some of its source code, the C# portion at least, everybody now can learn from them. Learning more about how the engine works and practices of solid C# programming is available to anyone interested.

The no manual repetition principle

It’s more than a loss of time, it’s an error-prone practice—the kind of error that’s difficult and tedious to detect and correct. Whenever you see you (or anybody from your team) doing an extremely repetitive task on a computer, it’s time to assess how hard it’s to automate such task. Most people will tell you that if it hasn’t happened at least X times it’s wasteful to automate, but we actually never know how many times the task will be performed again. With each request for a revision, comes frustration that time will be wasted again on a non-human activity, implying that instead of the quality of the work increasing in each revision, there’s a chance that it is going down.

Hefescos, AlignTools, and the CSV Glove Design Import/Export are the three main tools that I’ve created based on that principle. Other mini tools that aren’t worth mentioning by name have also been created, but they are nothing more than small script snippets attached to buttons invokable using an Odin - Inspector and Serializer button attribute.

Hefescos, a non-template based C# code generation tool

the god of fire, as used in art, and master of all the arts which needed the aid of fire, especially of working in metal.

—Milton, Paradise Lost

Hephaestus is the artisan of Olympus, doing a silly joke with his name and at the same time paying a tribute, I’ve named my C# source code generator library Hefescos. Hefescos is heavily influenced by its Java counterpart Java Poet. Since I’ve been an Android Application Engineer for a very long time, I’m acquainted with a lot of techniques from the Java world, and I’m a big fan of the open source work from Square (the fintech). After observing that the C# ecosystem lacked something as simple to use as Java poet I’ve accepted the self-imposed challenge of creating a subset of what would be an adaptation of Java poet to C#, the result is the Hefescos lib.

The need for generating C# code from a high-level API came from the fact that Unity requires its users to pass a bunch of strings around as arguments, and that’s extremely error-prone, and worst, it’s only noticeable on run-time. To alleviate some of this horror, I’ve hooked the creation of a few static classes containing important string definitions, namely: LayerNames, TagNames, and SceneNames.

Assets/Scripts/gen/LayerNames.gen.cs
//// <hefescos-generator-notice>
////   Do not edit, all changes are likely to be lost.
////   This file content has been generated by the Hefescos tool at 2020-Mar-13 19:01:26.
//// </hefescos-generator-notice>

using System;

namespace Bladecast {

  public class LayerNames {

    public const string Default = "Default";
    public const string TransparentFX = "TransparentFX";
    public const string IgnoreRaycast = "Ignore Raycast";
    public const string Water = "Water";
    public const string UI = "UI";
    public const string Hit = "Hit";
    public const string Ground = "Ground";
    public const string Ball = "Ball";
    public const string Particle = "Particle";
    public const string Player = "Player";
    public const string PostProcessing = "PostProcessing";
    public const string Collectibles = "Collectibles";
    public const string Mechanics = "Mechanics";

  }

}

It certainly required a lot more work than just manually creating these files, but this subproject was more than successful, every time I’ve changed or created a new Tag I’ve felt such a relief knowing that my code would still work or warn me that something’s off even before running the game, in compile time.

The specific details of how Hefescos work is a subject for a new post, but I’ll cite the main Unity APIs that were necessary and the general idea for the implementation in case you’re also trying to solve a similar problem.

To create a hook for your code generation to run you could use a regular MenuItem attribute or ask it to run on every few seconds using EditorApplication.update, I don’t like the latter because it might slow down the already slow Unity editor, but github shows that people are fond of this approach. Just be sure to don’t do it every frame at least.

For the code generation, think of an AST created without parsing. Hefescos offer classes and calls like NamespaceDeclaration, ClassDeclaration, FieldDeclaration.WithInitializationExpression(...) and so on. Creating these objects and calling these methods it’s possible to specify, using high-level code, no string templates, what code you want to generate. This is good because now the C# compiler can help you with this code generation with its type safety features and we can also run our own analysis and efficient string generation. Hefescos has been implemented in a different .NET assembly.

AlignTools

Positioning coins in a perfect manner was also taking a lot of time. Not every coin setup needed to be perfect, but some did, and I didn’t want to create sloppy work, so I was typing values in the inspector, something extremely boring. AlignTools started as just a couple of buttons to align objects vertically and horizontally, later evolved into its own EditorWindow with more buttons such as circle positioning and horizontal and vertical uniform distribution among the selected objects. It does not work on all axes, but it doesn’t matter, it’s a specialized tool done to do a very specific task.

Align tools toolbar.
Coins aligned using this tool.

Import/Export glove designs using CSV

That one doesn’t have a fancy name yet, but it got the fanciest functionality. More than just importing the data (exporting is simple), the importer first lists all the changes and additions that it will make when the user presses the confirm button. I’ve always wanted to do such tool for so much time I’ve spent altering tables using MySQLWorkbench and getting such useful reports, and it was work worth the time. Whenever I add or change glove designs on my spreadsheet application of choice (Numbers) I can get a good sense of what’s going to happen to my scriptable object asset files, and more than once this helped me find issues with my manual data editing.

A good relationship with Substance Designer, excessively good actually, and the discarded artwork of the level selection made using it

Eighteen months ago I’ve started a journey to become an artist, a competent one. My art of choice is tech art. But I’ve heard countless people prophesying that without a true understanding of the subjective subtleties of art my work would be mediocre, at best. Believing in such tales I’ve started my journey in the most honest of the visual arts, drawing.

Drawing by understanding and not by means of copying shows the raw state in which the artist's visual knowledge capability lies. That study made me appreciate the details, the stroke directions, the subtle choice of colors of similar hues, but also the strong compositions, and how hard it is to achieve high-quality artwork in the traditional drawing craft. After a long time drawing every day and also reading about the subject I’ve felt ready to start my transition into the digital realm, as everyone I’ve started with modeling (as most people), but that mysterious and powerful piece of software, at principle designed for material authoring, was luring me to it. Its exact nature, computational nature, logic design, minimal manual work approach is a combination that I’ve never asked for because only of my ignorance, this collection of ideas is just phenomenal. Substance designer has changed the way I think about digital art.

After doing course after course on material authoring using it I’ve started to do experiments on how to use it for different things, such as creating textures for VFX, graphic design elements, and a bunch of other things. It started to become ridiculous when I’ve created the background artwork for my game using it. I knew it could be better if I kept working on the piece but it was not feeling worth anymore. Instead, I’ve gone with a totally different approach, way more traditional, creating a mesh on blender and using designer to create the sand material.

Old level selection was 2D and ugly

The game still uses several graphic elements made in designer, as well as the punch and grab coins visual effects textures.

The new level selection in 3D

Modeling had nothing special for the new level selection, I already knew what I wanted before I’ve started to create the new level selection. I did it for two reasons, the first one being that I’m not a competent painter (not by any stretch of the imagination), second is that I have a tendency to believe that 3D graphics, when done by a person with artistic sensibilities can be cheaper to achieve the same level of wowzyness from the average consumer. Since I’ve spent a good time of my art training studying clean modeling topology and material authoring I could achieve a nice result without too much effort. The only challenges that I faced were the oyster and camera movement, camera movement is always a trouble, even for professionals, I heard.

Oysters were a problem because I’ve never rigged anything before, but worst than rigging was discovering a proper workflow to export animations from blender to unity. The one I’ve used is quite messy but reliable, in the future I’ll try to learn a new one, better yet, invent one since the time I spent looking for solutions for this problem is embarrassing enough.

Oh, the meander, I can’t end this section without talking about the meander. I got such a beautiful, curvy and natural-looking meander on Substance Designer that I had to replicate on 3D, it was rather easy, regular spline authoring followed by triangulation, the shader had a little something too—an Add (LinearDodge) to make it blend better with the base sand.

The water shore shader

No rite of passage for a tech artist could be cited that wouldn’t contain some kind of water shader. I feel that with this one I was able to finally join the adults table, although they certainly will lunch only after I finish my meal. Contrary to my initial desire and attempt, this shader has been written manually, in code, I always start my shader work using Amplify Shader Editor, it’s a fantastic tool.

There are two basic principles behind this shader. For coloring is the use of the depth texture for choosing between the shore color (white) or a gradient also based on the depth that goes from teal to marine blue. Second, for the wave movement, done in the vertex shader, Gertner waves are used, a single wave was sufficient since the shoreline is only present in the edge of the screen and Summer Punchball has a cartoony look.

Oyster’s rigging, skinning and animating process

I was not the one responsible for modeling the oyster, it was my friend Pedro. Pedro is very capable at any kind of organic sculpting and modeling task, I’ve asked him to work on it and the result was a beautiful oyster that looked good both on close inspection as well as seen from the top at a considerable distance. The rig was really simple and unnecessary, exporting the oyster as two separate shells with pivots in the right place would be sufficient and simpler to use, but since both of us were trying to learn to use more traditional rigging, skinning and animating techniques we went full power. One bone for each shell, an all or nothing skinning and that was it.

Animating it was funny, I’ve created two animations, one for opening the oyster, and another one when it denies itself to open for when the stage hasn’t been unlocked yet—closing was made as a speed -1.0 directly on unity.

The hard part, as mentioned in the previous section, was exporting the animations. Each animation is a new action in blender and they all must be stashed before exporting.

Optimizing the rustling of leaves shader with GPU instancing

Another manually written shader. When the game started I was using outlines for the main objects and I learned that it was not possible to do GPU instancing, outlining, and vertex animations, all at the same time, using Amplify. At first, I was shocked. But then, after it was done, I liked it because I’ve felt empowered, writing shaders by hand is not that difficult.

Two special things are happening here. The first is that it’s necessary to call UNITY_SETUP_INSTANCE_ID(v) in the vertex shader, and second is that to create the sensation that the leaves are rooted in the branch to which they are attached to it was necessary to use their UVs to make the wind force less strong towards the root. In the end it’s not using outlines anymore and it’s probably possible to be done using Amplify, but this task never wins a prioritization round.

Level design without UVs — How to create a simple planar mapping shader

Not that UVing these levels would be any hard, but since it could be avoided noticing that all of them would contain seams in pretty much the same place, the borders, I had this idea of creating a planar mapping shader instead of relying on traditional UV unwrapping, and to my surprise, it worked really well on the first attempt! To create some variation I’ve exposed the rotation parameter to the material.

The great difficulty of mixing kinematic objects with fully simulated objects

A naively unexpected difficulty haunted the project for months and months on end. At some point I’ve started to develop a few debugging techniques that led me to new ideas on how to tackle the situation, in essence I had to do sphere/ray casts every other frame, at least when there’s a chance that the player is trying to punch the ball, eventually winning its way to a stable gameplay implementation.

The debugging techniques are not fancy, drawing lines of different colors, pausing the game, public variables to be seen in the inspector, that kind of thing. In a following section I’ll talk about how tests helped me to accelerate development, but unfortunately I don’t think tests would’ve helped me here.

A new workflow for baked lighting in Substance Painter and the creation of the game’s 3d coin

I knew that the coins would need to be efficiently rendered so I’ve discarded the use of the standard shader or any GPU intensive shader. What was left was a diffuse only and possibly a diffuse with added specularity for highlights. I’ve decided to try doing it with just the diffuse component. The remaining mystery was knowing how to achieve a high quality diffuse only texture without painting skills. It was time to investigate what I could do using Substance Painter.

I got a basic painted metal with an aged appearance quite easily, this is one of the specialties of the application. Some scratches manually inserted and I got in hands a pretty convincing and good looking coin. But it was lacking character, I knew since the first time I thought on using coins for this game that they would need some kind of customization, prior to the modeling of the coin, I had created a very detailed oyster shell on blender using subdivision surfaces. It was time to bake.

With yet another learning project in hands, I did the usual, asked google and youtube for help, but never getting exactly what I needed, that’s when I’ve decided to try experimenting on my own.

Oyster shell normal map.

Using matcaps and blender I was able to create a normal stamp to be used against the coin surface. After some struggle, the import of this normal map happened successfully in painter. It was time to apply it, had again another issue with the edges, but this time it was not a struggle to solve it. My beautiful coin, with a shell engraving, done. Right?

Although it had the engraving I couldn’t rely on just exporting the usual maps to unity, it was looking terrible, that’s when I had the idea of baking the HDRI lighting information right into the diffuse texture. Again, without success on my internet searches, I was on my own—luckily these applications I’m using are quite capable, mature, and full of features beasts. There was a way to export the 2D view of painter to a texture, and that’s what I did.

Simplifying monetization having the project’s objective in mind

When the project started to feel fun and grow, I knew that I’d try to publish it. But in today's mobile market, it’s very very hard to sell a premium game, the only business model that’s recommended for beginners to try is the free to play. Ads. Ads were the answer, but even with ads there’s a lot that can be done, rewarded ads can be used, obligatory ads can be used, banner ads. You can mold the whole gameplay to fit your ads model. But I wasn’t really into it at the moment, I just wanted to get the game out so I could look for a job. I don’t believe I have the necessary knowledge and experience to run a game studio yet.

A banner in the level selection, rewarded ads for tripling the number of coins earned on victory, and a store selling purely cosmetic glove designs without an energy system, done. A pretty lightweight monetization, but more than enough to show that I understand the basics of the Free to Play market.

How I’ve accelerated the development of the game using automated tests

Whenever you hear people complaining about automated tests you’ll hear that they slow you down. I’ll argue that not always, on Summer Punchball I was able to develop all the functionalities related to the store, level progress, coins calculations, and a few more using tests without needing to reach that points where these things are needed in the game. This enabled me an accelerated development, both in terms of what’s been described as in a reduced number of bugs.

A collateral effect is that I was able to grow completely isolated APIs for these things, there is no logic that affects the internal storage (save) of the game that’s written inside a “screen” class.

Getting started was painful, but after learning how assemblies work on .NET and with the help of the Rider IDE from my beloved Jetbrains the work became smooth and delightful.

A very disappointing thing is the fact that we can’t test async functions in unity, I had to rewrite and reorganize a lot of code because of that. Unity Technologies has this terrible culture of delivering things half done.

The disappointments with the Unity Addressables system API

Why Unity Technologies keeps releasing 60% done work is beyond comprehension, and the addressables API is yet another case of this problem. The API is inconsistent, incomplete, and the documentation is quite confusing. They’ve created a lot of concepts that they don’t properly define, (Resource Locators, I’m talking about you), the very confusing and limited Addressables.MergeMode, well at least I couldn’t do an intersection between a group label and a few specific addresses.

Another issue is that there’s no way (that I’m aware of) to incorporate an automated step that will build your player content when trying to build the game using the editor GUI, it’s probably doable with some kind of build script, I haven’t spent the time investigating.

And overall the api is not consistent, specifically, if you want to load from a list of addresses I need to pass a null for the callback, MergeMode.Union and my addresses should be cast to Object s.

Addressables.LoadAssetsAsync<Object>(addresses, null, Addressables.MergeMode.Union)

How anybody would come up with this? And to make everything worse, the Addressables manual is very light on their examples, they just write a bunch of things for people that are already familiarized to the api, that was my impression, anyway.

The functionality is there, but it is very hard to learn how to use it.

The ball popping effect, feat. spiral equations

This effect was double fun. I spent time watching footage of a balloon deflating through the air, and (re)learning about spiral equations. Armed with knowledge of parametric equations for a spiral, doing this was easy. A code listing will explain more than prose this time.

// standard archimedes spiral motion offset by a slight amount of random noise
        spiralSpeed += spiralAcceleration * Time.deltaTime;
        theta += spiralSpeed * Time.deltaTime;
        var r = spiralA + spiralB * theta;
        var x = r * Mathf.Cos(theta) * 0.1f;
        x += spiralTowards.x * Time.deltaTime;
        var y = r * Mathf.Sin(theta) * 0.1f;
        y += spiralTowards.y * Time.deltaTime;

For more information on how the archimedes parametric equation work visit https://www.wikiwand.com/en/Archimedean_spiral. It also had a random component that I didn’t show on the code snippet to add some variety, people said to me that they liked the effect, it softens the blow of a defeat.

Combating an irrational fear of using AA and normal mapping by reading GPU manuals

When trying to develop games for mobile, the limitations of the mobile hardware will surely be hit. Then, if someone starts to read about how limited these hardware are they can start to develop phobia to any kind of technique they perceive as “advanced” even though they haven’t profiled and a lot of times even tested on their target device if the problem really exists. I was also a victim of this illness of thought and haven’t even tried to use normal mapping or anti-aliasing.

No matter what I did I couldn’t be on par graphics quality-wise with many top games of the Play Store and that was becoming a big concern. It was not even close. Then, I’ve decided to reflect on what I’ve been learning on talks from Mike Acton when he says “the hardware is the platform”, that was an eye-opener moment.

I’ve been trained in an environment where people were not only not taught on how to make the best use of specific hardware but actively discouraged, that the compiler would do its magic and this kind of work creates unportable code. I had no one telling me to open a manual (although in retrospect it sounds obvious now) from the chip developers to learn about the best practices on how to get the most out of their products. Overcoming my past is something that I always try to do. That particular trait was hard to move on from, but I did. Not that I didn’t get proper training on how hardware work, and how CPUs are architected, what is a superscalar processor, and the Tomasulo’s algorithm, I've learned all that. What is hard it to be able to combine theory and practice.

I’ve started to read again how CPUs work, what is the role of an operating system kernel, the different levels of memory caching, assembly, and most importantly to the game, I’ve started reading the GPU manuals for the Adreno 306 and Mali-G72. Two popular GPUs that I also happened to have access to.

From these readings, I got important insight on why AA shouldn’t be feared on some devices and that polycount is not king but fill rate is, that a few objects could use normal mapping without any problem if they are important for the aesthetic you’re trying to create and lots of other vital tricks.

Nested prefabs and a level creation process

Ever since I’ve watched a video from Unity introducing the new prefab workflow I knew I would use it to create levels. Having multiple scenes for each level is always painful, people started working around the previous nested prefabs limitation using incomplete scenes and additive scene load, it works, but it’s still odd, prefabs are what feels natural to me to do this.

So the game basic organization is: there’s a game scene which has all the objects that are present at every level, such as the camera, the ball deformer, all sorts of object pools and a few managers. Everything that does change is contained a different prefab, each prefab of that type constitutes a level. The level terrain shape, the coins, even the glove and ball are contained within the level prefab because their position changes, and it was way better for visualization and iteration to have them in the level prefab, the game state manager just needs to find a reference to these main objects by name at Awake.

Each prefab is associated with a level using a scriptable object that saves the order of them in a list, this object is then queried in the level selection and when the player wins a level.

Blender for 2D

To say that Blender is a piece (a big piece) of software used to create 3D artwork gives no one surprise, what might surprise a few people is that it's is also perfectly suitable for certain workflows on 2D image creation too. After all, once rendered, all you get is a 2D image. Since I still don’t know how to paint properly, I can, but I take too much time to do the simplest of the renders, before starting I knew I'd try to use Blender whenever I could. The secret here is to use shaders in a “creative” way, I ended up creating a radial vfx sprite and the coin icon sprite using blender, both done pretty quickly. I’ll explain more about how I’ve done the coin icon right away.

A new coin icon using toon shading and photoshop retouching

New coin item.

The first coin icon was not beautiful, to say the least. It was a pre-rendered image of the 3d coin in a slightly turned angle. The problem was that it was not blending in well with the rest of the user interface.

I needed to do something about it but I wasn’t sure on what visual route to take. On a completely separate event, watching random digital art tutorials on YouTube (a habit that I’ve acquired in the last 18 months or so), in the middle of the tutorial a guy taught a type of toon shading that was really easy to implement using Eevee and looked really good. The trick was to combine the gradient ramp with strategical light positioning.

The result was something that was resembling the Spider-Man Into the Spider-Verse movie, even though I still haven’t watched it, its visual content is too strong to no be influenced by it with just the trailers. It was really nice, my talented friend Pedro, a digital sculptor, said that he really liked the way I’ve portrayed the coin, I just need to add a little final touch of polish, it wasn’t making sense to continue working solely on blender, that was when I’ve moved the final compositing and the retouching work to Photoshop.

I’ve did two renders, each using different lighting. I’ve them combined both using photoshop and made it shine more using a few transparent gradients.

Radial image background for the new glove design screen

Final radial background image.
3D Mesh used to render the previous image.

If you look for information on how to draw this kind of thing using Photoshop you’ll find these laborious workflows that are nor fast nor flexible, either. Solution? Start the base of the work using blender and do a top view render, simple. How? Creating a low poly cylinder, deleting the laterals and the bottom. With a flat shading scheme combined with uniform lighting (ambient lighting) I got the image without going through any repetitive workflow.

The shell transition effect

For a long time I’ve been struggling to grasp the basics of shader programming. On one of my many sessions trying to code something with it I ended up creating a nice looking enclosure ellipse animation. Problem was that this had been created using the OnRenderImage callback which is full of drawbacks, and since I wasn’t processing the image itself, I just was doing a layer masking, it was just a waste, on the low-end device I was testing the game on, a Samsung Galaxy J5, it was always lagging a lot during the transitions.

After some investigation, I’ve decided to reimplement it using some kind of UI element, an Image, or ImageRaw component. To my surprise, the shader worked just fine with almost no changes and since I wasn’t reading the screen texture grab anymore it ran pretty smoothly on the J5.

Adventures in Sound Design using Audacity and freesound.org

For those who don’t know me, I like sound and music as well. I’ve been trying to educate myself on music composition and sound design too. For that I’ve used and recommend truly excellent courses from AudibleGenius (www.audiblegenius.com). Their courses are interactive, hard but fair, and have the right amount of theory. Anyway, confident that I’ve developed the minimum aural perception to at least do the sound design of the game justice to the visuals, I’ve embarked on this journey of learning yet another totally new skill. Skill in the singular because I’ve deferred the task of creating the pieces of musics to a freelancer, I just didn’t have the time.

As usual, when I try to learn something new, I look for conference talks of the industry to try to understand how they think, what are the problems they are facing, what’s been conquered, I look for courses—it’s pretty rare to find good ones, and books, I love learning from books.

Combining what I’ve learned, with free sounds from freesound.org and some sounds I’ve recorded myself, all mixed together using Audacity, I was able to create a sound palette to create variety for the punch sounds, a good water-droplet based transition sound and a few more. The composer also created a very good coin grab sound, that I’ve used without editing.

If you are starting, the “secret” I’ve found was layering sounds together, experimenting with different positions in time and volume. Using EQs, compressors and reverbs can also help a lot when trying to use sounds from freesound because there are a lot sfx from that site that are not exactly what we need but with slight editing, they become just perfect.

Making the game easier using feedback from people outside the project

Balancing games is hard, and I’m not talking about multiplayer competitive games, those are almost impossible to balance, the subject here is making an approachable, learnable game, with good pacing. Oh lord, that’s also a really hard problem. Before undertaking this problem, verify if the game you’re trying to balance doesn’t have a cursed problem—cursed problems are a class of game design issues that have no perfect solutions, there’s always a compromise, see more at https://www.youtube.com/watch?v=8uE6-vIi1rQ.

Now that you know that your problem isn’t cursed or if it is that compromises are inevitable, you can start testing your game with people not from your team. Yep, you need a constant influx of feedback from people outside the project, once our eyes—and hands get used to the game, it’s really hard to have that so necessary naive look from a beginner. Stages that I considered easy were really hard for most people. And, of course, you can’t use the same person too many times as they will also lose their naive approach to the game. That’s not news, I guess, for any experienced game developer, but I found valid to reverberate that idea once more due to the impact it had on the project.

Armed with the notes I’ve taken from these people I created several way easier levels, that required much less hand-eye coordination and timing in general, this made the game much more enjoyable.

With time I’ve started to learn what is hard and what is not for the beginner player, and that led me to a level design classification system which will be explained in a further section.

Winning choreography —inc.: confetti sprite sheet animation

To appeal to the reptilian section of the brain we need to reward our players when they just nail the game. There are a few things that change on the winning choreography that are dependent upon how well the player done in the stage, the numbers of oysters that will open (oysters are our “stars” in a more common game system) and the sound and look of the CLEARED or PERFECT label, the sound for when the player gets a perfect is much more energetic. I’ve also decided to use confetti to shake things up—camera shakes included.

To do a beautiful confetti I knew that simply using a single frame particle system wouldn’t be enough and relied once again on Blender to create a spreadsheet animation of a small piece of paper bending around itself, this sprite sheet animation is used by the several particle systems that compose the effect. The particle system is very simple, uses the gravity and noise module, but they spawn just in time coinciding with the opening of the shells, creating an energetic and rewarding sense of rhythm. They are also randomly colored by the particle system using vertex coloring picking from a rainbow gradient.

Deforming the ball on contact and the incredible Deform library

Now that I’m almost at the end of this breakdown I’ve realized that this project was nothing more than applying a lot of techniques that I’ve been learning and have been exposed to in the past months, I knew that if I could deform the ball where it’s hit it would create a very rewarding effect, making the punch feel yet more powerful.

There were two approaches that I could’ve used to implement this deformation, vertex shaders or the Deform (github.com/keenanwoodall/Deform) library. The main benefit of the Deform library is how easy it’s to use and iterate upon, shaders are cool, but interacting with them on C# scripts are always a nuisance. Since they run on the GPU by definition, they are not aware of the game context, this interface is always cumbersome.

Deform, on the other hand, was easy, and in less than an hour I had something really good working already. With a bit more work to coordinate the deformation with the punch motion the effect was pretty convincing and pretty lightweight too because it uses the magnificent Unity DOTS.

The ball trail vfx

By studying traditional art I’ve learned that we’re always connected to our past, we grow to love art by absorbing the work of previous artists. We can and should innovate, this is also a pattern observed if you study how art has evolved through the millennia, but there’s always something that can be traced to the past, even in the modernist movements. I accept that as a fact. That was probably the most elongated way to say that I like to use references, and indeed I’ve used lots of them.

Every cartoony game, and others not so cartoony, use trails, there are trails everywhere in gaming. Trails bring energy to movement, but they also help the player understand what happened in the near past since trails represent it. It allows someone to pay attention to some other aspect of the game and in a glance find the ball and where it came from.

To implement the ball trail vfx I’ve once again used Substance Designer to create the necessary texture. It was really easy.

Ball trail texture.

The rest of the work is all done by Unity, I just had to configure a few things in the trail renderer component. A low hanging fruit, that’s what I call this.

Animating stuff using coroutines, FSMs, and AnimationCurves

Admitting that I don’t feel it is the best way to achieve sequential events scripting is how I’ll start this section, I say feel because I know no way better. To create a sequence of events that last many frames I use coroutines, since they’ve been implemented to do exactly that on Unity, it’s not a misuse, but what I feel is that it lacks responsivity, both in terms of iteration speed and immediate visual feedback while authoring, since what I was working on was pretty much coordination of things that move on the screen I felt the necessity of something more visual. Perhaps a visual scripting system like Playmaker or Bolt (Unity timeline, perhaps?) would give me more “milage” for the time spent, that’s certainly something I’ll investigate before starting a next project, how to create scripted sequences on a more visual way using Unity.

Having said all that, the way I’ve implemented those things was by creating AnimationCurves, one for each type of movement (ease-in, bounce-out, etc) and storing these curves for reuse on a master animation curves game object. That was the only visual part of the process and I enjoyed it. Some animations required custom animation curves that were created directly in the object responsible for coordinating the animations—object that owns the coroutine.

A special case was the Win Choreography, I wanted to allow the player to skip an animation sequence if the screen were to be tapped. To do that using coroutines would be a nightmare, I even started doing it, but gave up before pressing play on the Unity editor for the first time, the answer was obvious, what I needed was a full-fledged Update loop backed by a finite state machine (FSM). Since it was a linear FSM the transitions were done using a single switch statement, making my life really easy, and the result was splendid. It’s funny, there are things that happen in games all the time, by the nth-time I see it I start to wonder how they could’ve implemented it, that was one of them. In reality, I’ve been tinkering with this problem on my head for ages, that’s why I was able to finish this feature so quickly.

Making coins follow a path using splines

Ever since I have used Unity to work on my final project for college I had almost zero contact with the engine for several years. To my surprise when working on that feature the engine still lacked a standardized way to work with splines, a ubiquitous mathematical structure used in game development. Unity has it all over the place, in different modules of the engine, but none available through a C# API. Somewhere in their forums there was a unity engineer saying that they are unifying their spline implementations and will deliver a flexible and capable spline implementation, while this doesn’t happen we need to run our own solutions or rely on third parties, which is what I did.

Sebastian Lague has released his spline work for free, including source code and examples, it was by far the best free spline tool I’ve tried, I had to test two other ones before finding his'. Most would assume that you want to attach their components having ease of use in mind and a few specific use cases. What I liked about Lague’s approach was that his library is very lightweight in terms of abstractions, you can use the objects he has designed in your own MonoBehaviours without needing to do inter -omponent communications, which was great.

Mixing two tracks — A DJ mixer abstraction

Surprisingly unity doesn’t have an easy built-in way to mix two tracks, for that an abstraction of a super simple DJ table has been created by me. The dj table object has two audio sources, one for track A and another one for track B, its main interface is the method CrossFadeMusicTo that takes an AudioClip as a parameter and the user of this object don’t need to do anything else, the track will be faded to this new one. Fading happens by adjusting the volumes and nothing else.

Hiring freelancers and communicating what you have in mind is not easy

Summer Punchball was my first project in which I’ve hired freelancers to work on a creative project. Something that’s crystal clear to you is likely to be very blurry for the other person, for a multitude of reasons of course, but mainly being that they are not living the project every day like you are. To my luck, I had been studying a bit of each of the disciplines involved in the production of a game, that allowed me to be more precise when describing what I wanted from them, but even then it was not easy.

Since we’ve established from the beginning how many changes and the kind of change would be allowed before they could charge again I think it worked very well in the end. The lesson is, be very specific if you have something specific in mind.

A level classification system imbued in a spreadsheet and a level difficulty chart

At first, completely lost in the darkness of the level design alley of Summer Punchball, a system to classify the stage features revealed necessary, that system imbued in a spreadsheet constituted what allowed us to see how hard the game really is, what should be done with it if the market accepts and become friends with the game.

The first step was to try to classify the main ideas used in the construction of the levels. I soon realized that there were main two forces driving the creation of levels: skills to be learned by the player and ways to entice them—called flavors.

Level design is a discipline that consists of teaching the player ways in which the game can be played, helping the player master all the skills required to play the game effectively. So, the skills to be learned column was obvious, what was not so obvious was the flavors column, because a game shouldn’t feel like work or simply studying, we can't rely only on teaching new mechanics or skills, the game has to create a sense of wonder for the player, this is what the flavor column represents, that something else.

Briefly, the list of skills a player can learn in Summer Punchball are: move the glove laterally, drag down to punch, aim where you punch to do a cross punch, and ball balancing. Levels will have flavors to temper the desired “didactic” requirements. Examples of flavors are: spinning coins, ballistic coins static paths, zarabatana’s darts, and the big void (a stage that doesn’t have a supporting enclosure).

What you’ll see next is an excerpt from the mentioned spreadsheet.

Level Difficulty Learn Flavor Existing Stages
1 1 BP BCSP C1a
2 1 ML, BP BCSP, BGD
3 2 ML, BP, SI CP, LLO
4 2 WSP CI
5 3 ML, WSP SC, CL, BGD
6 1 BP, ML JC, BDS, LCO C1b
7 2 BB SC, LLO
8 2 ML, BB BCSP, LLO
9 3 ML, BB, WSP BVO C3
10 1 BP SC C4
11 3 BB, WSP BCSP, SK, LLO
12 1 CSP CP, LLO, CL C2
13 1 CSP, ML CP, BGD
14 3 CSP, BB CP, CL, BDS, LLO
Skills to be learnd and flavor/level excitement.

As you can see, the existing stage column is empty for a lot of rows, and that means the game isn’t 100% done according to this new balancing device. But it was good enough for us to test if people will like the game. I’m really proud of this exercise and to ship this initial version a second spreadsheet was created only using existing stages.

Chart difficulty.

This chart shows the expected difficulty level of each stage and is crossed by a trendline.

Acknowledgments and important lessons

To finish this tome I can’t thank enough my fiancée, Thais, that always kept me firm over the ground, releasing me from my impossible dreams and enabling us to release the game. As the project evolved she started to get more involved, contributing not only to testing but also to the game and level design, as well as working as my manager and feature prioritizer. Without her help, this game wouldn’t be ready. Hey, did you know that Summer Punchball is already playable on Android and it has 17 levels? Go play it on the PlayStore.

I also would like to thank all my friends and family that played the game to help me test it and validate that the main mechanic was fun, my friend Gabriela Bee that was always available to help me with artistic choices and also a special thank to Pedro Martins, who sculpted the Glove, one of the three main objects of the game, he has also worked on the UI and the logo which are both phenomenal. The game is way better with his contributions.

The main lesson here is that if it isn’t a clone, be prepared for the unknown. Even when doing clones you’ll face implementation issues, with original ideas there also problems in the design space, and solving those only in production is costly but sometimes unavoidable. Always break down what you’re trying to do in achievable tasks, even listing what you need to list is valid. Finally, fight the urge to make the project bigger than it should, this is a constant battle.


Classify in
  • Postmortem
  • Unity
  • 3D Art
  • Game Development Process
© Bladecast 2020. All rights reserved.