© Minhaz-Us-Salakeen Fahme, Tanimul Haque Khan 2021
M.-U.-S. Fahme, T. H. KhanHow to Make a Gamehttps://doi.org/10.1007/978-1-4842-6917-6_11

11. Help!

Minhaz-Us-Salakeen Fahme1   and Tanimul Haque Khan2
(1)
Narayanganj, Bangladesh
(2)
Dhaka, Bangladesh
 
In this chapter, we are going to talk about some specific mechanics and even share some pseudo code on how to implement them. In this chapter, you will learn about the following:
  • Difficulty settings

  • Rewards vs. punishment

  • Game mechanics: Jumping

  • Game mechanics: Health

  • Game mechanics: Movement

This chapter is dedicated to a few game mechanics that can significantly improve or ruin your game experience. A good game should help the player to play the game. Enemies in-game are but obstacles for players to overcome. Almost all games have multiple paths for players to choose from. The main story is called the critical path. This is something that should be the easiest feat for the players. When you make a game, it needs to target a huge number of audiences. Targeting a niche audience for your game isn’t always a great idea. It’s not easy to please a niche audience. Then again, you want to empower the niche audience to some extent.

Player Types

There are a lot of types of players in the community. Here’s a list so you can understand the situation better.

Type

Characteristics

The novice

Plays very few games

Story hunter

Cares more about the story than the gameplay

The casuals

Plays a few hours per week

Achievement hunter

Cares more about finding secrets over actual game completion

The hardcore

Plays games daily and has a schedule

The magician

Can play at least one game with their eyes closed

The nerd

Eat ➤ Play ➤ Sleep ➤ Repeat

The lower you get down the chart, the harder it gets to please those players. Your ideal player base is the top four types of players. They are your major audience. But the players who will truly appreciate your games are the latter three types.

Now you have a problem. You can’t possibly make a game that will please all of players mentioned in the chart. Their tastes are different. Their expectations of games are different. A niche player base that is your actual appraiser wants a game that offers challenges while the majority want a game that’s a fun way to pass time.

This brings us to our first topic: difficulty settings. How do you implement good difficulty settings in your game?

Difficulty Settings

When we start a game, we are usually faced with a choice. We need to choose the difficulty: easy, medium, or hard. As a first-time player, nobody knows what each setting will offer. But this is one of the deciding factors of the game experience the player is going to have. Every player wants to have a fun time, but the definition of a fun time isn’t the same for every player. Let’s take Resident Evil 4 as an example.

It is the fourth installment of the franchise, and the game already has veteran players (hardcore category). By veterans, we mean the players who played previous installments and are familiar with the gameplay. If the game is too easy for them, they will lose interest. And if the newcomers find it too difficult, they will abandon the game.

Just stamping an easy, medium, or hard difficulty setting at the start of the game is not a good choice because it doesn’t explain or adjust to the actual skill level of the player. How does a player know which mode is the best experience for them? A lot of games briefly explain what each mode offers. This has a lot of other problems. For example, this can be a spoiler alert because you are potentially telling how the game will go on, so there’s less surprise in the game. Aside from that, this still brings us to the first problem. How does a new player relate to “enemies have low health?” How low is actually low? Nobody can actually know without playing the game first. A fixed difficulty scale is a really bad UX.

There’s another problem with fixed difficulty. Let’s assume the players selected the easy mode and they’re actually a new player. Over time, their skill in the game will get better. At some point, they will no longer face any challenge because the difficulty is not increasing.

Consider it the other way around too. Let’s assume the player has selected the hard mode from the start and is having a very difficult time playing the game and is getting frustrated. But over time their skill will increase. And at some point, they will reach the point where the game is no longer difficult for them anymore. Hopefully, the game will be over by the time the player reaches this point. But what if they reach this point before the game ends?

What you want is a dynamic difficulty setting, a difficulty setting that adjusts itself according to the player’s skill. If the player does well, the difficulty rises. If the player does badly, the difficulty lowers. But it never rises too high to frustrate the player and never goes too low to make it boring. It’s called the flow state; see Figure 11-1.
../images/499184_1_En_11_Chapter/499184_1_En_11_Fig1_HTML.jpg
Figure 11-1

Flow state chart

Resident Evil 4 is a prime example of this dynamic difficulty implementation. This game had a hidden difficulty setting that adjusts how the AI works depending on how the player is progressing. This is something the developers can find out by analyzing the performance of a player. For example, if the accuracy of the player is too low, maybe make the zombies move slowly so that players can shoot easily. And if the player’s accuracy is too high, make them move faster. This way this game is not too frustrating for new players and not too boring for skilled players because the game adjusts its skill cap. This is explained in Figure 11-1.

On the x-axis is the player ability, which rises over time, and on the y-axis is the difficulty. If you have a constant difficulty setting on the y-axis, you will have a problem. Over time the skill of the player will increase. As the player becomes more skilled and the difficulty stays fixed, the players will enter the boredom state because there’s no longer a challenge.

And there’s the other state, anxiety. If the difficulty is already too high, the players will enter this state if their skill level does not match.

