Saturday 15 March 2014

Level Design and Flow

So Recess Race is coming along nicely, and I couldn't be happier about that.

What I am working on most right now is level design. I've had formal training in level design, but my experience in this field is still only a couple of years old. There's a lot I have to learn, and I learned something recently that I would like to share.

First, if you don't know about Flow - specifically the flow state as described by Mihaly Csikszentmihalyi - you may want to read up on it a little. If not, a whole lot. Like read the book of the same name.

tl;dr: the flow state is where you are so focused on a task or activity that you lose track of time, yourself, and everything unrelated to the task. Ever been so involved with something that when you looked at the clock you realise you should have left for work ten minutes ago? It's because you were in a flow state.

Video games aim to get the player into a flow state. It's how they hold your attention and get you addicted. Because the flow state is very addictive and a game that can reliably produce it is valuable to an individual.

One of my best friends was playing a level last night, and brought to my attention that certain specific spots were flow-breaking. I was defensive at first (as we always are... pff, artists, amirite?). Then I realised that was just about the worst thing my level could be. It should be catalytic to flow in as many ways as possible.

What breaks the flow?

This is one of the specific points my friend pointed out:



The black line is the jump arc of the character. The red box is the character's collision box. As you can see, jumping from that point, the player will collide with the side of that platform. I don't have ledge grabs in Recess Race; this means the player will have a hard time getting up to the top platform without being conscious of this. They will have to hold the jump button to get enough height to clear the platform, and also hold left for enough time to get on top of it - but not for too long, or they won't have time to turn around, and they'll fall off the other side.

This problem makes the player feel there's something wrong with the physics or the level. That's the problem right there: if the player knows it's their fault that's fine, they'll be willing (even excited) to try again. If they feel it's the level/game's fault, they'll get frustrated and become more likely to ragequit.

RULE: The player must know exactly why they failed, and must feel it's their own fault. Otherwise the flow will be broken and they will want to quit.

How difficult is too difficult?


Difficulty is a problem I've always had. I, like many young designers, tend to crank the difficulty when something is too easy for me. This is deadly. If something is difficult for you, who designed the level and have been working with the mechanics of the game for months, that means it will be nearly impossible for a player picking it up for the first time.

The philosophy I've adopted for Recess Race has been: easy to play, hard to master. This is something Nintendo has done best for decades, and it's present in every game they release. It's particularly important to inducing a flow state. Consider this flow chart (pun intended):



A condensed version of the theory behind this: when the challenges presented to you are appropriate to your skill level, you will be more likely to be in a flow state. If a challenge is too difficult you'll get anxious, and if it's too easy you'll get bored. You'll also notice there's some wiggle room here: that's because sometimes a challenge is just a bit too hard for you, and knowing "Oh man I can totally make this if I try for a few minutes" is an awesome feeling. Then you beat the challenge and your skills have improved, meaning challenges of that difficulty are no longer as daunting. And you climb the "Flow channel".

So, how does Nintendo do it? I'll make a list.

1) Simple or recognisable gameplay: everyone knows how to play a 2D Mario game, and if they don't then they're likely playing with someone who does and they'll learn. They've never necessitated players to learn more than 2 buttons: Jump and Run; A and B. This means that players can feel comfortable that they'll never have to learn another button, which is reassuring.

2) Secrets. Secrets everywhere: discovering a secret is fun. It's so satisfying! In pretty much every circumstance. Because there's lots of different kinds of secrets. To name a few:

  • Hidden mechanics or abilities: Super Mario 3D Land/World has a bunch of jump types. Crouch-jump, long jump, cartwheel jump (running in one direction, snap to the other direction and jump, gives you a higher jump than usual). None of them necessary to get to the end boss, but each super fun to discover/experiment with.
  • Collectibles: again, in Super Mario 3D Land, each level contains 3 star coins that are usually difficult to find or present an optional challenge. These are great because they can be as hard to get as the designers want, because they're not necessary to complete the game. The player knows there's 3 in each level, so they might not be a secret per se, but they are often well hidden which makes them nonetheless fun to find.
  • Secret collectibles: in Braid, there is a type of collectible that I didn't even know about after having (in my view) 100%'d the game. Someone told me they were there... and I had 20 more hours of gameplay in front of me. Sadly, this is an area Nintendo is not wont to delve into. They have in the past, but not for decades.
3) Difficulty settings: done wrong, difficulty settings are stupid and useless. However, done right, they can feel organic, empowering and enhance every user's experience. The Legend of Zelda: The Wind Waker HD is a great example. Right off the bat, you have the option of playing the game in Hero Mode. Wait, what? Awesome! I want to be a hero! ...I take double damage? And there are NO RECOVERY HEARTS?! Oh dear... well, here goes nothing. This difficulty setting was a fantastic move from Nintendo: they know a lot of people have played the game before, so they don't want those guys to get bored with the same challenges, and this is super easy to implement. It also shifts the player's focus considerably: I had to keep track of every fairy fountain and constantly go back to visit my grandma to get soup. Going into a Gauntlet room unprepared was deadly (but super fun, I'd recommend it :D ).

