In order to create my game, I started learning how to use an engine called Godot. Godot is very easy to use, especially for a coding and engine novice like me, and it uses it’s own script called GDScript. Godot uses a system of Nodes in order to build the game, each Node is presented similarly to a Layer on Adobe Illustrator or Photoshop. Because of this, Godot provides and easy to navigate UI, perfect for someone new to building games.
To get acquainted with it I’ve been following a series of tutorials by a man known as Heartbeast, who has also been known for his tutorials on Gamemaker. My journal on his tutorials can be found here:
As of now I have had three attempts at creating perfect movement for my game. The first try I used a Kinematicbody like I used in the Heartbeast tutorials, I managed to get smooth movement and movement in 4 different directions. The first problem was when ever the player would try and move diagonally, the body would double it’s speed. While I considered keeping this in as a sort of boost mechanic, I decided that it just wouldn’t work and tried to fix it. Online chat rooms suggested using a normalise function but it wouldn’t work when I tried it and just took away all movement. My second issue was instead of rotating the Sprite it would remain stationary as it moved, this could easily be rectified by creating multiple Sprites of the ship moving up, down, left, right and diagonally but I decided to start fresh with a different body.
My second attempt used a Rigidbody instead of a Kinematicbody. The Rigidbody has physics embedded in it already and doesn’t need you to code features like gravity into it, just simply turn it on. This allowed me to easily incorporate an area with a gravitational pull, kind of like a black hole, which gave me some more ideas for level design. I still needed to tether the two ships together with a sort of elastic effect which proved a huge challenge. I tried to use a Springjoint2D which essentially bolts the two objects together with spring. While this sounds ideal and would be perfect if it worked, it did not work. The joint couldn’t take the strain of both of the ships being controlled and sort of devolves into an elastic spasm with very limited movement for both players. After a while of failed experiments with it I moved on to a brand new build which I named Elateth V2.
My third attempt went back to the Kinematicbody2D with a similar but smoothed out movement script to the first build. The movement system simply uses the left and right arrows to rotate the ship and the up arrow to thrust forward in the direction you are facing. With this body my tutor and I were able to work out how to create a tether between the two ships by using lots of math to calculate max and min distances, then put the ships into reverse when they reach the max distance. This creates an elastic like effect where the ships will reach max_dist then reverse themselves until they reach min_dist.
We were also able to create a visual representation of the piece of elastic between the two ships by using the draw function. The draw function on Godot will draw a shape or line purely from code. Using the complicated bit off code below we managed to specify how we wanted the line to draw, in a sort of wave length shape and with a colour of our choosing.
draw_line(Vector2(dist_to*i/20, b*sin(c*i)), Vector2(dist_to*(i+1)/20, b*sin(c*(i+1))), ColorN(“slateblue”), 5)
After I got the movement of the players down I focused on building the levels within the game. I’d previously created level designs for game which have been tweaked over time to match the capabilities of the Godot engine and my own skill. For example in my second build I was playing with the effects of gravity on the player and decided to implement a black hole in the middle of the arena. Unfortunately the kinematic body didn’t have the physics needed built into it and would have needed bunch of code way beyond my ability to implement, so instead I just designed a new arena with different obstacles instead.
You can find the Asset and Background designs for all of my levels here:
The first level is called Retrograde, this level is based in an asteroid belt around a planet so I had to include lots of Asteroids to collide with and a few moving ones. The static asteroids were easy to put in as they just consisted of a Staticbody2D, a Sprite and a Collisionshape2D, it’s a simple object designed to sit still and be solid. I also added an Area2D node and a Collisionshape2D as a child of that, the Area2D node is for 2D detection and physics influence and the Collisionshape2D provides and shape for the Area2D to work in. I then added a signal to the Area2D so that when a body enters the Collisionshape2D it will send a signal (on_body_entered) to another node. Receiving this signal lets the nodes know when contact has occurred so it can take the damage off of the ships health.
For the comets shooting through the screen and orbiting asteroids I had to figure out how to use the Path2D node. The Path2D node along with the PathFollow2D node and the AnimationPlayer node allows an object to follow a path around the screen. It essentially allows you to draw a line or loop on the level that a node will travel along according to the timings set in the AnimationPlayer.
Finally for a spinning wreckage of a space ship I followed the same directions for the static asteroids but I added an extremely simple piece of code that allowed the ship to spin on the spot at a constant rate. With a Var of motion = 0.01 below.
The Boneyard was a little more simple to create than the first level as I’d gotten the Path2D node down. This level is set in the aftermath of a large space battle so I’ve designed it to have lots of wreckage’s of space ships and malfunctioning ships in it.
I included two spinning wrecks of ships near the centre of the map, with Area2Ds on them to detect collision. I included a few of the asteroid assets from the previous level as well as an asteroid that I’ve changed to have shipwrecks crashed on it’s surface. These all provide a simple collision and loss of 1 health point. 2 of the crashed ships are malfunctioning and firing a laser like discharge from their thrusters, this provides another hazard that shoots across the scene and might even catch out an unwary player. The lasers use the Path2D node and all that follows to fire every 2 seconds and whizz across the screen. In one of the corners I used the Path2D node to create 2 Pistons that pump back and forth, providing a loss of one health point if touched, this will provide a nice little obstacle to catch out the other player.
One on side of the screen is a huge space ship with it’s thrusters pointing towards the centre of the screen, if a ship were to touch these thrusters they would lose a health point. It was originally my plan to place a hidden button somewhere on the level that would fire 3 laser blasts out of the thrusters that would take up most of the screen and instantly obliterate the first player it touched, but this has proved difficult within my time limit. The large ship is simply a collection of Collisionshapes on a Staticbody and is not intended to move at all.
Forge was a different level to the rest as it was set within the hull of a large ship, so no asteroids of wrecks of ships. I did however love the idea of cogs within the level, so I have a small number of large cogs rotating and causing 1 point of damage upon impact. The pistons are back with the Path2D node and pumping at different speeds in the corner, I also have two that pump against a conveyor belt on the top left that will crush any ship caught under them.
I had less time to put this level together so it has less variance but still provides a challenging experience. I created a small box shaped incinerator that will provide an instant death if entered, it’s completely static as I haven’t managed to animate it yet but I’m hoping it will be complete for the final shows.
The UI was quite easy to code and I knocked it out in one night. The game starts on a nice Startscreen with calm menu music playing in the background, pressing space will take you to the Chooselevel screen. On this screen you can choose one of three levels either by clicking on the pictures or pressing the keys 1, 2 or 3, this will then take you into the level.
After the death of one of the players a screen will pop up saying either “Player 1 wins” or “Player 2 Wins”, pressing space here will then take you back to the Chooselevel screen.
It’s very simple in the script, the script below says; if the button mapped to “ui_1” is pressed then look up the scenes available and change it to “World1”.
Most of the actions in the script look very similar to that, in most of the menus I have mapped:
- ui_accept to Space
- ui_cancel to ESC
- ui_back to Backspace
- ui_pause to P
You can find the designs for the UI below:
I spent ages trying to work out how to create a health system within my game and it turned out to be not so difficult after all. All it involved was creating a variable for health and a simple bit of code that allows you to take away one health point every time a signal is received that says that ship entered the Collisionshape2D. Along with a “if health is less than or equals zero, change scene”.
var ShipH1 =3
func _on_Rock1_body_entered( body ):
if body.get_name() == (“Ship1”):
ShipH1 -= 1
if ShipH1 <= 0: