Inspiration

The Young Raider was created for Reddit’s Devvit Hackathon as a single-player action-survival and progression game.

The project was inspired by a larger browser game I had developed previously. For the hackathon, I challenged myself to recreate its most engaging ideas inside Reddit’s Devvit environment while simplifying the scope enough to complete it within the contest timeline.

Before starting development, I identified the parts of the original game that made it enjoyable:

  • Constant character progression
  • Increasing enemy difficulty
  • Meaningful upgrade decisions
  • High-score chasing
  • Simple controls
  • Short but replayable sessions
  • Long-term goals beyond a single run

Because Reddit games are often played in short bursts and on mobile devices, I wanted the game to be understandable within seconds while still providing enough depth for repeated attempts.

The result is a game built around progression, mastery, personal-best improvement, and competition. Instead of having a traditional ending, each run challenges the player to survive longer, destroy increasingly powerful bases, collect more resources, and achieve a higher leaderboard position.

I also wanted each run to feel less predictable. This inspired systems such as randomized enemy spawns, changing base locations, multiple enemy types, progressive scaling, upgrade choices, catastrophes, and unlockable characters.

The central design goal was simple:

Create a game that is easy to begin, difficult to master, and rewarding to return to.

What it does

The Young Raider places the player in a hostile battlefield containing enemy camps, bases, environmental dangers, and opponents that continuously become stronger.

Players must:

  • Fight enemies using attacks and abilities, with own combat skills such as reaction and dodging
  • Clear enemy camps
  • Destroy enemy bases
  • Collect gold and other resources
  • Purchase upgrades during each run
  • Survive periodic catastrophes
  • Unlock and select different Raiders
  • Improve their personal best
  • Compete on a persistent global Reddit leaderboard

Enemy camps function as protected areas where enemies patrol, recover health, and return when the player leaves their pursuit range. Enemies get enraged if the player hit the base directly, which grants them much higher damage and movement speed to the player.

The enemy base acts as the central objective of each run. When the player destroys it:

  1. The remaining defenders are eliminated.
  2. The player receives rewards.
  3. A rebuilding timer begins.
  4. A stronger base appears at a different location.
  5. Stronger enemies are generated.

This creates an endless progression loop in which every successful base destruction makes the next stage more difficult.

Enemy health and damage also increase at fixed intervals. This prevents players from taking his time and creates constant pressure to improve their build.

Catastrophes periodically threaten areas of the battlefield, forcing players to move rather than remain in one safe location. It can also be used strategically to lure enemies to the high damage of Catastrophe fire storms.

The in-game shop allows players to spend their collected resources on upgrades such as:

  • Maximum health
  • Attack damage
  • Attack speed
  • Movement speed
  • Increased gold rewards
  • Catastrophe immunity
  • Other powerful enhancements

The game also contains a character collection system. Different Raiders have unique appearances, statistics, and playstyles, giving players long-term objectives beyond achieving a higher score.

When a run ends, the completed score is submitted to the Reddit Devvit server. The Game Over screen displays the player’s:

  • Final score
  • Personal best
  • New personal-best status
  • Global leaderboard rank
  • Score-saving status

A dedicated leaderboard screen displays the top ten players, their Reddit usernames, their scores, and the current player’s global position.

How I built it

The game was built using:

  • Phaser for the game engine
  • TypeScript for gameplay and server logic
  • HTML5 for browser deployment, CSS for designing of Reddit post contents
  • Reddit Devvit for interactive-post integration
  • Hono for server API routes
  • Devvit Redis for persistent data
  • Reddit authentication for player identification
  • Shared TypeScript types for client-server communication

The project is divided into several scenes and systems, including:

  • Preloader
  • Main menu
  • Raider collection
  • Main gameplay scene
  • Battle UI
  • Tutorial overlay
  • Game Over scene
  • Leaderboard
  • Server APIs
  • Persistent profile and progression systems

Gameplay architecture

The gameplay was divided into separate classes and systems wherever possible.

These systems manage:

  • Player movement and combat
  • Enemy behaviour
  • Enemy camps
  • Enemy bases
  • Catastrophes
  • Upgrade purchasing
  • Score calculation
  • Character unlocks
  • Desktop controls
  • Mobile controls
  • Scene transitions
  • Tutorial progression

Enemies use several behaviour states, including:

  • Patrolling
  • Detecting the player
  • Pursuing the player
  • Attacking
  • Returning to camp
  • Healing
  • Becoming enraged
  • Becoming strengthened
  • Dying

The player can control the game using a mouse and keyboard on desktop or a virtual joystick and touch buttons on mobile.

Persistent leaderboard

Competitive scores needed to be stored outside the browser. Local storage would have been device-specific, easier to modify, and unsuitable for a shared Reddit leaderboard.

I therefore created two main API flows:

  • Submit a completed score
  • Retrieve leaderboard results

When the player dies, the Game Over scene freezes the final score and sends it to the server.

Scores are not submitted when the player:

  • Leaves through the pause menu
  • Restarts from the pause menu
  • Returns to the main menu
  • Refreshes the Reddit post
  • Closes an unfinished run

A one-time submission guard prevents the same Game Over event from sending the score more than once.

The server validates each submitted score and rejects values that are:

  • Missing
  • Negative
  • Non-numeric
  • Non-integer
  • Above a reasonable maximum

The authenticated Reddit username is retrieved through Devvit’s server context, so players do not need to create a separate account or manually enter a display name.

Leaderboard scores are stored using a Redis sorted set. This allows each Reddit username to be associated with a score while supporting score ordering and rank calculations.

For every valid submission, the server:

  1. Retrieves the player’s existing personal best.
  2. Compares it with the completed score.
  3. Saves the result only when it is higher.
  4. Preserves the previous best when the new score is lower.
  5. Calculates the player’s global rank.
  6. Returns the result to the client.

This transformed the project from an isolated browser game into a persistent Reddit competition.

Responsive desktop and mobile design

The game uses a fixed internal resolution, while Phaser scales the complete game to fit the available display.

This provides a consistent coordinate system for gameplay, cameras, UI positioning, and input while still supporting different devices.

The Battle UI was redesigned into a compact horizontal interface containing:

  • Player statistics
  • Catastrophe information
  • Enemy-strengthening progress
  • Score-multiplier progress
  • Score and currency
  • Shop and pause controls

The shop uses a dedicated Phaser camera. Its viewport matches the visible shop area and displays only the scrollable item container, while the shop header and scrollbar remain fixed.

Mobile controls include a virtual joystick and large touch-friendly ability buttons. The input system also prevents touches on HUD elements from being interpreted as movement commands.

Interactive tutorial

As the game grew, a simple instruction page was no longer enough to explain its mechanics.

I created a multi-step first-time tutorial containing:

  • Previous and Next navigation
  • A progress indicator
  • Darkened overlays
  • Spotlight regions
  • Animated arrows
  • Dynamic dialogue positioning
  • HUD highlights
  • World-object highlights
  • Temporary demonstrations
  • A final Start Battle button

The tutorial explains mechanics such as:

  • Enemy camps
  • Enemy bases
  • Enemy strengthening
  • Catastrophes
  • Enrage effects
  • Pursuit behaviour
  • Camp healing
  • Attack indicators
  • Base progression

World objects exist in camera-based coordinates, while the tutorial overlay uses screen coordinates. To align them correctly, helper methods retrieve an object’s world bounds, convert those bounds into screen space, and position the tutorial spotlight around the resulting area.

Instead of relying on a full-screen geometry mask, the tutorial creates several dark rectangles around the target. This leaves the selected area visible and avoids WebGL compatibility problems.

Tutorial completion is stored in Devvit Redis for authenticated Reddit users. Guest users can still complete the tutorial and begin playing, but their completion cannot be saved permanently without an account identity.

The tutorial was eventually extracted into a separate TutorialOverlay class so that its navigation, spotlights, arrows, demonstrations, API requests, and cleanup logic did not overwhelm the main Battle UI file.

Challenges I ran into

Learning the Devvit environment

Although I had previous experience with JavaScript, TypeScript, Unity game development, Devvit introduced a different project structure, deployment process, hosting environment, and server workflow.

I had to learn:

  • Devvit project structure
  • Interactive posts
  • Development and deployment commands
  • Reddit developer tools
  • Asset and build handling
  • Server context
  • Redis integration
  • Client-server communication

The early stages involved significant trial and error. Building and deploying small test versions helped me understand the workflow before implementing the complete game.

Scene lifecycle management

As the number of scenes increased, scene transitions became one of the most difficult technical areas.

Bugs appeared where:

  • UI elements remained after a restart
  • Timers stopped updating
  • Old objects were still referenced
  • Scenes resumed with outdated values
  • Multiple copies of systems were created

I solved these problems by restructuring initialization and shutdown logic, resetting scene state carefully, and ensuring that each new run recreated the required objects cleanly.

Enemy state management

Enemy behaviour became increasingly complex as more mechanics were introduced.

State conflicts appeared between patrol, pursuit, attack, return, healing, enrage, strengthening, and death behaviour.

One difficult bug prevented later groups of enemies from becoming enraged after new bases were constructed. The cause was a stale list containing references to enemies from an earlier base.

Fixing it required restructuring how enemy instances were registered, removed, and retrieved throughout the run.

Base reconstruction

Rebuilding the base after destruction required several connected systems to happen in the correct order.

The intended sequence was:

  1. Destroy the current base.
  2. Eliminate its defenders.
  3. Display the rebuilding timer.
  4. Remove old objects safely.
  5. Create the stronger base.
  6. Register the new enemies.
  7. Update the UI and difficulty state.

Initially, defeated enemies disappeared too early, new enemies inherited incorrect references, and timers became disconnected from the current base.

The solution involved delaying cleanup, explicitly registering each new instance, and separating the destruction and reconstruction phases.

UI synchronization

The HUD depends on many changing gameplay values, including:

  • Health
  • Damage
  • Attack speed
  • Movement speed
  • Currency
  • Score
  • Score multiplier
  • Enemy strengthening
  • Catastrophe timing
  • Base rebuilding

After restarts, the gameplay values could be correct while the interface still showed information from the previous run.

I resolved this by improving the initialization order and ensuring that the Battle UI always received references to the current gameplay objects.

Mobile and desktop responsiveness

The original game was designed around a fixed landscape resolution, which worked during desktop testing but caused problems on mobile devices and narrower browser windows.

Issues included:

  • Cropped gameplay
  • Loading screens not filling the display
  • Incorrect UI scaling
  • Controls becoming too small
  • HUD elements covering gameplay
  • Shop contents escaping their panel
  • Portrait orientation problems
  • Input coordinates not matching the visible screen

My initial approach was to reposition objects individually. This created additional inconsistencies because the gameplay camera, UI, and input did not always share the same coordinate system.

Using a fixed logical resolution with full-game scaling produced a much more stable result.

Building the tutorial

The tutorial needed to connect objects from two different Phaser scenes and coordinate systems.

It also needed to create temporary effects without changing the real game state. For example:

  • Displaying an enrage marker without increasing enemy damage
  • Showing a pursuit bar without changing detection behaviour
  • Displaying an attack cone without triggering an attack

Temporary objects also needed to be removed whenever the player changed pages and recreated when moving backward.

I solved this using page-specific onShow behaviour and centralized cleanup methods.

Trusted server data

Another challenge was deciding which responsibilities belonged to the client and which belonged to the server.

The Phaser client runs the game and calculates the final score. The Devvit server:

  • Identifies the Reddit account
  • Validates the submitted value
  • Preserves personal bests
  • Stores leaderboard data
  • Calculates global rank
  • Returns the final result

This separation reduced accidental data inconsistencies and made the leaderboard more reliable than a client-only implementation.

Accomplishments that I am proud of

I am proud that The Young Raider evolved from a simplified adaptation of an older project into a complete Reddit game with connected gameplay, progression, onboarding, and server systems.

The completed project includes:

  • Fast-paced action combat
  • Multiple enemy camps
  • Several enemy behaviours
  • Progressive enemy scaling
  • Rebuilding and strengthening bases
  • Catastrophe events
  • A decreasing score multiplier
  • An in-run upgrade shop
  • Character collection
  • Desktop and mobile controls
  • A responsive battle interface
  • A scrollable shop with its own camera
  • A multi-step interactive tutorial
  • Persistent tutorial completion
  • Reddit account authentication
  • Devvit server integration
  • Redis high-score storage
  • Personal-best tracking
  • Global ranking calculations
  • Server-side score validation
  • A top-ten leaderboard
  • One-time Game Over submissions

I am proud of successfully turning the game into a persistent Reddit experience. Players are not simply completing isolated browser sessions. They can return, improve their personal best, and compete against other Reddit users.

What I learned

This project reinforced the importance of planning architecture before systems become heavily interconnected.

Many of the most difficult bugs were not caused by advanced algorithms. They came from:

  • Old references surviving after restarts
  • Objects being destroyed in the wrong order
  • Scenes initializing at different times
  • UI systems reading stale values
  • Temporary tutorial objects not being cleaned up
  • Client and server responsibilities being unclear

I learned that scene lifecycle management is just as important as gameplay logic.

I also gained a better understanding of responsive game development. Making a game responsive is not the same as resizing a normal webpage. It requires considering:

  • Logical game resolution
  • Display scaling
  • Camera viewports
  • Safe gameplay areas
  • Input-coordinate conversion
  • UI layers
  • Touch targets
  • Orientation
  • Aspect ratios
  • Scrollable game interfaces

Frequent testing on both desktop and mobile was essential because many issues were invisible when testing on only one device.

Another important lesson was the value of separating trusted server operations from client gameplay. Shared TypeScript request and response types helped keep both sides synchronized and reduced errors when processing API results.

The tutorial taught me that onboarding can become a major technical system. Explaining a mechanic clearly may require camera conversions, dynamic overlays, object lifecycle management, persistent completion data, and temporary gameplay demonstrations.

Most importantly, I learned that major features rarely work perfectly on the first attempt. Nearly every system improved through repeated testing, debugging, restructuring, and refinement.

What's next for The Young Raider

The next step is to gather feedback from real Reddit players and use it to improve balancing, usability, and replayability. Perhaps I would recreate this project in Unity 3D since using 2D assets bring many limitations such as poor flexibility of changing weapons, difficult controls as the characters uses 8 directional spritesheets. 3D variant would also improve accuracy of hitbox. As this hackathon is focused on Phaser, I decide to stick to 2D/

Survive, grow stronger, overcome relentless enemies, and climb the global ranks!

Share this project:

Updates

Submission history