What you want is to be in the flow state. The flow state is the dynamic difficulty settings because the flow state will change for each player. What this state does is expand the horizon just enough to keep the player out of their comfort zone. And it keeps expanding according to their speed of improvement. Being in the comfort zone is what you want to avoid. This is where the players are struck with boredom. Also, expanding too much brings anxiety.

Ideally, the flow state is what you want to achieve in modern games that tend to target a vast range of audiences.

That being said, some games target a niche audience with this artificial anxiety. Some players even enjoy this; there are games specifically designed to keep gamers in an anxiety state.

The most common example is Flappy Bird. It doesn’t have much to offer other than frustration. The only reason you probably kept playing the game was to show off on social media how much you can endure the punishment. Yes, gamers really like to flex. This is a form of psychological manipulation. Making the game unusually hard is a way to attract experienced gamers who are very hard to satisfy.

Frustration is a very sharp double-edged sword. You should handle it with care. We can cite Bennett Foddy, who is mostly famous for his frustrating platformer Getting Over It. Now, he has made an art out of it. There’s even a blog post by him where he describes different flavors of frustration and why game makers should embrace them. If you can play well with a double-edged sword, it is definitely a very handy tool in a battle. However, it is equally dangerous as well since you might end up hurting yourself. Developers tend to make this mistake a lot.

Another good example of a difficult game that is a measurement of flex in the game community is Dark Souls. It’s very well known for being very difficult from the start. Being able to finish this game in any difficulty is a crown for a gamer to wear.

Some games do this the wrong way. They develop a broken game and make it unplayable to achieve this state. But that’s not how this state is achieved. The game needs to be playable. This is something that we can learn by following what Konami did with Castlevania, another genre-defining title. They too were developing a game that challenged the players. But to ensure that the difficulty wasn’t something impossible, they had the developers play the game. If the programmer who scripted the boss fight couldn’t beat the boss without getting a single hit, they had to fine-tune the script until they could. This way they knew the game was beatable.

Both Flappy Bird and Dark Souls do this right. The mechanics aren’t broken. The game isn’t unfair. There are players who have finished the game. So you just need to “git gud.” But there’s a problem in making a game hard. As shown in Figure 11-1, as time passes, the skill of the player will increase. No matter how high the initial difficult cap was, players will eventually get to that point where their skills are way above the difficulty. And they will fall into the boring state. But as a result, we see new self-imposed difficulty increase in games now.

Yes, players themselves can increase the difficulty of the game manually. For example, Dark Souls offers armor for survivability and even health potions. Some players abandon them from the start and try to finish the game so that they can get that thrill of artificial anxiety state the game can no longer deliver normally. There are players who have finished the whole game without being hit a single time even though they used a wooden stick instead of a sword to beat the game. This is major flexing but we can learn something from it. There’s a crowd out there who yearn for games that keep players in an anxiety state rather than the flow.

But this is a niche audience. The recommended difficulty setting design is the dynamic difficulty setting instead of the classic easy/medium/hard choices.

Note that Resident Evil 4 wasn’t the first game to implement dynamic difficulty. In reality, this is an age-old concept. It has existed since the 1980s shoot ‘em up games. Also, Max Payne had this setup.

There’s always the option to mix both of the approaches. The recent versions of EA SPORTS FIFA offer the option to choose a difficulty when you begin your first game from the menu option “Kick-Off.” This portion is the predetermined approach. After that, based on your performance in the match, the game suggests some changes in the difficulty level. It asks whether you want to play with a higher or lower difficulty before you begin the next match, although this suggestion might not be very effective as most players have too much ego to lower the difficulty after the game says to do so.

So what’s the drawback? This game keeps the player in the flow state for the best experience. But we as humans tend to want to be in the safe zone. If the players know that the game adjusts itself when they start playing badly, it can be misused. For example, players can intentionally play badly in some sections to avoid difficult fights so that the game always thinks the player to be on a lower skill cap than they are. Although the players have every right to play the game however they want it to, it may not be the best experience you as a game developer want them to have.

We talked a lot about ideas on how to design difficulty code. Let’s now code a simple dynamic difficulty. By no means is this an easy system to develop. But for the sake of simplicity, we will take a game that we already know, and develop a dynamic difficulty setting around it.

We are assuming all of you are familiar with the House of the Dead series. It’s an arcade game. Arcade games are where the dynamic difficulty shines the most because the business policy behind arcade games to keep getting coins out of you without frustrating you. So if the game is too easy, you can finish the game in one try, which is bad for business. At the same time, if the game is too hard, you won’t want to try it since it’ll take too much money, which is also bad for business. So a constant flow state is required where the game adjusts itself to its player’s performance and makes sure they have to drop a few coins to end the game.

So how do you add dynamic difficulty in House of the Dead? Before you dive into coding, let’s analyze how to do this. First of all, let’s mark the properties that you will need to modify for difficulty change. First, you will see how the conventional difficulty setting is done, and then you will update it to be dynamic.
  • The health of enemies (number of bullets needed to be killed)

  • Speed of enemies (the faster the enemies will attack you)

