Pew Pew: How I suffered making a game during my school holidays
Venkatesh

Venkatesh @vensah

About: Swift, C#, C++, C, Python, HTML, CSS

Joined:
Jan 28, 2025

Pew Pew: How I suffered making a game during my school holidays

Publish Date: Jan 28
0 0

"How hard would it be to make a game?"

Being excessively free and bored during my school holidays, I was looking for something to occupy my time. Unfortunately for me, my first thought was making a 3D space shooter game. Even though I have quite a fair bit of experience with programming and some basic game development, it was not even close to being easy to make my own game. Since I haven’t fully completed the game, I thought I would document my progress.

What Exactly did I Want to Make?

Game Design Document

Usually, when starting to make a game, developers make a game design document to make their ideas clear and have a fixed scope. This helps define the game and prevents feature creep. Game design documents can include many things but the most important ones are the storyline, aesthetics, core game mechanics, and gameplay.

Story

For my game I decided to start with the story as I felt it would give me an idea of what aesthetic and gameplay I would go for. In summary, my game is set in a dystopian galaxy where you, the player, will overthrow your rulers to gain freedom. With the overarching storyline in place, it was easier for me to flesh out the lore more and come up with gameplay mechanics.

Gameplay

The idea is that the player can conquer planets if they are not owned or fight with the ruler of the planet for its ownership. When owning a planet, you can gain large amounts of resources depending on the type of planet. For example, deserted planets are more rich in pure elements while planets with civilisation would be able to provide you with products and processed resources. However, the Galactic Government (your rulers) will try to stop you from rising to power by sending attack ships to destroy you.

Aesthetics

I had originally wanted to make something that looked like Freelancer without pixelation. However, during development, I found No Man’s Sky. This sent me through a No Man’s Sky phase where I tried to mimic my aesthetic and features to look like No Man’s Sky. Luckily, I had come to my senses and realised that I can’t and don’t want to make No Man’s Sky 2. Then I found Atroneer

Now if I hadn’t sit down and settled on an aesthetic with my friend, I can assure you that I would still be in dilemma about the aesthetics alone. I finally decided on a toon shaded style with only solid colours

Name?

Even after asking AI and using random name generators, I surprisingly wasn’t able to come up with a good name for the game. The next best thing at this time would be to give it a good temporary name that would encompass what the game is about and maybe even be related to the lore. After a lot of thought, I present to you the name: Pew Pew.

Choosing Development Tools

Now that I have all my ideas organised, I can move on to choosing my game engine and other development tools.

Game Engine

Even though I have experience with Unity, I wanted to use Godot to develop this game. Since I plan on making a game with simple graphics, I wouldn’t be needing any fancy rendering pipelines. This meant I could just use a light game engine like Godot which is only around half a gigabyte. This would in the long run enable me to have a less cluttered project, which I think is important to keep me developing the game without going anymore insane than I have to. Debatably more important, Godot can run on my potato MacBook with an 8th Gen i5, 8GB of LPDDR3 ram, and no graphics card.

Secondly, Godot doesn’t really have that much smaller of a developer community as compared to Unity. In fact there is a good percentage of Godot developers coming from Unity. This meant it wouldn’t be hard for me to learn Godot with Unity experience.

Programming Language

I had three options when it came to Godot, C# or GDScript or both. I decided to use GDScript for the most part of my code due to its purely magical integration with Godot and simplicity. If I ever do need to prioritise performance, I could then switch to using C# for that specific script.

Starting on Development

Flight

Now that I have a Godot project set up for my needs, it was time to start the real development, the slow burn torture.

Since I’ making a game about space ships I should start out the project with a flight controller. Except the tiny little problem with that is that I have never touched game development in the past 3 years and I’m using Godot and GDScript for the first time. In other words I had no idea what to do. So logically I should’ve looked up a Godot tutorial on how to make a 3D 6 axis flight controller that mimics space ship controls right? NO. I adapted code from a Unity tutorial on YouTube from gamesplusjames.

Input Code


First things first, I would need to start of by getting user input. The simplest of which is the standard WASD keys that are needed for movement. I also wanted to be able to roll on the local z axis. This basically means I can spin around my axis like in Star Wars. Finally, I needed a key to enable me to boost or speed up.

Movement Code


After that, I obviously had to move the spaceship according to the input. I started by checking if the boost key is pressed down, if it is and the spaceship is moving, then I would increase FOV for a speed up effect. Using Godot's character body, I could set the velocity using a Vector3 which was calculated based on key inputs and the boost multiplier. The final values were interpolated. To make the spaceship move, I used the move_and_slide() function inherited from CharacterBody3D in Godot.

Mouse Movemet Code


Since, the spaceship controller was controlled by the mouse to rotate around, I had to map mouse movement to actually rotating the spaceship accordingly.

To do that I spent way way longer than I should have to figure how to update rotation properly. All it took in the end was 2 lines of code that I placed in the _process() function, which gets updated every frame. For Unity people, its Update() function. The two lines basically use the mouse position (variables x and y) and the roll variable to make a Vector3 representation of the rotation and then covert that into a Quaternion and finally convert that Quaternion into a Basis data type to be used to update transform.basis which is the rotation.

