Cart Movement and Enemy Spawning

by | Feb 10, 2025 | Rail Spirits

I’ve spent the last week and a half working on implementing a few more core features for Rail Spirits, including getting the cart moving, as well as spawning enemies when the player’s cart passes certain points. I also started fleshing out the mechanics of 4 different enemy types. Instead of GIFs this time, I made a video of the new stuff, since there have been a lot of new things added – you can find it toward the end of this post!

Before I started on those features, I went ahead and added controller support, since that’s an important feature for my wife, and it’s a nice thing to have in general. It went smoother than I expected, since Godot’s built-in input system made it easy to map buttons to inputs I had already set up; getting the joystick to control the camera was the trickiest part.

After that, I worked on the cart movement system. As the player progresses through the game, they’ll unlock 2 additional routes on each map that they can select at the beginning of the run, with those routes being left and right of the main route. These alternate routes will be much tougher, but the player will receive more currency from defeating enemies, as well as stronger in-run upgrades from the checkpoints along alternate routes. When building that system, I wanted a visual way to make sure things were working, so I went ahead and added an arcade-style prompt when the player gets near the track switching point that lets them choose their track.

I also added basic gravity to the rail system that calculates how fast the cart should go based on the incline / decline slope. I’ll likely need to tweak it once I start making the actual maps, since I want to make sure the game is generally slow enough that the enemies can keep up with the player and be a threat (and so the player can actually shoot the enemies), while having some fast sections that feel a bit like a rollercoaster (especially during the boss sections). I currently have the max and min cart speed capped pretty conservatively to keep things simple.

Next, I created 4 distinct enemy types (out of 6 of the basic enemy types that I have planned so far):

    • Ghosts (currently represented by a purple capsule with blue outer glow) spawn in large numbers (to make up for their low health and damage) and rush the player. They can only attack the player once, dying after doing so.
    • Zephyrs (currently represented by a pink box) move like wind through the player, then turn back around and heads back through the player. This repeats up to 3 times if the player doesn’t defeat it first. They deal a lot more damage than ghosts, but are still pretty easy to defeat.
    • Phantoms (currently represented by a transparent capsule with purple outer glow) are ranged enemies that cast a spell at the player. They deal decent damage, have decent health, and don’t have an attack limit. Spells from Phantoms are blocked by the Shield special.
    • Wraiths (currently represented by red capsules with an orange outer glow) teleport behind the player anytime they are damaged, leading the player to have to focus on the wraith to defeat them. They are the toughest enemy so far, with high damage, high health, and no attack limit.

With adding these enemies, I also added simple placeholder animations for when they spawn and are defeated.

On that note, I added a dynamic spawn system that allows enemies to spawn as the player moves along the track. I set them up so that I can set the spawn chance of each enemy that can spawn at each spawnpoint, as well as a range of how many enemies can spawn randomly. This means that I can set them to spawn a specific amount of a specific enemy type (as shown in the demo video below), or randomized amounts of random enemy types, which will be nice for adding difficulty ramps as the player progresses along a run.

Stats

User Stories Completed: 
25 for this period  |  83 total

Bugs Found: 
4 for this period  |  8 total

Bugs Fixed: 
3 for this period  |  7 total

Commits:
71 for this period  |  169 total