Scripting Good Game Feel

So in my re imagining of Super Mario Bros using El Lissitzky’s art style that I have decided to call Super Mario Bros. World El-Lissitzky, super creative right? Most of my ideas have been centered around the actual feel of the game, so I have been doing a lot of code that achieves just that. Although the duration of this project only lasted a single week, I think I’ve spent a good chunk of that coding rather than planning, designing or making the assets which just so happen to be the core of the project, or so I think.

So lets get this out of the way, I am a game designer and I love programming (wow!). This project doesn’t have the most complicated code I’ve ever made, but it definitely has the most coherent. Something else I should point out before diving in is that most of my code is based off of the usage of layers. By using layers I can choose what objects collide with one another and have easier access to deciding how different layered object behave with one another.

grounded

Super Mario Bro’s World El-Lissitzky’s grounded and score multiplier functionality

Something that is used in many video games is a grounded feature, what this does is checks if the player is on the ground. This can help with things such as a jump feature, a jump will typically add force or move the player upwards, if the player holds the jump button should they continue to gain force or be moved upwards? If that’s your intention sure but in this case its a no. To make sure the player can only jump when on the ground then you may need a grounded check. In addition to that I will explain how I implemented my score multiplier from Super Mario Bros. For those of you who don’t know, when you jump on a goombas head and then jump on another goombas head in succession without hitting the ground your score multiplier is doubled for each consecutive kill. For example if I jump on a goomba I will get 100 points, if I jump on another goomba without touching the ground I will get 200 points, if I then jump on another goomba without touching the ground I will get 400 points.

So to start off I needed an empty object on the player object, this object is placed slightly below the player object so that it is overlapping the ground collider when the player is on the ground. The first line of code in this snippet sets the is grounded bool to true if it returns an overlap point. In this scenario the overlap point takes 2 parameters which is the game object that was just placed on the player object and the layers that is reacts to. These will both need to be variables that are set either through code or the Unity inspector. I used the inspector and simply dragged the game object into the script component and selected the ground layer from the drop box also in the script component. So now whenever that empty object on the player is overlapping with the ground layer, is grounded will be set to true.

stompmult

Super Mario Bros. World El-Lissitzky’s enemy head collision functionality

For the score multiplier I took advantage of the grounded functionality. The above code is from the player controller script and this snippet covers the on trigger enter 2D, specifically for layer 17 which is the enemies head. Jumping on the enemies head is the basic way to kill an enemy. When the player collides with layer 17 it will call the enemy death function from the enemy controller script which takes a parameter that is the stomp multiplier. After that it multiplies the stomp multiplier by 2, because the multiplier starts at 1, the next enemy that the player jumps on will have a score multiplier of 2 and then after that is 4 and so on.

It is vital that the multiplying of the multiplier is after calling the enemy death script because the stomp multiplier is applied within that function and we want the score to be increased for the next kill not the current one. That’s the general pattern of it, but what stops the player from increasing the score indefinitely? Well if we refer back to the previous image with the grounded check, there is a nested if statement that sets the stomp multiplier to 1 if it is greater than 1. What this means is that whenever the player is on the ground the multiplier is 1, if the enemy jumps on an enemy the multiplier is multiplied by 2.

Something else to note here is that at the end of this if statement the players velocity is zeroed and then some upwards force is applied them. This is so that the player can bounce off of an enemy and onto another to make use of the score multiplier feature.

platform

Super Mario Bros. World El-Lissitzky’s platform block collision functionality

Similar to the previous feature of applying an upwards force to the player object when jumping on an enemy, when the player hits the bottom of a platform block some down force will be applied to them. This is not something that I had initially noticed in Super Mario Bros but after some time testing my early build of this project I noticed that hitting the platform blocks felt really bad because you just float down. Another issue of not having this feature is that, because the platform animates upwards when hitting them, it’s possible to collide with the sides of adjacent platform blocks which completely negates horizontal movement. To fix all these issues simply zeroing the players velocity and then applying some down force which is equal to negative stomp force (kind of cheaty but still gives good results).

jump

Super Mario Bros. World El Lissitzky’s jump function

Something that I was unsure about at the start of the project was how to imitate the ‘hold to jump higher’ feature that Super Mario Bros has. Above you can see a snippet of the code I did for this function, this function is called whenever the player presses the space key. I’ll start with the second if statement, if the player is on the ground when the function is called, the jump sound will play, the was grounded bool will be set to true, the players velocity will be zeroed and then an upwards force will be applied. The reason behind zeroing the players velocity is because there are multiple objects in the level that apply force to the player. If they hit multiple of these objects in succession the player object will gain a whole lot of velocity which they shouldn’t. This workaround is a bit cheaty because it will stop any horizontal momentum too which shouldn’t happen, but it’s a quick way to get a nicer feeling jump.

The third if statement checks if the player was grounded, remember this was set to true when the player initially jumped. There’s some important variables to this code that is not explained in this screen shot, but basically the jump timer is set to 0.5 by default and the was grounded bool is set to false as soon as the player lets go of the space bar. While the player is holding space the jump timer variable will decrease by the value of delta time which is relative to real time and an upwards force will be applied to the player which is equal to the air force variable multiplies by the jump timer. This means that the longer they are holding jump the less the upwards force will be, this makes for a nice jump curve.

Finally the first if statement simply sets the was grounded to false if it was true and the jump timer is less than or equal to 0. What this means is that after the player has initiated a jump and is still holding jump in the air to increase their jump height, once the jump timer is over (hits 0) the was grounded variable is set to false and the third if statement will no longer be in effect and thus no force will be applied to the player object. This is to avoid the player from being able to hold jump down indefinitely and constantly apply force. If that were the case they would be applying down force anyways since the force of the jump is relative to the jump timer which would be in the negatives after the 0.5 second mark.