For simplicity, let’s just keep track of these two properties. First, let’s see how to make conventional difficulty settings for these two properties. You can make a small preset table for the enemies that you want to modify for difficulty changes.

Enemy Type

Health

Speed

Boss 1

100

10

Boss 2

150

15

Boss 3

300

18

Boss 4

500

20

Let’s assume three modes: easy, normal, and hard. And the chart here shows the default values for the enemy health and speed.

These are the default values (or you can call it the Easy Mode). What do you do to make things harder for the player? If the health value is high, it will be harder to kill the enemies, which in turn, will make things harder. How do you increase enemy health? Or the speed? You already did that previously, in Chapter 8. Let’s take a look at the code again but the final version this time:
public class Boss1{
 Dictionary <int, int> difficultyMultiplier = new Dictionary<int, int>(){
     {1, 1f},
     {2, 1.5f},
     {3, 2f}
 };
 public int health=100;
 public int speed=10;
 public void initialize(int difficulty){
  healthModifier(difficulty);
  speedModifier(int difficulty);
 }
 public void healthModifier(int difficulty){
  health*=difficultyMultiplier[difficulty];
 }
 public void speedModifier(int difficulty){
  speed*=difficultyMultiplier[difficulty];
 }
}

This code simply updates the health values according to the difficulty that was set before. Depending on the mode the player selected initially, the health and speed will be set for that game.

So how do you make it dynamic?

For that, you need to get some kind of judging criteria first. Remember how every time you died in House of the Dead you were given a rank? So there was some kind of judging criteria to rank how well the player was doing. It could be based on several things:
  • Shooting accuracy

  • Remaining health

There can be more, but for simplicity, let’s take these two parameters to judge a player. You can make a table for the player too but that means you are fixing the player to some fixed preset values. You want to avoid this. So instead you make a function to understand floating points instead of whole numbers so that you can make little changes as needed. And you make a new function to place in some kind of rating system to judge the player and get a number out of it.
public class PlayerSkill{
 public float accuracy=0;
 public int maxHealth=10;
 public int remainingHealth=10;
 public float GetCurrentSkill(){
    float skill=accuracy+(remainingHealth/maxHealth);
    skill=Mathf.Clamp(skill, 0.5f, 2f);
    return skill;
 }
}

In this player skill class, when you call the GetCurrentSkill function you get a floating-point value that is clamped between 0.5 and 2. Why? Because you don’t want to go any lower than a fixed value. Otherwise, the game will become very boring. For example, you don’t want any boss to die with just one bullet no matter what, right? And with 2 set as the upper value, the player can’t go anywhere above that because it might make the game unfair. Please note that these values will be different for each game. 0.5 and 2 have no direct relation to this topic; they’re used as an example only.

So what does this code do? When you get the GetCurrentSkill for the first time, it will return 1 because initially the accuracy is zero and the health calculation also returns 1 as the remaining health and max health are equal. (Please note that you can define your own formula for ranking players.)

As the game progresses, the player will get an accuracy value. It can be anything ranging from 0.1 to 1. As the player gets hit by the enemies, they lose health and start adding less and less points to the skill function. So you have two properties that fluctuate. If the accuracy is good, the skill is good. The more health the player has, the better the skill.

Now you have a skill point. What do you do with it? You need to modify the previous code a little:
public class Boss1{
 public float health=100;
 public float speed=10;
 public void initialize(float skill){
  healthModifier(difficulty);
  speedModifier(int difficulty);
 }
 public void healthModifier(float skill){
  health*=skill;
 }
 public void speedModifier(float skill){
  speed*=skill;
 }
}

Firstly, you no longer need a dictionary to hold the preset data. Secondly, you change the data to floating points, which we explained previously. Thirdly, instead of the fixed difficulty code, you pass player skill.

What happens now is you get the current skill of the player at the point before you initialize the boss and change its health and speed values. If the player has good skill values now, the boss will have more health and more speed. If the player has bad skills, the boss will have less health and less speed.

This is an oversimplified version of a dynamic difficulty code. You don’t necessarily have to follow these parameters by the book. Even the equation to calculate player skill can be different. There can be more parameters. It will depend on the type of game you are developing. You can use the skill parameter for other components as well. Depending on the skill level, you can give the player some kind of reward. We will talk about rewarding a player in the next section.

Rewards vs. Punishment

There are two ways to guide the player on how the game should be played. The most common one is punishing the player for not playing the way you think they should play. Let’s take XCOM2 as an example of this.

XCOM is a turn-based tactical game. The developers intended the players to take risks in the game and get the best out of it. Instead, the players almost always take the safest route and grind to optimize the difficulty. It’s in human nature to play safe. To counter this in their next game, XCOM2, the developers put a new system which they believed to be something to guide the players to get the best experience.

What Did They Do?

They put in a timer system. In XCOM2, they added a timer system that forces the players to end the mission in a fixed set of turns, otherwise it’s game over. The developers had the best interest of the players but this new timer system met with controversy. The players hated to be forced to play in a way they didn’t want to. The players didn’t stop whining; they even made a mod of the game that removed the timer settings.

What Went Wrong?