I feel strongly about difficulty settings and some day I'll do an article all on those. Point out some shining examples.

So how does this apply to Level Design?


Most of the points in the previous points are actually about game design. I'll list some things I think are important for your level to be fun from beginning to end.

Difficulty curve: the most important. If you aren't conscious of how difficult your level is at each point, it will be impossible to shape an enjoyable experience for the player. Your difficulty curve should actually look a lot like the wavy line of the Flow Channel chart above. To make your own difficulty curve, look at each challenge in your level and rate it on a level from 1-10. Then look at the figures: do they generally increase as the level goes on? Is there ever a jump of 3 or more units (that's generally bad)? Are there 'break' spots where the difficulty decreases after a particularly hard spot?

Placing ingredients: when I say ingredients, I mean anything in the level that the player interacts with. It can be a special type of platform, or an enemy, or a pick-up, or even a specific platform formation that requires a specific skill. Always introduce these on their own before placing them in combination with other ingredients. 


Here, the goomba is entirely on its own. You will either figure out a) it kills you, b) you can jump on it, or c) that you can jump over it and it's ok. Later on, you'll see it between two pipes so it patrols between them, or in combination with other types of enemies, or even just with more goombas. The challenge is much greater in combinations like these, so use them wisely. They can also be the most interesting and exciting moments for a player.

Give the player something to look forward to: this is difficult to explain, let alone pull off. It involves giving the player some kind of hook: something they know is going to come back later, or a task they need to work at for the whole level, or a big looming structure they hope they'll be able to visit later on. Some sort of mystery to keep them guessing; to give them a reason to keep playing. In Recess Race, it's the desire to finish well; to beat the other racers (bullies) who will beat you up/call you names if you get too close. You want to prove your worth! And the only way I let the player do that is by being awesome at the game. So the plan is to make the player feel as awesome as possible for as long as possible, and that means keeping them in a flow state :)

Well, that will be all for now. I hope you enjoyed these musings, and implement them in your game (if that's what you do!).

Until next time,
Keep flowing, super surfer.

-mysteriosum(the deranged hermit)

Thursday 6 March 2014

Recess Race Announced!

This week has seen a big step for the deranged hermit and his friends. It is my pleasure to announce our game, Recess Race!



Many Hands Make Light Work


I've been working on Recess Race for months (as some of you know...). I've done several prototypes, and gone through many design transitions as a result. But, when I felt I had the final design down, Serendipity played her part and a team fell into my lap! I am working with Will from Temp8 and Richard-Bananas now, and after one month of production, we're already nearly done the alpha.

It is wonderful to work with other people, especially if those people are fun, intelligent, hard-working and like-minded. I recommend, to any of you lone indies reading this blog, find someone to work with whose skills differ from your own, but who shares similar goals. And trust fate! If you happen to meet someone who vaguely fits this description, do not hesitate! Pounce upon them and never let go.

Concept art: in-game "screenshot" mock-up

So... What IS Recess Race?


Recess Race is a 2D platformer racing game. It takes place at an elementary school, where the administration has organised a race event with the ulterior motive of cleaning up the yard. The participating children must race to the finish, all the while picking up as much trash as possible. But, the other racers are bullies! If you get too close, they'll beat you up or call you names.

Recess Race is a game that comes from the very depths of my soul. It has spawned from a tortured elementary school experience, where I was bullied more than anyone enrolled (in my head at least). I had to cope somehow, and that how was video games (and my awesome family). No matter how badly people treated me, I knew I could go home at the end of the day and play a video game. I could have an impact! I could use my skills to do some good. Whether that 'good' was rescuing a princess, getting food back from the malicious Dedede, or smiting the Maverick leader Sigma, I was responsible.

In-game screenshot! Pinky is this alternate universe's Kirby


I bring elements of these games into Recess Race. Mario Kart-style power ups include: booger armour that give you a Megaman X wall jump; a dapper tail coat which allows you to glide as in many Mario games; and a magic hat that allows you to float-jump like Kirby.

Next step: pre-alpha web release!


In the next week we're going to have a playable pre-alpha version on our website. If you would like to keep abreast of our activity, you may follow me on Twitter: @derangedhermits, or find Recess Race on Facebook here.

More news forthcoming! 

Thanks for reading. Until next time...
Stay strong, stalwart stewards.

-mysteriosum(the deranged hermit)

Monday 3 March 2014

2D Platformer Collision Detection with Raycasts: One-Sided Platforms & LayerMasks

Something that happened magically while developing this system was one-sided platforms. That is, platforms that you can go through easily on one side, but from the other side it doesn't work, it's a wall.

I stumbled upon an elegant solution I love very much, and I will now share it with you!

These platforms are rad


Lots of platforms in Kirby can be accessed from underneath


So you may be asking yourself, "Why do I want these platforms?" The answer is usually: they're rad (sometimes, it's: you don't). They can add a lot of depth to your game. They give options during level design, opening up puzzles, dexterity challenges, and other such intricacies.

OK that's enough talking let's code.

Layermasks & Bitwise Operations


Layermasks are integers that inform a Raycast what to pay attention to. They are key. Once you start using them, you'll never go back and you'll be very glad you have this skill in your pocket.

What is a Bitwise operation? In this case, we'll be dealing with a bit shift. This requires a little bit of binary, so if you know all this stuff you can skip right to the line of code where the binary operation is.

Binary is a counting system exactly like our normal one (Decimal), but instead of counting all the way to 9 before reaching 10, we count to... 1. 0, 1, 10, 11, 100 are 0, 1, 2, 3, 4, respectively.

In any number system, the leftmost digit (or bit in binary) refers to how many of the highest exponent of the base are in the total value. In Decimal, 854 is literally 8 * 10^2 + 5 * 10^1 + 4 * 10^0. A 0 exponent always gives you 1 no matter what you're putting to it.

So, 11011001 is:
1 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 1 * 2^0
which simplifies to
2^7 + 2^6 + 2^4 + 2^3 + 2^0
which simplifies to
217

For Layermasks, we will go from 2 ^ 0 to 2 ^ 31. This is because we have 32 different layers in unity, each of which is assigned an integer from 0 to 31. If you say Layermask.NameToLayer("normalCollisions") in my code it will return 31.

So, the Layermask is always a 32 bit integer. But, what matters in a Layermask is not the value in Decimal, but the status of each bit. Each  Let's say your Layermask look like this:
1000 0000
0000 0000
0000 0000
0000 0000
The value is 1, but that doesn't matter. In this case, the Layermask tells the Raycast only to pay attention to 1 layer, Layer 0. If it looked like this:
1000 0000
0000 0000
0000 0000
0000 0001
then it would look at the first and the last layer. Its value is 2147483649 but again, that doesn't matter.

So how do we make a number look like this? Luckily you don't have to spell out your own binary numbers and convert them to Decimal. You just have to do a bit shift. A bit shift looks like this:

int collisionLayer = 1 << 31;

This means you're shifting a 1 to the 31st position in a binary sense. But that's just one layer. What if we want to do more than one layer? Easy.

int collisionLayerPlus = 1 << 31 | 1 << 30 | 1 << 0;

The | character indicates we're shifting more than one bit in an integer. Now the Layermask will look for collisions in the 31st, 30th and 0th layers. For fun, this is what the bit will look like:

1100 0000
0000 0000
0000 0000
0000 0001

If you're having trouble with any of this, please google Bitwise operations, or bit shifting, or even just layer masks and someone else will give you a better explanation (because there's lots out there :).