2016-11-10_19-45-20.gif

Gif of some features in Super Mario Bros World El-Lissitzky

That’s quite a bit of information for some simple scripts but it makes for a much more polished feeling game. Having the player be able to hold the space bar to increase their jump height is a fundamental thing for replicating Super Mario Bros that I simply had to have in this project. The method of implementing it really makes for a good feeling jump curve and is something I’m proud of. The feature of applying down force to the player when hitting the under side of a block is a nice touch of player feedback and makes the game more fast paced. You can speed through the level and bounce off the under side of a platform to quickly get a goomba stomp in without the need for predictions or difficult timing. While the upwards force after a goomba stomp is quite necessary to use the stomp multiplier to any effect it definitely makes is easier and adds that extra player movement that makes the game feel very bouncy.

Studio 1 Project 1 – What I’ve Learnt

Super Mario Bros (World El-Lissitzky):

In our first Studio 1 week we were tasked with making a Super Mario Bros world 1-1 clone with a different art style inspired by a famous artist. The game needed to have different mechanics with the artists art style in mind. We had 1 week to make the whole game which in retrospect is not that long, but it turns out Super Mario Bros has a lot more code and mechanics behind the scenes that I didn’t know about at the time.

The final build can be downloaded from my itch page here.

Art Design:

So first off the art style, the artist I was given was El Lissitzky which is known for very abstract and architectural artwork. Right off the bat I can see a connection between Super Mario Bros art style and Lissitzky’s art style. They both use primarily 2D shapes and being able to use architectural designs and concepts to make the space of my Mario clone would make it easier for me.

Out of Lissitzky’s art work I opted to use his Proun series which were his most famous work as seen in the above images. I chose this because I thought that it would work best with the blocks, pipe and stairs seen throughout World 1-1.

elmario2

Screenshot of Super Mario Bros (World El-Lissitzky)

The above image shows the final build of my Super Mario Bros World 1-1 clone with Lissitzky’s art style in place. For the floor I went with the flat 3D rectangle because the floor is static and did not need to move unlike the platform blocks. For the platform blocks I opted to use normal squares with a textured surface and similar to that seen in Lissitzky’s proun work. These blocks had a darker top to them so that the ground is more visible to the player. The reason I did not use flat 3D images is because these blocks animate up and down, when separated the 3D blocks would overlap with one another and make the animation look unappealing. The stair blocks uses a more 3D look giving it an illusion of being a pile of blocks with the textured surfaces. The pipes were a tricky one but I decided to go out of the box with them, I used a 3D looking sprite but made it distorted by having a more narrow bottom than the top. It also looks like it is being viewed from an angle, making the top visible and the bottom overlap, making it look as if the dark part of the floor is the ground and the white part is the wall of the floor. The question blocks I replaced with the 3D cube seen in Lissitzky’s Proun 1 and it rotates in its animation. I think that the question blocks compliment the art style I was going for while still looking like a question block to anyone who knows the Mario games.

elmario

Screenshot of Super Mario Bros (World El-Lissitzky)

With the player sprite I went with a more complex design using smaller objects that animate in a strange way. It’s much like Lissitzky’s art in the sense that not much of it makes sense but it still looks appealing. For the enemy sprites I tried to keep the similar look of the Goombas but simplified it, added some shadow on the left side and replaced the eyes with almost samurai looking eyebrows, I was quite pleased with the outcome. The mushroom object came a bit after and I put more work into it so it has a more 3D look to it and some 2D planes extruding from it. The coins are actually an imitation of one of Lissitzky’s proun works which has an almost S looking symbol in the middle that I decided to use.

Mechanics:

With the mechanics I tried to keep them as close to the original Super Mario Bros as I could. I wanted to game to feel responsive and easy to control. Although there was only 1 week to work on it, I had quite a few mechanics in mind that I wanted to add. Unfortunately I had to drop some due to not enough time, including the fireflower, destroying blocks, UI for score gain and secrets such as the secret level, the 1-UP block and the secret coins.

The mechanics I added include holding space to jump higher, camera follows the player forward but not backwards, headbutting question blocks and platform blocks to move them, enemies above a headbutted block die, mushrooms above a headbutted block change direction, headbutting a question block will either produce a coin or a mushroom, collecting a mushroom makes mario invulnerable for 1 hit and makes him two times taller. The enemies movement behavior was the same as the mushrooms, they simply move in a set direction and when they collide with a wall they change direction, if they fall off the map they are destroyed.

Scripting:

The scripting was my favourite part of this project, and that probably sounds a bit weird coming from a designer. I haven’t actually worked with Unity 2D or made any sort of platformer so this project was quite educational for me. To get started with the unity project I watched a tutorial on YouTube about 2D platformers. Thankfully it was about the original Mario Bros. so it shared some characteristics with my project.

I figured out how to use the physics options to allow certain object layers to collide with each and also allow certain layers to ignore each other. This is a handy feature since it cuts down on performance loss by having less collision checks. I also setup my input settings to include only what I needed, I used axes rather than just button inputs to allow for joystick mapping in the future.

After getting the project settings out of the way I started to plan out how I would go about the floor and platforms. For the sake of a prototype I made a simple player script that I put on an empty game object with a collider as well as some flooring with colliders on them. I wanted to use separate 16×16 colliders for each block so that I could do headbutting and block destruction easier, but I found that the player collider would always get stuck on ‘non-existing’ gaps between each block. I don’t know how to actually fix this so I used a work around which was just using a single collider for each stretch of flooring or platform. Another problem that I found was that the player object would stick to the side of the platforms if they were trying to walk into it. To fix this I made separate colliders on the sides of each platform and floor with a physics material that had 0 friction. This allows the player to slide down walls even when trying to move.