Nobody likes being bossed around. The players won’t want to be forced to play in a way that you as a game developer may think is the best way to play. As a game developer, you must respect the players’ will to play the game as they want as well.

So How Do We Fix It?

The solution to this problem isn’t new. To be honest, it’s very old. Let’s look at some old games. World of Warcraft is an age-old MMO. MMO players tend to get addicted to playing a game. They lose a sense of time and sometimes they get sick. You as a game developer don’t want your players to be sick because of your game. One, you’ll get a bad reputation and two, they can’t play your game if they are sick. So the developers thought about this problem and punished the players for playing too long. The reason players play MMO for too long is the games are based on grinding. They have to grind for XP to make progress. The more they grind, the more they get powerful in-game. So the developers added a penalty on XP when the players played the game for too long. The longer they played, the higher the penalty. The community didn’t like this at all. It too faced controversy because it was clearly a punishment mechanic even thought it was good for the players.

So the developers came up with something smart. Instead of punishing players for playing too long, what about rewarding players who play less? So they tweaked the XP penalty mechanics into XP boost mechanics. Whenever the players took a break, their rest meter went up. The longer they rested, the more the boost was. So once they came back to play, they gained more XP while the players who didn’t rest had the same XP they did before. The numbers were the same yet the goal was achieved without forcing anyone.

Another brilliant example is by EA Sports. Its FIFA has been the market leader among all football video games for as long as we can remember. We are going to observe a reward related incident here and talk about our assumption regarding what might have happened there.

In the past few years, arguably the most popular game mode has been the Ultimate Team. Here you make your own team and play in competitive modes regularly. There are weekly competitions where you fight to secure a better position to get lucrative rewards. You keep grinding to make an overpowered team dominate the field. As long as you keep playing, they reward you with coins, reward packs filled with players, and other items. Every year, a new FIFA gets released around October. People start building their squad immediately. Some people even pay extra to get access a week before the official release of the game.

Since FUT (FIFA Ultimate Team ) keeps rewarding the player as they keep playing, it’s pretty much expected that somebody who starts in October will have a much higher rated squad after playing six months, right? Well, technically, yes. So, what happens to the player who starts their journey in FUT in March of the next year? They will start with a basic team whereas all their opponents will be in much better shape, right? The imbalance should be significant. But before you entertain that idea, let me tell you what happened to me.

I started playing FUT 20 in March 2020, whereas most of the players started six months prior. The division rivals mode (which you can play all week) was okay since it’s based on skill level. So, all the new players are put into Division 9, which is just one step ahead of the lowest division (Division 10). This is suitable to start the journey, but the issue begins when you start playing the Weekend League. The FUT Champs or Weekend League (WL) is like the weekly World Cup to the FUT gamers. Not all players can qualify here. You only get 30 matches to play within 3 days. This tournament gives away the most lucrative awards of the game. The matches are really intense and full of twists. The matchmaking happens mainly on how many matches you have won so far on that particular weekend. So, it’s very likely to match with a real pro opponent with a powerful squad. I faced this fate with my basic squad in my few WLs. It was painful.

Now, let’s consider FIFA packs. You earn them by completing objectives, doing well in tournaments, or purchasing them directly. They contain players and items for your club. Pack luck is one of the most discussed things in FUT. In any random FIFA group, you will always see people complaining about how bad their luck is, whereas very few people come flexing about how they got a super card out of a very ordinary pack. You can get a very low-rated player out of a costly pack and sometimes you can get the best player in the game from a very ordinary pack. I thought that pack luck was a myth because mostly I saw people getting very low-rated players from packs.

So imagine my surprise when I got an actual high-rated player in a pack one day! A few days later, I ended up packing the most recent card of Lionel Messi (99 rated card). Now that was a shock beyond imagination because not only did he fit in my team perfectly (I just had to replace his basic card, which became cheap at that time) but also he is one of the most sought out players in the game. Seeing me packing him, people offered to buy the FUT account from me!

Surprisingly, that was not the end. I kept getting great players from packs once in a while, and eventually my team became one of the most highly rated teams among most of the players. Meanwhile, my friends, who had been playing the game since last October, became furious about my pack luck because even after playing much more than me, their team was much below standard than mine. It felt like just dumb luck at that time. But when I look back, I remembered that before packing Messi, I was just about to give up playing FUT because of the constant bullying I used to face in the Weekend League with my basic team. I played FIFA 20 wholeheartedly until the release of FIFA 21.

Maybe I didn’t deserve that overpowered team but it was necessary to keep me going.

Looking back, it all feels connected. I had help, maybe. Disclaimer: We don’t claim to have known this for certain. Just entertain this as an outcome of logical deduction, nothing official.

Let’s Fix XCOM2

Now let’s do a little brainstorming. Close the book and think about how they could have done the same thing in XCOM2 without making controversy?

So here’s our suggestion on how they could have done it. Instead of adding a timer that ends the game, they could have made it into a challenge that rewards the players greatly. For example, if the players can finish the game on X turns, they will gain a very powerful weapon or character.