What I did was set up a class with static variables that contain these bitwise operations so I don't have to keep doing them in my code. This is what it looks like.







That's it! That's all it is. Now we use it elsewhere.

...What? You want an explanation of this too? OK fine...

Well first you'll notice the class doesn't inherit from MonoBehaviour. That's because it doesn't need to! I'm not going to put it on an object - in fact, I'm never even going to instantiate one. All it needs is those static ints that can be accessed from anywhere, at any time. I'll do that later.

The other fun thing in here is the static constructor. I don't fully understand how a static constructor works, but I guess it probably calls that when it needs to to give values to the variables I declare above. I can't use functions like Layermask.NameToLayer in a variable declaration like that so I had to use a static constructor.

Last, softBottom is what I call the kind of platform you can jump up through. softTop is what I call platforms you can fall through but can't jump up through. They're evil. And fun! :D

Now let's use the darn things!


Let's start with platforms that you don't hit your head on. Ones you can jump through from underneath but will then land on stably. Find the code where you look for things to bump your head on.

....we haven't done that, have we? Oh...

Well, we'll do it at the same time! It's related.

Here's the final code.



You'll notice it looks a lot like our other directional checkings. That's because it is pretty much the same.

There are two main points of interest here:



Here is where the character hits his or her head. If a platform is there, teleport to the point of contact, and set your velocity to 0. The other option (a la Mario) is to have a little rebound. I like to use a fraction of the upward velocity you were moving at, assigning it as a negative velocity.

And...



This is where we use the Raylayers class. It dictates what I'm going to detect with my up-layers. In this case, I will only bump my head on things in the NormalCollisions or SoftTop layers.

Now all you have to do is assign a platform the SoftBottom layer and you won't hit your head on it!

It's really that simple. A few lines of code and a lot of functionality. It's just as easy to add the SoftTop platforms (just add the right layermask) and to add one-way sideways platforms (which are also quite interesting).

I know my explanations in this post may be a little hasty, so if you have any questions please feel free to leave them in the comments and I'll get back to you as soon as I can. This was supposed to be a really short tutorial but it ended up... not being. ^_^

Thanks for reading!

Until next time...
Stay smart, little mite.

-mysteriosum(the deranged hermit)