A fully playable 2D cyberpunk platformer inspired by Prince of Persia, built entirely with vanilla JavaScript and Canvas 2D.
Visit the GitHub Pages deployment to play instantly in your browser.
Year 2189. Neo-Shenzhen 7. A megacity of 80 million souls, all connected to the Nexon Grid — controlled by AXIOM, a corporate AI that manages everything from power to memory.
You are Kael Voss, a former Nexon enforcer who discovered Protocol Shadow — AXIOM's plan to upload and overwrite the consciousness of every citizen. When your partner Mira's memory was wiped for knowing too much, you went underground.
Armed with your mono-katana and cybernetic implants, you must fight through the city's three districts — The Undergrid, The Midwire, and The Spire — to reach AXIOM's core and destroy Protocol Shadow before 80 million minds are erased forever.
- Prince of Persia-style platforming: run, jump, wall slide, ledge grab, climb
- Combat system: light/heavy attacks, block/parry, dodge with i-frames, stamina management
- Targeting priority: nearest attackable enemy highlighted with a cyan bracket
- Attack telegraph warnings: enemies show clear visual wind-up indicators before attacking
- 12 campaign levels across 3 acts
- 2 boss fights: Warden Frame (Act 1) and AXIOM Core (Final Boss) with multi-phase encounters
- 5 enemy types: Sentinel Drone, Hover Drone, Enforcer Mech, and 2 bosses
- Enemy HP bars: health indicators above enemies (shown when damaged); boss name labels and large HP bar during boss fights
- Enemy corpse system: defeated enemies remain visible with a fade-out animation instead of vanishing instantly
- Traps and hazards: lasers, spikes, timed obstacles — hazards also damage enemies (bosses immune); enemy corpses on spikes lock them extended; smart per-entity damage cooldowns prevent re-damage within the same activation cycle
- Fall damage: enabled on Operative+ difficulties when landing velocity exceeds threshold
- Collectibles: Data Shards for score bonus, Life Shards (+1 max HP per 5 collected, up to 8 max HP)
- 4 difficulty levels: Civilian (Easy), Operative (Normal), Agent (Hard), Shadow Protocol (Hardcore with permadeath)
- Training/Practice mode: a dedicated arena accessible from the main menu with all mechanics present — no saves, no scoring, no achievements
- 6 animated in-engine cutscenes with character portraits, typewriter dialog, camera pans, character movement, and timed events
- Full narrative arc from underground sewers to corporate spire
- 4 named characters: Kael Voss, Mira, Dekker, AXIOM
- Cutscene skip: hold Escape for 1.5s; cutscenes don't replay on level retry within the same session
- Achievement system: 21+ achievements (combat, exploration, speed, hidden)
- Speedrun mode: continuous timer, level splits, best time comparison, ghost replay system
- Speedrun ghost system: record your run, toggle ghost overlay (G key), export/import replays as secure JSON (HMAC-SHA256 integrity check)
- Leaderboard: top 10 scores with initials entry; "End Game" option on death for DNF leaderboard entry
- Multi-slot save system: 3 save slots with save/load/overwrite/delete; auto-save at checkpoints; automatic migration from legacy single-slot format
- Settings: volume control, difficulty selection, scanline toggle
- Progress indicator: HUD shows Act/Level, shard collection progress (collected/total), and difficulty badge
- 100% procedural graphics: all sprites drawn with Canvas 2D primitives
- Enhanced animations: player squash/stretch, dodge afterimage trails, enemy telegraph indicators, smooth spike extend/retract, laser startup flicker
- Procedural audio: all sounds generated with Web Audio API
- Zero external dependencies: no libraries, frameworks, or CDN
- 60 FPS game loop with fixed timestep
- Particle effects: dust, sparks, dash trails, explosions, hazard sparks, impact stars, energy wisps
- Complete tutorial system: contextual prompts covering all controls (movement, combat, heavy attack, block, wall slide, stamina, hazards, pickups, checkpoints, pause)
| Action | Key |
|---|---|
| Move Left/Right | ← → or A/D |
| Climb Up/Down / Menu Navigate | ↑ ↓ or W/S |
| Jump | Space |
| Light Attack | Z |
| Heavy Attack | X |
| Dodge (with direction) | C (while moving) |
| Block (standing still) | C (while standing still) |
| Parry (timed block) | C (precise timing on incoming attack) |
| Toggle Ghost (speedrun) | G |
| Pause / Skip Cutscene (hold 1.5s) | Escape |
| Confirm / Advance | Enter |
| Delete Save Slot | Delete |
| Difficulty | Damage Taken | Enemy HP | Enemy Damage | Stamina Drain | Fall Damage | Score Mult | Special |
|---|---|---|---|---|---|---|---|
| Civilian (Easy) | ×0.5 | ×0.75 | ×0.75 | ×0.75 | Off | ×0.75 | — |
| Operative (Normal) | ×1.0 | ×1.0 | ×1.0 | ×1.0 | On | ×1.0 | Default |
| Agent (Hard) | ×1.0 | ×1.5 | ×1.5 | ×1.25 | On | ×1.25 | — |
| Shadow Protocol (Hardcore) | ×1.0 | ×1.5 | ×1.5 | ×1.25 | On | ×1.5 | Permadeath — death clears save, auto-leaderboard entry |
Select difficulty after choosing "New Game" from the main menu. Difficulty can be changed mid-game from Settings (except Shadow Protocol, which locks once selected).
3 independent save slots, each storing: level progress, score, health, max health, shards collected, Life Shards, difficulty, checkpoint position, and total play time.
- Auto-save: triggers at every checkpoint
- Save Slot Panel: accessible from Main Menu — shows level name, play time, date, difficulty badge, and shard count per slot
- Actions: Load, New Game (into empty slot), Overwrite (with confirmation), Delete
- Legacy migration: old single-slot saves (
neonrift_save) are automatically migrated to Slot 0 on first load - Hardcore: Shadow Protocol deaths automatically clear the active save slot
public/
├── index.html # Entry point, canvas setup
├── src/
│ ├── main.js # Module loader, game initialization
│ ├── core/ # Engine core
│ │ ├── Game.js # Game loop, state machine
│ │ ├── Input.js # Keyboard input handler
│ │ ├── Camera.js # Smooth follow camera with shake
│ │ ├── Physics.js # Gravity, velocity, friction
│ │ ├── Collision.js # AABB + tile-based collision
│ │ ├── AudioManager.js # Web Audio API procedural sounds
│ │ └── AssetManager.js # Asset stub (all procedural)
│ ├── rendering/ # Visual systems
│ │ ├── Renderer.js # Layer-based rendering, parallax
│ │ ├── SpriteRenderer.js # Procedural entity drawing, telegraphs, ghost
│ │ ├── ParticleSystem.js # Object-pooled particle effects
│ │ ├── Effects.js # Screen shake, flash, scanlines
│ │ └── BitmapFont.js # Text with glow effects
│ ├── entities/ # Game entities
│ │ ├── Player.js # 12-state player (run/jump/combat/climb)
│ │ ├── Enemy.js # Base enemy class (HP bar, corpse fade, telegraphs)
│ │ ├── SentinelDrone.js # Melee patrol guard
│ │ ├── HoverDrone.js # Flying ranged enemy
│ │ ├── EnforcerMech.js # Heavy armored unit
│ │ ├── WardanFrame.js # Act 1 boss (3 phases)
│ │ ├── AxiomCore.js # Final boss (4 phases)
│ │ ├── Projectile.js # Energy bolt
│ │ ├── EntityFactory.js # Entity instantiation factory
│ │ ├── LaserTrap.js # Toggling laser hazard (damages enemies)
│ │ ├── SpikeTrap.js # Periodic spike trap (corpse lock, damage cooldown)
│ │ ├── Trap.js # Base trap class (damagesEntity support)
│ │ ├── DataShard.js # Score collectible
│ │ ├── HealthPack.js # Health restore pickup
│ │ └── LifeShard.js # Max HP upgrade collectible (5 → +1 HP)
│ ├── level/ # Level management
│ │ ├── TileMap.js # Tile rendering + collision layer
│ │ └── LevelManager.js # Level loading + transitions + act helpers
│ ├── ui/ # User interface
│ │ ├── MainMenu.js # Title screen with neon rain
│ │ ├── PauseMenu.js # In-game pause overlay
│ │ ├── HUD.js # Health/stamina/score/progress/difficulty badge
│ │ ├── GameOverScreen.js # Death screen (Retry/End Game/Quit)
│ │ ├── LevelCompleteScreen.js # Victory stats + replay export
│ │ ├── SettingsMenu.js # Volume, difficulty, scanline toggle
│ │ ├── DifficultySelect.js # Difficulty selection screen
│ │ ├── SaveSlotPanel.js # 3-slot save/load/delete panel
│ │ ├── AchievementsPanel.js # Achievement browser
│ │ ├── LeaderboardPanel.js # Top 10 scores (DNF support)
│ │ ├── InitialsInput.js # 3-char name entry (with Escape cancel)
│ │ └── Tutorial.js # Complete contextual tutorial system
│ ├── story/ # Narrative system
│ │ ├── CutsceneManager.js # Dialog + animated sequences (camera pan, char move)
│ │ └── cutscenes.js # All cutscene data with animation steps
│ ├── systems/ # Game systems
│ │ ├── SaveManager.js # Multi-slot localStorage persistence
│ │ ├── ScoreManager.js # Score tracking + high scores
│ │ ├── AchievementManager.js # Achievement tracking + notifications
│ │ └── ReplayManager.js # Speedrun ghost recording, export/import
│ └── data/ # Configuration
│ ├── config.js # Game constants, colors, states, difficulty presets
│ ├── levels.js # All 12 level definitions + training level
│ └── achievements.js # Achievement definitions
| # | Name | Size | Enemies | Boss |
|---|---|---|---|---|
| 1 | Undergrid Sewers | 60×17 | 2 Sentinels | — |
| 2 | Pipeline Nexus | 70×17 | 3 Sentinels, 1 Drone | — |
| 3 | Neural Conduit | 80×20 | 4 Sentinels, 2 Drones | — |
| 4 | The Iron Maw | 30×17 | — | Warden Frame |
| # | Name | Size | Enemies | Boss |
|---|---|---|---|---|
| 5 | Neon Alleyways | 80×17 | 3 Sentinels, 2 Drones | — |
| 6 | Skybridge District | 90×20 | 2 Sentinels, 4 Drones, 1 Enforcer | — |
| 7 | Nexon Tower Lobby | 70×25 | 3 Sentinels, 3 Drones, 1 Enforcer | — |
| 8 | Data Spire | 40×30 | Mixed waves | Mini-boss |
| # | Name | Size | Enemies | Boss |
|---|---|---|---|---|
| 9 | Chromatic Depths | 80×20 | 4 Sentinels, 3 Drones, 2 Enforcers | — |
| 10 | The Firewall | 90×17 | 5 Drones, 2 Enforcers | — |
| 11 | AXIOM's Threshold | 100×20 | 3 each type (enhanced) | — |
| 12 | Protocol Zero | 40×25 | — | AXIOM Core |
Start a continuous run through all 12 levels with a persistent timer. Deaths restart the current level (timer continues). Level split times are compared against your personal best. No cutscenes, no saves — pure speed.
- Record: your input and position are automatically recorded each frame during a speedrun
- Toggle ghost: press G during gameplay to show/hide a semi-transparent cyan ghost of your best run
- Export replay: after completing a speedrun, choose "EXPORT REPLAY" to copy the replay JSON to your clipboard
- Import ghost: before starting a speedrun, choose "IMPORT GHOST" to paste a replay JSON and race against it
- Replay format: secure JSON envelope with HMAC-SHA256 integrity checksum, level/difficulty metadata, and frame-by-frame position data
- Validation: imported replays are strictly validated (type checks, size limits, frame bounds, checksum verification) — no code execution risk
21+ achievements across categories: Combat, Collection, Speed, Movement, Story, and Hidden. Examples:
- FIRST BLOOD: Defeat your first enemy
- GHOST IN THE MACHINE: Complete a level without taking damage
- CIRCUIT BREAKER: Defeat the Warden Frame
- NEON DRIFTER: Perform 100 wall slides
- PACIFIST (Hidden): Complete a level without killing any enemies
-
Clone the repository:
git clone https://github.com/q3ok/neonrift-shadow-protocol.git cd neonrift-shadow-protocol -
Serve the
publicdirectory with any static HTTP server:# Python cd public && python -m http.server 8000 # Node.js (npx) npx serve public # PHP php -S localhost:8000 -t public
-
Open
http://localhost:8000in Chrome or Firefox.
Note: The game uses ES6 modules, so it must be served via HTTP (not
file://).
The game auto-deploys to GitHub Pages on every push to main.
Workflow: .github/workflows/deploy-pages.yml
- Triggers: push to
main+ manual dispatch - Validates
public/index.htmlexists - Uploads
public/directory as Pages artifact - Deploys to GitHub Pages environment
Setup: Enable GitHub Pages in repository Settings → Pages → Source: "GitHub Actions"
Levels are defined in public/src/data/levels.js. Each level object contains:
{
name: "LEVEL NAME",
act: 1, // 1-3
width: 60, // tiles
height: 17, // tiles
bgTheme: "undergrid", // undergrid | midwire | spire
isBossLevel: false,
playerStart: { x: 48, y: 208 },
tiles: [...], // 2D array of tile IDs
entities: [
{ type: "sentinel", x: 320, y: 208, patrolRange: 96 },
{ type: "shard", x: 160, y: 192 },
{ type: "laser", x: 400, y: 144, direction: "horizontal" }
],
checkpoints: [{ x: 480, y: 208 }]
}Tile IDs: 0=air, 1=solid, 2=wall, 3=platform (one-way), 4=hazard, 5=ladder, 6=ledge, 7=decoration, 8=checkpoint, 9=exit
- Language: Vanilla JavaScript (ES6 modules)
- Rendering: Canvas 2D API
- Audio: Web Audio API (procedural generation)
- Storage: localStorage
- Build: None required (no bundler, no transpiler)
- Hosting: GitHub Pages (static)
| Browser | Supported |
|---|---|
| Chrome 90+ | ✅ |
| Firefox 90+ | ✅ |
| Edge 90+ | ✅ |
| Safari 15+ | ✅ |
| Mobile browsers |
See LICENSE for details.