Mobile games propose a good solution to this problem. Most mobile games have this concept of stars. Each stage is rated with stars. If you can finish the stage in the most skillful way, you get the highest stars. And in some games, stars are totally optional. You can still finish the game even if you don’t get the stars.

This fixes a major problem from our last topic as well. How do we balance the best difficulty experience? Instead of blocking players from moving forward unless they match a certain skill threshold, maybe reward them if they play well enough. Give them a badge or something to show off that they played well. And let the casuals still enjoy the game.

A prime example of this are the games made by CAPCOM. Everyone knows about Devil May Cry. This series emphasizes stylish gameplay with combos. However, mastering the combos is no easy feat. You can finish the game without even realizing the game has such good combos to offer if you can master them. This opened up the game to a larger player base. Newcomers can just play the game in easy mode and not worry about the combos at all. But the veterans can use their skills to enjoy the game to its full potential and feel rewarded by the game with its ranked scoring system. The ranking system itself has zero impact on the game’s critical path, so it doesn’t block the players from progressing. But often the game hides some special reward behind the skill cap. Some challenges are made for skilled players to feel rewarded. These are hidden rewards that players have to find themselves. They might even miss them entirely. As a result, neither the veterans feel left out nor do the freshers feel overwhelmed.

This isn’t the only example of punishment. Remember those stealth games where the game just forces you to replay if you fail to play stealthily? It’s a bad game design. It means you as the developer just didn’t account for other playstyles. If you want your players to play a game in stealth mode, reward them for doing so. But do allow them to just go Rambo if they want. Hitman, for instance, does this very well. You can always just kill everyone in the mission, but to rank on the leaderboard you will have to score well. And to score well, you must play the game in a very stealthy way.

There are some good examples of punishment as well. Punishing players for not playing the way you want the players to play can also be a great experience. It’s something that shouldn’t be overdone. We talked about Undertale before and the fight with Sans. This can be interpreted as a punishment. This battle only happens if you take your sweet time to kill every single character you ever encounter. You must even find NPCs that are not on the critical path. A game that promotes compassion as its core message would like to encourage you not to do so. The fight with Sans is clearly an off-the-charts difficult boss fight. It’s not intended to be won. Not that it’s impossible; it’s just a big wall that discourages you to be a bad guy. Sans keeps telling you to go back. Go back and be a nice kid. Some players may get frustrated and go back and be nice to finish the game. That’s very likely the intention of Toby Fox, creator of Undertale.

The classic example of punishment can be found in a game franchise that has probably been the most popular one for quite some time. We are talking about Grand Theft Auto (GTA) ! You can be a gangster with the capability to do almost anything in the game. This has been the synonym of freedom for an entire generation, if not more. The story modes have always been fun, but the most enjoyable part has always been roaming around the city and, yes, destroying things.

Now the game does allow you to vandalize/kill at will, but it comes with a price. The police will look for you and the wanted stars will only go up as you keep at these crimes. Higher wanted stars mean more superior law enforcement will come for you. It’s your choice. You can be a bad boy in the game, but you will be punished. Most of the pro players enjoy this a lot. Oftentimes, we see them trying to get the highest wanted stars just to have some sense of challenge. In my case, in GTA 4 Vice City, it is all about getting to the three stars wanted level so that they send in helicopters and I can shoot them down with a rocket launcher. But I had to run away once they sent the SWAT team to get me. In six stars, they used to send in tanks, making things impossible to handle. These memories are very dear to all of us, right? Look how they have implemented punishment in this mechanism and made the best possible outcome out of it. Years and decades later, we still love the game.

Game Mechanics: Jumping

A game designer’s most difficult task is to protect gamers from themselves. Yes, you read that right. Gamers are their own worst enemy in a game. Sometimes gamers have unexpected expectations from games. One common example is in platformer games where the core of the game is jumping around. Most players want to jump off the edge of the platform. They run until they reach the end of the platform and jump just after they step off the platform. Now, in normal game logic the game character is mostly not even grounded anymore. So logically, it can’t jump. But the players won’t like that. They’d say the game has bad controls. Just this one jump mechanic could affect how a player feels about this game. This brings us to our next topic.

You must be wondering, what could go wrong in implementing such a simple thing? Well, we hate to break it to you but even a simple mechanic such as a jump can go wrong. Actually, most new developers do get it wrong, thinking it is just a simple mechanic. It is not.

The problem we are talking about is the edge jumping problem. There’s a solution to it. And the solution comes from a cartoon. Remember Will E. Coyote from Roadrunner - A cartoon show by Warner Bros? It seemed like the laws of physics didn’t work for him properly. He could hang off the edge of the cliffs until he looked down. This is why we are going to use the term called coyote timer .

This timer is simply a grace period where the game ignores the fact that the player just lost their footing. Usually, this grace period is like 0.1-0.3 seconds. If the player tries to jump during this grace period, the player can still jump even if they have no footing and are supposed to be falling.

Here’s a little pseudo-code so you can get a better idea of how to implement this. The most common way to implement a jump is to check if the player is on the ground and the jump button is pressed. If yes, then do the jump; otherwise, ignore.

Code: Pseudo Code for Jump
if (key_jump_pressed && onground)
{
    //jump
}

