Magic Zombies (2013-2018)


My biggest passion project so far, and a fairly accurate measure for my growth as a game developer over the years: an arcade top-down shooter.

Since I made the first prototype in Clickteam’s Multimedia Fusion 2 back in 2013, the game has changed a lot, except for its simple goal: you kill zombies until you die. The twist: these zombies are almost never alone, while their loot must be gathered close to the point they died. This mechanic requires the player to smoothly dance and manoeuvre their way through the hordes, else they’ll fall behind in unlocks and upgrades that help them push through the game’s scaling difficulty; firing from a distance is discouraged!

The core inspiration for this game is the “Zombie Mode” game mode from the Call of Duty franchise, though a lot of inspiration was drawn from a variety of genres and titles. For example, the main weapon was inspired by ‘90s space shooters, some equipment was inspired by items in League of Legends and the satisfyingly juicy rain of hitsplats was inspired by more modern hack-and-slash games.

While the last version of the game was built in Android Studio, I’ve only used the software for its native Android compatibility; the game itself runs on a homebrew engine.

Code examples and design choices

Code: Limiting actions in a loop to happen periodically

In the code above, I defined two simple methods whose boolean results can be used as a condition for an if-statement in the game loop. Effectively, a check is made to see if a sufficient number of frames has passed since the last call, limiting certain actions to happen only a certain amount of times per second or minute.

In this implementation for example, this simple if-statement makes sure particles are created at a rate of 4 per second.

What I would do differently today
In hindsight, I realise that I could’ve increased performance by making less frequent use of static methods and attributes, e.g. Engine.repeatPerSecond() and Constants.frameCount. It might’ve been better to make these accessible through methods in the base GameObject class, instead.

(Also, the rather convoluted SpriteParticle constructor call could’ve easily been replaced by a more specific ‘new SnowParticle(creature)’ constructor call)