Monster Mash

November 14th 2022

Game Jam 2 - Fighting Game and Learning Godot


Set-up

For this game jam, I was put in a group with multiple members. We would have about a month to create a fighting game, like Street Fighter. Once we were tasked with this, the group producer made a Discord server and invited us all, and we began discussing a plan. The group contained 2 Programmers, me and Finlay, and then 3 other artists. 

The idea we came up with was a unique take on fighting games, where instead of hitting each other, you would hit a ball that would bounce off walls and hit your opponent to give you points. It would also be Halloween themed as it was around October and having a Halloween theme could make us stand out, so we named it monster mash. The idea was heavily inspired by the game Lethal League Blaze.

Before development, we decided we would create the game using Godot, rather than using traditional engines like Unity. This was because the producer had the most experience with Godot, and had used it many times in the past for their own games. 

Learning Godot

As I had never used Godot before, the first thing I had to do before beginning development was learn the very basics of the engine and how to use it. Luckily, the GDQuest website has an incredibly helpful intro about learning Godot, covering all the basics including:

It also featured long walkthroughs where I created a very basic 2D and 3D game.

After I got through the course, I felt fairly confident to begin working on the project, and try to provide as much help as I could.

Development

Development had started from other members of the team before I finished learning Godot. Finlay had created multiple models and animations for a character named Skully, as well as come up with a ball model and a testing map. Other members were creating other character designs and maps. As a result of the Halloween theme, we had chosen for the map, the artistic choices made would reflect that. For example, Skully is a skeleton, the ball was pumpkin-shaped, one of the planned maps was a graveyard with pumpkins, the fonts planned were scary fonts and more.

The first task I was given was to implement the mechanics related to the ball, this includes things like being hit by the player, hitting players, bouncing off walls, picking up momentum and more. While originally I didn't think it would be too hard, it ended up being significantly harder than expected. This was largely due to my lack of experience, so I found it hard to be able to properly come up with solutions for tasks. 

The main part was coming up with a reliable way to detect the player hitting the ball. The system I came up with was creating a collision shape in front of the player and then also checking if they input the hit key. If so, I'd do some checks to see the direction they hit in, then apply velocity accordingly. There ended up being a few issues with this, however, mainly inconsistency when detecting the hit. When the ball was travelling quickly, it became very hard to hit it, which was frustrating. There was also a bug where after a number of hits, the ball would be stuck to the wall, and I wasn't sure how to fix this.

One part I did manage to get working though was the ball bouncing. Since the area would essentially be a 2D box, the ball would need to be able to bounce off of each surface consistently in a way that the player would be able to predict. I had a good idea for how to do this, first I created 4 collision areas around the ball object, one on each side (top, bottom, left, right). Then, I checked if any of the boxes collided with any of the walls. If so, I check which one and depending on which i invert the velocity in that direction. This gives off the effect of the ball bouncing in the opposite direction.

I later found out Godot has a built in bounce function, so a lot of what I did was useless. But at least it worked!

Because I was struggling with the ball mechanics a lot, I let Finlay manage it instead, as he would be much more reliable at doing so. I decided to take on a much simpler task which I could easily follow, so I began creating the main UI used for the game.

First things first I chose a font, using dafont.com which is a great website with a huge selection of different community-made and professional fonts. I looked through the horror fonts and selected a few which I thought would look best for the game. I posted on Discord and decided on Kaira. It had a good horror theme, while also sticking well to the 'monster' in the game's name, with monster horns and spikes all over the letters.

I found a great, short tutorial for how to make a main menu in Godot, perfect for what I was doing. The process was surprisingly simple, as Godot has a great UI system that I found incredibly easy to learn. For the main menu, essentially all I had to do was create a VBox container, which can store different UI elements in a vertical list, and then add 3 different buttons to that container that would show up in vertical order (Start, Options and Quit). Clicking each button runs a unique signal, which I can use to run specific lines of code depending on the button, making them very easy to program.

The quit button simply closes the game window, which is done in one line of code get_tree().quit()

The start button simply loads a new scene, that scene being the main game scene where the players are able to control the characters. I wanted to add a little more visual flare to the start button, so I found a way to add a fade-to-black transition so that it would smoothly enter the game. This tutorial was perfect for this, and I was able to add it easily.

The options button was much more complex, this was because I wanted the options screen to have a key bind screen, where players can remap actions in order to tailor the game to better suit them. This makes the game much more accessible, as it provides the game to be played in any way.

I had no idea how to implement this sort of system, so I searched for a good YouTube tutorial. This one wasn't the best, but I used it nonetheless.

