- Date: 8.2.2024
- License: CC BY-NC 4.0
- Categories
- Programming languages
- Tools used
Alien Invasion 2024
Alien Invasion 2024 is a remake of Alien Invasion from 2015 in Godot 4. The art assets have been reused from the original game, but the code was written from scratch in GDScript utilizing a component-based gameplay framework.
Improvements over the original game include
- Particle effects for projectiles and alien death explosions
- Screen shake on certain events to improve the game feel
- Small improvements to the UI
I chose GDScript over C# as the programming language to have the ability to make this game playable in a web browser (since C# is not supported for exporting to the web in Godot 4.2).
The Game
Requirements
In order to run Alien Invasion 2024, you need the following system requirements:
- CPU: Any x86-64 CPU
Example: Intel Core 2 Duo E8200, AMD Athlon XE BE-2300 - GPU: Integrated graphics with full Vulkan 1.0 support
Example: Intel HD Graphics 5500 (Broadwell), AMD Radeon R5 Graphics (Kaveri) - RAM: 2 GB
- Storage: 150 MB
- Operating System: Windows 7 or higher
Screenshots
Insights
Source Code
The full source code is available on GitHub.
Spawning Projectiles in Godot
The approach of how to spawn nodes, like projectiles, into the game world is something I found a bit curious in Godot.
Since you have to add the instantiated node to the node tree of the game level, it is often recommended to simply emit a
signal
in the node that wants to spawn something. Let’s say you want to spawn a projectile from the player ship
when firing its weapon. Following this approach means you would have to create a signal, say weapon_fired
, and listen
to this signal in the level to do the spawning of the projectile for you.
I found this approach to be illogical, like putting the cart before the horse. The responsibility of spawning projectiles belongs to the player in my eyes, not the level the player is currently located in. There is also the inconvenience of having to remember listening to this signal in every level. What if you have a hundred levels? And then you would have to do this for every entity firing projectiles – like the aliens – in every level. Unless I am overlooking something here, I found this approach to be very cumbersome.
For these reasons, I chose to follow an approach similar to the Unreal Engine: I created a global node called Game
that holds a reference to the world
. This is always pointing to the current level (admittedly, there is only one
level in Alien Invasion, so it wouldn’t matter, but I wanted a solution I could apply to other games with more levels.)
# Autoload: Game. No class_name required here as the autoload takes are of that.
extends Node
var world: World
The level is then setting the Game.world
reference on it’s _init
method to itself.
class_name World
extends Node2D
func _init() -> void:
Game.world = self
With this done, I can then access Game.world
from anywhere to spawn and add new nodes to the game world. In the case
of the player, I am passing the world
to the ProjectileSpawnerComponent
which does exactly what its name implies.
class_name Player
extends CharacterBody2D
@onready var _projectile_spawner_component := $Components/ProjectileSpawnerComponent as ProjectileSpawnerComponent
func _ready() -> void:
_projectile_spawner_component.world = Game.world
Lastly, in the ProjectileSpawnerComponent
I can then easily access the world
to add instantiated nodes to its tree:
class_name ProjectileSpawnerComponent
extends Node
## The stats that configure the projectile.
@export var _projectile_data: ProjectileData
## Reference to the world scene the game is played in.
var world: World
func spawn(position: Vector2) -> LaserProjectile:
assert(_projectile_data, "Projectile Data not assigned")
assert(world, "World not assigned")
var projectile = _projectile_data.scene.instantiate() as LaserProjectile
projectile.projectile_data = _projectile_data
projectile.position = position
projectile.collision_layer = _projectile_data.collision_layer
projectile.collision_mask = _projectile_data.collision_mask
world.add_child(projectile)
return projectile
Concept Art
Check out the project page on the original game from 2015 for concept art.
Attributions
My Work
My contribution to the project was mainly the following:
- complete reimplementation of the game logic in GDScript
- creation of particle effects for the projectiles and alien deaths in Godot 4
- recreation of the UI in Godot 4
The Team
I would like to express my sincerest gratitude to all people who contributed to the original project, upon which this work is based. These are, in no particular order:
- Patrick Bader
- Daniel Friedenberger
- Isolde Scheurer
- Benjamin Wiedmann
- Christian Seitzer
My special thanks goes to Hansheinz Müller Philipps Sohn for providing the server infrastructure.