Camera Follow Code


Camera follow. One of the most important feature in any 3rd person game like mine. Coincidentally, it's also notoriously confusing to implement. After about 2 extremely short days I figured it out. To achieve that I would need to set up the Camera node as a child of a parent node of type Node3D.

Node Hierarchy

The parent node will be have top-level turned on which means the node will be using global transforms instead of a transform relative to the player. This would mean I can interpolate the transform of that parent not to be exactly the same as the player node. Since the actual Camera node is a child, I can offset the camera to my needs relative to the actual player position.

Now you might ask me, why don’t you just use [.translate()](https://arc.net/l/quote/ledommvb) method on the transform object before interpolating to it? Well, this was my first instinct too. However, in practice it messed up the rotation of the camera which led me with no choice but this.

Procedural Galaxy

Finally, I had proper controls, movement, and camera follow. I could move on to the next feature. The next natural, move would be to make some basic shooting mechanics, so instead I spent a good chunk of my time generating a procedural galaxy.

Now the words ‘procedural’ and ‘galaxy’ both sound scary when it comes to programming them, but somehow programming this system was the most smooth sailing in the entire development process so far.

Unlike real galaxies that have over billions of star systems, mine only has around 100 star systems for simplified gameplay. Obviously, the distances between said star systems aren’t the average of 5 light years like in our own real galaxy. Instead, in my generated galaxy the distances between star systems on is around a mere 50 000 M –1 000 000 M.

The procedural generation starts by spawning 100 stars randomly within a sphere of a tiny arbitrary radius like say 300 000 000 M. Then, planets are spawned around the star with their own orbit distances and revolve around the star creating a star system. Different configurations of such star systems can be created and spawned around with adequate amounts of spacing between. Voila, you now have your very own simple simulated galaxy.

Spawning Celestial Bodies

A celestial body in my game can either be a star or a planet, soon there would probably other types like asteroids. For now the planets and stars are basically differently sized and coloured spheres with textures or glow effects. They are spawned by using seed noise which means the same noise can be generated when I use the same seed to generate the noise. This would work similarly as in Minecraft for the users. The seed noise is used to determine the celestial body’s size, type and global position. After the parameters are assigned to the celestial body object’s instance it is made a child of a node to make it appear in game.

Star Systems

Now that I can spawn in stars, I needed to add planets to the stars. I can use the same celestial body spawning technic to spawn in planets around the star. However, due to angular momentum (and some mathematical symbols I don’t yet comprehend), the planets of a star are usually aligned on the same plane, as in our own solar system. Since, my game was totally realistic (and not because I needed an excuse to simplify planet orbits), I wanted to spawn the planets on the same plane.

When a star is spawned, planets are spawned yet again based on seed noise, and positioned relative to their radius. The larger the planet the larger its spacing from its neighbouring celestial bodies. For example, if the closest planet to the star is large, then the spacing between the star and the large planet would be larger than if it were a smaller planet. This doesn’t mimic any real behaviour, in fact in real life orbit is decided by gravitational forces due to mass and not volume.

Planet Orbits

Since all the planets are spawned on the same axis, all I would have to do now is just move the planet relative to the star. When thinking about the easiest way to do this I came up with a similar solution to the camera following. A parent Node3D with the same position as the star will be the parent of the actual celestial body node. Then the parent node will be rotated on the Y axis as the planets are spawned on the Z axis. This will allow the planets to have a perfectly spherical orbit around the star.

Now yet again this isn’t realistic because its a game. In real life, orbits are almost never completely a sphere and orbits are almost never perfectly stable. This means if I gave each of the bodies masses and used F = G * (m1 * m2) / r² to simulate gravity and have orbits that way would be impractical as the orbits might not be for as long as it is in real life due to the smaller scale in my game. Moreover, if I do indeed end up calculating the exact velocity needed for a perfect orbit and simulate that, in my case it would have absolutely no difference other than worse performance. Hopefully thats enough justification for my sketchy methods.

Spawning Star Systems

Now that I can have procedural star systems, the final step is to spawn them in. This part is very similar to how the spawning of planets work when a star is spawned. Solar systems are spawned within a sphere with an arbitrary radius with spacing that is calculated based on the size of the entire solar system. The function in_another_body(), in this script checks if the distance between the star system that’s currently being spawned in is large enough based on my parameters. That is used to spawn the star system somewhere else where its far enough away from other star systems.

The code does indeed slow down when there is several of hundreds of star systems that I want to spawn in. It will also try to spawn a single star system forever if the distance required to spawn star systems with the spacing specified is greater than the space inside of the sphere that the star systems can be spawned in. However, for now this will do as it can still generate a small 100 star galaxy considerably quickly, even on my potato.

Conclusion

With that I have barely covered half of what I had done in the holidays for this game. In a future blog, I will continue writing about the other features I added over the holidays. In the meantime, you can checkout my GitHub repository.

Comments 0 total

    Add comment