But this way the player will not be able to jump off the edge of the platform since they are no longer grounded. So instead of doing this, you do some additional calculations. You need to start a countdown as soon as the player is no longer grounded. Add this variable called jump_grace_timer. The countdown timer is the grace period going down to zero. Whenever the player is grounded, you set the timer back to its maximum.

Code: Pseudo Code for Coyote Timer Ticking Down
if (!onground)
{
    jump_grace_timer -= 0.1f
}
Code: Pseudo Code for Coyote Timer Going Back to Maximum
if (onground)
{
    jump_grace_timer = 0.3f
}

If the player presses the jump button while it’s greater than zero, you allow the player to jump whether the character is grounded or not. Let’s see how the code for the jump looks now.

Code: Pseudo Code for Coyote Jump
if ( key_jump_pressed && (onground || jump_grace_timer > 0) )
{
    //jump
}

There’s more to jumping mechanics than jumping off the cliff. Notice how you can jump only after you have touched the ground? It’s a split second but it could make the player feel laggy input behavior. Players may want to jump as soon as they hit the ground. But this code only works after the players hit the ground. To allow this other behavior, you need to do something called input buffering. If you register the jump button to be pressed while the player is still in mid-air, you need to keep the event buffering. What do we mean by buffering? It’s waiting another grace period before you decide the input was invalid; otherwise you make the character jump once the requirements are fulfilled.

In short, you want the character to be able to jump if the player hits the jump button just before (0.1-0.2 sec) they should actually be able to. Let’s see how to code it. Let’s call it jump-buffer.

First, you check if the player is on the ground or not. If they are, add some time to the jump buffer.

Code: Pseudo Code for Jump Buffer
if ( key_jump_pressed && !onground )
{
    JumpBuffer=0.3f;
}

Second, you have the Update method that runs every frame. For Unity, Update() is a very special method. This function gets called with every frame change in game. This is the method where you want to handle your input code. Also, since this is called after every frame change, you need to consider the delay for each frame since all devices don’t have the same power to render each frame at the same time. Unity does something to help. A property called Time.DeltaTime stores the time difference since the last update call was made. You can use it to scale your calls.

So in your case, you check each frame if the jump buffer has turned to zero. If not, you subtract a small amount from it and check it again on the next frame. From what you coded in the pseudo-code, this code will run four times/frames before the buffer is below zero.

Code: Pseudo Code for Jump Buffer
void Update()
{
    if(JumpBuffer <0)return;
    JumpBuffer -= 0.1f;
}

Finally, in your onground method, you just need to add if the jump buffer is greater than zero when the character is grounded to do the jump.

Code: Pseudo Code for Jump Buffer
if (onground || JumpBuffer>0)
{
    //jump
}

This will make the jump button feel a lot smoother. Players can even hold the button to get a bouncy feel.

This isn’t the end of your jumping saga. There’s more. Players sometimes expect the character to jump higher if they press the button longer/harder. Pressing the button harder shouldn’t really do anything extra but you can comply with the press-for-longer-and-get-a-higher-jump desire.

So how do you do that? Let’s check out the C# code for Unity. You have two variables to manage. One is the charger that stores how long the button is pressed and a discharge boolean that is true as soon as the button is released:
private float charger = 0f;
private bool discharge = true;
public Rigidbody rb;
// Update will receive the input data
void Update () {
        // If pressing Space, charge the variable charger using the Time it's being pressed.
        if (Input.GetKey(KeyCode.Space))
        {
            charger += Time.deltaTime;
        }
        // On release, set the boolean 'discharge' to true.
        if (Input.GetKeyUp(KeyCode.Space))
        {
            discharge = true;
        }
}

Reference: https://answers.unity.com/questions/1459064/long-press-for-charged-jump.html

Now you are going to make the character jump or fall down depending on those two variables.

While the player holds down the button, you want the character to get increasing jump force. So you continuously increase its velocity to its rigid body component. (Note: This must be assigned from the inspector or from the start method.) Continuously increasing its velocity ensures that the character jumps higher as the player holds down the button.

As soon as the player releases the jump button, you want to stop adding force to it.

For this, you can use FixedUpdate instead of the Update method. Why? FixedUpdate is also a special method given to us by Unity. It is very similar to the Update method but instead of calling it every frame, it is called on fixed intervals in real time. So if you wish to update something on a fixed interval, this is the method you want to use. Also, FixedUpdate is basically called by the Physics Engine. So any physics-related code goes here since all the physics updates are done before this is called. The code you are going to do next needs access to some of the physics-related features, so you use FixedUpdate.
// Using fixed update since we are dealing with Unity's Physics
private void FixedUpdate()
{
    // On (discharge == true)
    if (discharge)
    {
        // Set jump force and give new velocity
        jumpForce = 10 * charger;
        rb.velocity = new Vector2(rb.velocity.x, jumpForce);
        // Reset discharge and charger values
        discharge = false;
        charger = 0f;
    }
}

Reference: https://answers.unity.com/questions/1459064/long-press-for-charged-jump.html

Now, this code has a little bit of a problem. It will keep adding velocity as long as the player holds down the button, which is bad. You don’t want to increase the velocity indefinitely. There should be maximum velocity that can be reached. So you need to add some sort of clamping code. Here’s how you can do it in Unity:
float jumpForce = Mathf.Clamp(10 * charger, minforce, maxForce);

Mathf.Clamp is a Unity library. It clamps a value between its min and max value. As a result, you will never go below or above certain thresholds.

How does Clamp work?

It clamps the given value between the given minimum float and maximum float values and returns the given value if it is within the min and max range:
public static float Clamp(float  value, float min,,float max);

This concludes your saga of how to not mess up the jump mechanics. Combining these solutions in one code is a good exercise for you. We strongly encourage you to code in a small character controller with these jump features in mind.

Game Mechanics: Health

You must be wondering how anyone can mess up a health mechanic. It’s because most developers don’t mess up this mechanic. As a result, the game loses some of its thrills. How come? Glad you asked.

Imagine you are playing this game for hours. You are almost at the checkpoint. And you are low on health. And suddenly some small fry enemy lands a blow on you and you are dead. Wasn’t very fun, was it? Or how about this: you almost kill a callous boss, but just before you place your final blow you get hit and die.

It’s not really fun to die, is it? You as a developer aren’t here to make the player’s life miserable; you are here to give them a good experience. And for that sometimes you need to cheat.

Let’s tell the same story again but with different outcomes. You are low on health. You have almost reached the checkpoint. The wild enemy appears. You beat him and reach the checkpoint with low health. How do you feel? A sense of achievement, right? What about the boss fight? How do you feel when you defeat a boss with almost no health? Yeah, you don’t have to say it out loud. It’s thrilling. And it’s fun.

But most players aren’t that good. They die a lot. And the chance of a player being able to clear the boss with low health is pretty low, unless you step in. There are a lot of ways you can assist the player in overcoming this. But if the player knows you are assisting them or at least if it’s too clear, they may not feel a sense of achievement at all. For this reason, you need to hide some cheating in-game code that’s there to assist the player.

Let’s take a look at normal damage code in a game.

Basic Take Damage Script
float maxHP;
float currentHP;
void ApplyDamage(float damageToApply)
{
  currentHP-=damageToApply;
  if(currentHP<=0){
   //Player dying code
  }
}

This is the simplest form of managing how to kill the player. The function takes a damage value and negates it with the current HP and checks if the HP has gone below zero. If yes, then it kills the player. Now the question is, should you just kill the player that easily? How do you make the player be on edge?

The concept is pretty simple. You don’t always apply the full damage. You cheat here. One way is to scale the damage depending on how much health the player has. You can just multiply the damage with the remaining health percentage, something like the following code.

Improved Take Damage Code
float maxHP;
float currentHP;
void ApplyDamage(float damageToApply)
{
  currentHP-= (damageToApply * (currentHP/maxHP));
  if(currentHP<=0){
   //Player dying code
  }
}

This way the lower the health points of the character, the lower the damage. But hold it there. This is actually a bad idea because at 1% health, the damage will be almost close to zero after scaling it down that low.

You are certainly on the right track but something is wrong. Remember that clamping method from the last topic? Yeah, you need to add it here. You need to ensure that there’s minimum damage even after doing the scaling. You can change that value depending on your game. Let’s see how the code looks now.

Even Further Improved Take Damage Code
float maxHP;
float currentHP;
float minDamage=10;
void ApplyDamage(float damageToApply)
{
  damageToApply = Mathf.Clamp(damageToApply * (currentHP/maxHP), minDamage,damageToApply);
  currentHP-= damageToApply;
  if(currentHP<=0){
   //Player dying code
  }
}

In the clamp method, you first pass the damage to be dealt with after scaling it with the remaining HP. Secondly, you pass a minimum damage value. As the health goes low, the damage will start to go very low. You want to avoid this as well. And finally, the damage to apply is sent as the max damage since the highest damage that should be done is the exact same value without scaling.

Now, this code will ensure the better survivability of the character. Also, this doesn’t expose that you as the game developer are assisting the player. It could hurt their pride if they ever knew.

No, this is not the end. You can further improve this. How about offering one last chance? How about you make sure the player always gets one last chance before dying? You just need to make sure if a hit is supposed to kill a player, it should instead lower the HP to the minimum value without killing them. For one time. Let’s see how the code looks for this:
float maxHP;
float currentHP;
float minDamage=10;
bool dyingBreath;
void ApplyDamage(float damageToApply)
{
  damageToApply = Mathf.Clamp(damageToApply * (currentHP/maxHP),minDamage,
 damageToApply);
  if(currentHP-damageToApply<=0 && !dyingBreath){
     currentHP=1;
     dyingBreath=true;
    }else{
     currentHP-= damageToApply;
     dyingBreath=false;
   }
  if(currentHP<=0 && ! dyingBreath){
   //Player dying code
  }
}

This puts an additional check before applying damage. If the applied damage would kill the player, it just makes the player’s HP as 1 instead of applying the damage it otherwise would. And the flag dyingBreath is a check to trigger this feature. Once dyingBreath is true, it will always deal with the damage next time.

