top of page

Rift Marine

Top-down roguelike twin-stick shooter

Unreal 5.5

5 weeks

Solo project

Download coming soon

About the game

image.png

Roguelike

image.png

Top-down Shooter

image.png

Vampire Suvivor-like

image.png

Deck Building

Rift Marine is a top-down roguelike twin-stick shooter mainly inspired by Vampire Survivors and Brotato. You will play as a Rift Marine fighting off hordes of enemies, surviving wave after wave, picking up EXP loots and selecting upgrades, and eventually becoming an unstoppable killing machine.

Design & Development process

When I decided to make a top-down roguelike shooter in Unreal, I first broke down the gameplay loop of my main reference game, Vampire Survivors and Brotato, to see how I wanted to handle the gameplay loop in my game. Each run in Vampire Survivors has no breaks for players, and players have to survive through 30 minutes of horde after horde of enemies, while in Brotato, each run is divided into 20 waves, allowing players to take a break and purchase upgrades after each wave, but players won't be able to upgrade or change their build during each wave. So I decided to kind of combine the strong suits of both gameplay loops: each run is divided into different waves like Brotato, and players can immediately select upgrade rewards as long as their gathered enough EXP to level up like Vampire Survivors.

Weixin Image_20251214193603.png

(after the countdown of each wave is finished, all enemies will vanish, and next wave will start when the player go into the portal)

Weixin Image_20251214194138.png

(EXP loots will be spawned at dead enemies' location. When the player levels up, they can choose one from three random upgrade rewards.)

image.png

Inspired by the stats system in Brotato, I decided to implement a simpler version of player stats system with 9 basic variables. Throughout each run in the game, these 9 player variables can be significantly modified depending on what upgrades the player picks. I also kept the player control inputs simple, which were just WASD to move, space to dash, and R to reload. 

(player stats system)

After deciding the core gameplay loop, I started to implement the 3C and basic player functions. The first challenge I met was that the crosshair and where the bullet was going were not 100% consistent, especially when shooting at distant enemies. I found this was because when I use "get hit result under cursor by channel" to determine how the player should rotate, the hit result was on the floor, while where the bullets were spawned was the player's gun muzzle, so this inconsistency in height caused the inconsistency between the crosshair and the projectile. My solution was: create a new trace channel called "CrosshairCheck", set the hit result under cursor for player rotation to be by the channel "CrosshairCheck", create a new floor in the level at the same height of player muzzle and set that floor's trace channel to be "CrosshairCheck". In this way, the hit result under cursor for player rotation and the player muzzle were on the same height, so the crosshair and the projectile became perfectly consistent.

(shooting prototype)

(Blueprint for player rotation)

(Blueprint for player firing and reload functions)

Another challenge I met during the early development stage was how to implement the player dash function correctly. I've made player ability with Blueprint for TPS or FPS in Unreal before, but I haven't tried with a top-down twin-stick shooter yet, where the player will always face towards where the cursor is. I figured that for a top-down twin-stick shooter, depending on whether the player is moving or not, the dash direction should also be different. If the player is static, then the dash direction should be where the player is facing. If the player is moving, then the dash direction should be where the player is moving instead of facing. Therefore, I used whether the player's velocity is greater than 0 as the boolean condition to determine the dash direction.

(dash prototype)

(Blueprint for player dash function)

After I was done with the basic player functions, I started to work on the first enemy, which was a basic melee type that kept chasing the player and attacked when close enough. Then I threw in dozens of enemies into the gym level and moved around with the player character to see if the controls and combat were smooth and responsive. I kept polishing everything until I was satisfied, then I invited some others to playtest, and everyone felt the controls and combat were smooth.

(early combat prototype)

(testing player rotation control)

(EXP loots, player level system, critical hit system implemented)

Meanwhile, I was also writing down ideas for the upgrade/perk rewards I could have in the game. Since this was the first roguelike project I made back then, I didn't want to go too overscoped, so the effects of most upgrades were just modifying the stats variable of the player. But I also don't want to make the upgrade boring and generic, and I wanted players to always make strategic decisions when selecting the upgrades. Therefore, many of the upgrades bring both positive and negative effects to the player. And I tried to make the names of these upgrades consistent with their effects to make them fun. For example, the "Human Turrent"  can significantly increase the player's fire rate and critical rate, but the player won't be able to move when firing.  The "Parthian Shot" can significantly increase player move speed when firing and allow the player to dash when reloading, but also significantly decrease player Max HP. Depending on different scenarios and play styles, every player can find the build that suits them most. 

(over 60 uppgrade ideas, most of them have been implemented in the game)

(Stucts, enums and data table for implementing the upgrade pool)

One special enemy is the "Bomber". Bombers will rush to the player on sight and detonate themselves when close enough. When there are Bombers hiding in a horde of enemies, taking them out will be the priority.

(Bomber enemy)

(Blueprint for Bomber's self explode mechanic)

Another interesting enemy is the "Spectre". When Spectres see the player, they will run to the player and fire plasma shotguns at the player. If the player runs away from the Spectres, they will turn into the form of intangible plasma, recovering all lost HP, moving to the player at a very fast speed and becoming invincible during the process.  If the player keeps running away from the Spectres, then they will never get rid of them. If the player stands still and faces the Spectre head-on, then Spectres won't be too hard to deal with due to their relatively low HP.

(Spectre enemy)

(Blueprint for Spectre's teleporting mechanic)

Overall, the development of this project was a very fun and fruitful experience for me and enhanced my visual scripting and gameplay design skills a lot. I planned to continue expanding and iterating this game in the future.

bottom of page