Locomortis
Locomortis is an isometric arena survival game where you deliver cargo carts across hostile alien terrain with a customizable, weaponized train. Earn credits for successful deliveries, unlock new weapon carts, and build your loadout for each mission. But beware, losing carts comes at your own expense, and if you can’t afford it – you are done. With limited cart slots, you’ll need to balance defense and profit, while choosing weapons suited to each mission’s enemy threats.
Watch the teaser video
Project informations
Team size: 2 persons
Duration: 1 college semester
Engine: Unreal Engine 5
My Roles:
Game Design: Shared equally (1 of 2)
Programming: Main programmer. Developed most features solo, except for VFX and post-processing.
Sound Design: Full design and integration. Sound effects are taken from a sound library and the music is created by external contributor Stéphanie Boulay.
Game design
Philosophy
This project aimed to highlight strong game design in a simple, accessible, and instantly engaging format. Choosing the arena survival genre let us focus on game mechanics over intricate level design, story, or visuals. We designed meaningful weapon-enemy interactions and a lightweight, economy-driven meta-game with the goal of encouraging quick priority decision-making, risk-reward planning and juggling between different tools to maximize effectiveness.
Goals and Challenges
The main challenge was to showcase thoughtful, in-depth game design within the constraints of a two-person team and a limited timeline. Scope management became essential, with a focus on quality over quantity. This allowed us to polish a modest but viable set of weapons and enemies, ensuring each felt unique and engaging. Every stat, timing, and edge case was carefully tested and iterated on to create a small-scale experience that feels intuitive, frictionless, and compelling—while hinting at how the game could scale further.
Here is a few of the mechanics I’ve worked on
Counter play system (rock paper scissors)
Each weapon is designed to counter a specific enemy type but can still damage others with more effort or time.
Only one weapon can be fired at a time, encouraging frequent switching based on moment-to-moment threats.
This creates fast-paced, thought-driven gameplay that rewards quick decision-making over passive clicking.
Players are incentivized to bring only the most essential weapons to maximize cargo space and profit.
Balance tuning ensures skilled players can complete all missions using fewer weapons then permitted — allowing for self-imposed challenge.
Enemies mechanics
Each enemy has part of its health set as a regenerating energy shield, encouraging players to focus on finishing one target at a time before it recovers and making accurate target priorisation even more important.
Seeker – A fast-moving, low-health enemy that rushes the train to explode on impact. Its speed makes it hard to track, but its fragility makes it easy to destroy if caught early. Continuous, directional fire from the machine gun is the most reliable countermeasure.
Disruptor – A slow but durable enemy that damages the train with a short range laser that intensifies over time. It poses little threat initially, but becomes dangerous if left unattended. Most of its durability comes from its energy shield, making it ideal for the rail gun’s anti-shield capabilities.
Obelisk – A ranged enemy that fires projectiles from a distance. Its weak core is protected by rotating armor plates, and its projectiles can be destroyed. Alone, it’s manageable, but in groups it becomes a serious threat—blocking player shots and protecting advancing enemies. The missile launcher excels here, bypassing the armor and striking the core directly from above.
Player weapons
Each weapon cart serves a distinct purpose, encouraging the player to adapt their loadout to the mission’s threats.
Machine Gun – A fast-firing, low-damage weapon with quick turret rotation. It’s the player’s starting weapon and is ideal for tracking and destroying agile targets like Seekers. Its forgiving fire rate allows missed shots, but players still need to lead their aim due to noticeable bullet travel time.
Rail Gun – A high-damage, slow-firing energy beam that excels against Disruptors due to its bonus damage to energy shields. It fires after a short charge-up, requiring timing and precision. It can pierce enemies in a line, but its beam is blocked by Obelisk armor plates.
Missile Launcher – A slow but powerful area-of-effect weapon with a delay between firing and impact. It requires predictive aiming but can eliminate clustered enemies in one strike. Its indirect fire makes it ideal for hitting Obelisk cores behind armor.
Shield Cart – A utility cart that adds passive energy shields to all train carts. Its active ability temporarily makes the train invulnerable and restores some health, but drains all shield energy afterward, leaving the player vulnerable until it regenerates. Best used strategically in high-risk moments.
Progression & Economy System
Each cart—whether weapon or cargo—takes up one of five available train slots, encouraging meaningful loadout decisions.
Cargo carts offer no combat value but reward more credits than they cost—if delivered intact. Players can bring several cargos, but each must be repurchased after use.
Players receive a free, mission-appropriate new weapon for the first four missions as a form of tutorialization. Intact weapons remain free, but destroyed ones must be repurchased at high cost.
Failing a mission by losing all carts forces the player to buy replacements—if they have enough credits. If not, the run ends and restarts to mission one.
This creates a constant trade-off between playing it safe and taking risks to earn more credits for long-term survival; adding a layer of resource management to the gameplay experience.
A pre-mission briefing reveals the dominant enemy types, helping players tailor their loadout based on expected threats and personal risk tolerance; giving them more choice and freedom on how they wish to play.
Programming
Challenges
The biggest programming challenge was creating an enemy AI that felt unpredictable while still following recognizable behavior patterns the player could learn. After scrapping an unsatisfying first version, we rebuilt the system using a grid-based approach—where enemies move between preset points on a hidden coordinates grid. This gave us the right balance of control and randomness, allowing us to quickly create varied behaviors using a small set of simple, adjustable variables.
Here are some of the features I’ve built using blueprints
Grid sysyem
The movement grid is divided into two sections—one on each side of the train—to simplify AI behavior and positioning logic.
A parent-child hierarchy lets both grids exist as separate objects while sharing a single construction algorithm, avoiding duplication.
Two serial loops generate points along the X and Y axes, storing both world coordinates and simplified integer-based coordinates in a map variable. This dual storage will support simpler AI calculations and labeling.
The grid is structured so that the point labeled (0,0) is the point nearest the train’s center. This setup lets us bias enemy movement toward the player by weighting random choices closer to the zero value.
The furthest grid points from the train are stored in a separate array and used as randomized spawn locations for incoming enemies.
The grids also keep track of the occupied coordinates, making sure no two enemies will choose the same point at the same time.
Use CTRL + Mouse wheel to zoom and right click to drag to navigate
AI system
When spawned, each enemy is assigned to one of the two side-specific grids and cannot cross to the other. This keeps movement logic simple and prevents aimless wandering before engaging the player.
To move, the AI reads its current grid coordinates and randomly adds or subtracts a value (0 to 2, depending on enemy type), with a bias toward (0,0) to encourage movement toward the train.
The chosen coordinate is validated to ensure the point exists and isn’t already occupied by another enemy. If invalid, the randomization restarts until a valid point is found.
Once validated, the enemy moves to the specific world location associated with that point coordinates.
For close-range attackers, once near the train, the system checks if a latch point is available. If found, the AI is disabled and a new behavior sequence in the enemy’s blueprint takes control.
Use CTRL + Mouse wheel to zoom and right click to drag to navigate
Enemy Health System
The health system is built as a modular actor component that can be attached to any enemy.
A modified version of this component is also used for the player's train carts, sharing features like damage handling, shield regeneration, health bar UI, VFX, and SFX triggers.
When the owning actor takes damage, the component receives both the damage amount and type as inputs through an event trigger.
If hit by the rail gun, the component temporarily reduces the shield value, reflecting the rail gun’s shield-countering effect.
Shield and health values are then updated sequentially based on the damages received and absorbed by the shield.
If health drops to zero, an OnKilled event is sent to the owner.
If not, a shield regeneration event is triggered, which slowly restores shield after a short delay without further damage.
Use CTRL + Mouse wheel to zoom and right click to drag to navigate
Use CTRL + Mouse wheel to zoom and right click to drag to navigate
Enemy Spawning System
Each mission uses a dedicated data table that defines enemy spawning sequence. Each table row represents an enemy wave with values for spawn time, enemy types/quantities, and which side of the train they should appear from.
When a mission starts, the corresponding data table is loaded and a timer begins counting elapsed seconds.
When elapsed time matches a wave’s scheduled spawn time, a wave spawner event is triggered with that wave’s information.
The spawner loops through each enemy type and quantity, picks random spawn points from the grid system’s array, and spawns the enemies accordingly.
This setup allows easy creation and iteration of varied missions by simply editing or creating data tables from the same template.