You can even go further by allowing the player to take more than one hit. But it’s a bad idea to allow more than three hits because the goal is to assist the player without ever letting them find out. There are other examples of assisting players when they are low on health.

In Spider-Man PS4, you can acquire an ability that slows time when your health bar is depleted up to a certain level. It’s a predetermined features to make sure you have a balanced health system.

Borderlands has a mechanic called second wind: whenever you die, you get to shoot enemies from a crawling state. And if you can kill any enemy from that state, you get a health refund. This resets every time you successfully come back from death.

Some games take it another step further. They provide this last chance as some kind of power that you can acquire. You can either acquire it as a reward by doing some in-game objective/mission or you can purchase it with some coins/XP you acquired in the game. Sometimes this power comes with a particular tool. If you avail that tool, you get this last chance ability as an associated attribute. God of War has different kinds of resurrection stones. Each replenishes health by its own capacity as soon as you die, so you can resume the battle from there without having to start over.

Game Mechanics: Movement

At this point, you should understand we aren’t kidding. There are a lot of ways to mess with every simple mechanic possible. But just like jump, this is mostly the fault of gamers. You are going to add features to movements that aren’t supposed to be there, but they need to be there to help players to get a better experience.

Almost all 2D platformer-like games have visual obstacles in games that weren’t intended to be a part of the gameplay. But often developers make the mistake of adding physics there. Even if it’s almost ignorable, this will ruin the flow of the player. Let’s take an example from Dead Cells. They did something very interesting to help the players.
../images/499184_1_En_11_Chapter/499184_1_En_11_Fig2_HTML.jpg
Figure 11-2

Small environmental collision

See that small bump on the edge in Figure 11-2? This part was never meant to force the player to jump. But if you don’t have any kind of helping mechanics in place, this is what will happen: see Figure 11-3.
../images/499184_1_En_11_Chapter/499184_1_En_11_Fig3_HTML.jpg
Figure 11-3

Player colliding with the environment

Yes, the player is stuck and they have to jump to actually move forward, as you can see in Figure 11-3. Instead, what you should do is push the player forward if they are colliding with something small in height. That’s actually how it works in Dead Cells. How did the devs it? We do not know but we can certainly try. Lets try that now.

If you are planning to do this in Unity, it can get a little complicated as we don’t usually handle physics collisions like this. But you can certainly cheat to make this happen. The problem is you do not want the player to get stuck here. Let’s see the fundamental reason behind this problem. By default we will use box colliders because they make more sense. And it would sort of look like Figure 11-4.
../images/499184_1_En_11_Chapter/499184_1_En_11_Fig4_HTML.jpg
Figure 11-4

Generic collider design

Now the character itself has a collider. And by default, it does what it’s supposed to do: collides with each another. And without any other helping mechanism in place, the character collides with the small edge shown right now.

Here’s a quick fix for the problem. What if you didn’t make such a pointy edge? What if it was a slope? No, I don’t mean changing the game design at all. Players can’t see the colliders anyway so what if you did it as shown in Figure 11-5?
../images/499184_1_En_11_Chapter/499184_1_En_11_Fig5_HTML.jpg
Figure 11-5

Better environmental collider design

No player will notice this, but it bypasses your problem and gives the player a better experience here. The goal of this chapter was to help players without letting them know that you are lending them a hand.

But this isn’t a very good way to solve this problem. The reason you had this problem in the first place was you were using default colliders. And in most cases for the level building, you would. It’d be bad to leave these crucial helping mechanics on the level designer’s hand. Because we are human and we make mistakes. Although this is a quick fix to the problem, this is not a great fix. What you should do is handle this with code. And the code looks somewhat like this:
//NOTE: THIS IS JUST A PSEUDOCODE
void OnCollision(collider coll){
     if(coll.rect.y<=someThreshold){
         //The player should be able to move forward
      }
}
In Unity, just like Update methods, there’s another special method called OnCollision, which gets called whenever a game object collides with another game object. Other game engines most likely have something very similar. In Unity, the OnCollision method brings in some data where you can get the size of the collision:
coll.rect.y

This represents the rectangular height of the collider. Since your goal is to let the player move forward if the collision height is a very small threshold, you are going to check if it’s below the threshold or not. If it is, you can write code that allows the player to move forward from there.

This pseudocode is here just to give you an idea about how to implement the feature. For each game movement, the logic will be different. So we are leaving that space empty for you to fill up as you develop your own awesome game.

The Cavalry Will Arrive

By now it’s pretty clear that almost all of the fundamental mechanics in a game are vulnerable. Rewards and punishments both are necessary, but you must not overdo either. If you try to overdo rewards, the gamers will lose interest since there’s a very little challenge. That’s very basic. Also, you shouldn’t just piss someone off in a way that they get rid of your game and never come back. You should always maintain the flow. At times, gamers may not be as good as they think. Most of the time developers help them play the game. And that’s fine. As a game developer, that’s your job. The goal of a game is to deliver a fun experience. If a little help from the developers makes the experience better, why not do it?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.119.199