The method used relies on a configuration .ini file to be packaged with the game .exe, this file contains each of the action names, as well as the appropriate scan code associated with the key. When the game is loaded, it imports this file and reads it, storing it all in a list, so it can be read again later much faster without having to reopen the file.

When the options menu gets opened, that list is then iterated through to find all the keys. For every new keybind it finds, it will create a new line of UI and add it to the screen. This UI contains a label and a button, the label text is given the keybind name and the button is given the keybind key name.

The final result is a full page, which is dynamically created, containing all keybinds and their designated keys. 

Next was the system of changing the keybind, and then storing that back into the configuration file so that they are saved the next time the player wants to play. To do this, each of the words on the right is actually a button, that when clicked, replaces the text with 'Press Key', and waits for an input. Once it receives one, it takes the key that was inputted and replaces that key with that.

There is also a system included which prevents the issue of having the same key used for multiple actions. When a new key is chosen, it will quickly check every other key and make sure that it doesn't match the same as the new key. If it does, then it resets the old one and makes it 'Unassigned' requiring a new input.

This options system ended up functioning alright, however it came with quite a few drawbacks. The main one was that it didn't work with mouse inputs, so you could not assign clicking or mouse buttons as keybinds. I tried researching ways into fixing this, however, I decided it wasn't worth the time to alter the system, so it remained like this in the end.

A few other smaller issues include: 

Despite the flaws of the system, I still kept it as it was and moved on, as I had managed time poorly and was running out of it.

The final UI task I undertook was creating a pause system so that while a game is in progress, players are able to press escape to freeze the game, and either quit or change their options. Yet again, I followed a brief tutorial for most of this system, it ended up being incredibly simple though.

It turns out Godot has a built-in system for this, and you are able to pause and unpause each node currently in the scene. Every node has its own 'Pause Mode', and this can be changed to Process (Unpaused), Stop (Paused) or Inherit (Pause mode is determined by the parent node). By having all nodes in the game be on the Inherit pause mode by default, all you have to change is the main nodes pause mode to stop, and then all other nodes in the scene will then also pause. This means the whole game can be frozen with one line of code. 

If the player presses the Esc key, I would pause all the nodes in the tree, and make the pause menu node no longer invisible. In order for this pause screen to not also be paused by the code, I had its pause mode set to Process, so it wouldn't inherit the pause. On this pause menu, there were 3 buttons.

Options would simply open the same options page used in the main lobby, but on this screen instead.

Resume would just unpause the game, and return the pause screen to invisible.

Quit would close the game scene and reopen the main menu scene, while playing the fade-to-black transition effect.

One final thing the pause menu has is a large translucent ColorRect which tints the screen slightly brighter. This is to make it more obvious the pause menu is open, and that the game behind is frozen.

With the pause finished, that was all of my part done, so I handed it back to the rest of the team for final touches.

The final product had a Cafe map replacing as the main, and also had the ball mechanics polished, as well as the second player to play against. One issue with the final version however was the pause menu having certain aspects bugged, for example opening the options menu would freeze the game, and the tinted background was not visible. I was unable to fix these before publishing, so instead I just removed the options button from the menu

Conclusion

Looking back at the project, there is certainly a lot I could have done better.

Firstly, my additions to the project were very minimal. In the final product, all I provided was the UI, which was disappointing. This happened for a variety of reasons, the main one being my lack of experience in using Godot and GDscript which made me unable to do simple tasks without needing to do lots of research first, and still messing it up. I should have stuck with easier and smaller tasks, such as the UI and pause system, rather than immediately jumping into larger and more ambitious tasks like the ball system. This way I would have been able to contribute in small consistent doses and not have to worry about doing things too difficult, and also means I could work my way up and accumulate Godot knowledge over time, and then gradually become more confident and be able to take on the more ambitious tasks.

Another reason was my poor time management. I had put off learning Godot and contributing to the project as I felt very unmotivated to do so as I would have to dedicate multiple hours to sitting through tutorials and following through, which I had already done just a few weeks prior when learning Unity, so it felt very tedious. Ideally, though, I would have watched the tutorials much sooner and begun trying to help sooner, that way I would have had more time to contribute more to the project.

Luckily, my lack of contributions didn't majorly harm the game in any way, as the other programmer Finlay was able to carry my weight for the game

If I were to improve parts of the project, it would likely be adding more visuals to the main menu, as currently, it is just a solid grey background which looks incredibly dull. It would also be cooler if there was more visual variety within the game, such as multiple maps to play on, and multiple characters to play as. Two team members were not able to contribute anything to the final product, so if they were able to, then maybe these issues could have been improved upon.

Overall though I am happy with the final product, and it was a good opportunity to learn this new engine, and work with multiple people properly.


Media