A fast-paced geometric survival shooter built with a modular, data-driven architecture.
The game's controls are the following:
- Move:
W,A,S,Dor arrow keys - Fire:
Left ClickorF - Cycle Guns:
QandE - Reload:
V(or empty magazine) - Pause:
PorEscape(while playing) - Toggle Gamemode:
H(while paused or in main menu) - Restart:
R(while paused/choosing/dead) - Main Menu:
M(while paused/choosing/dead)
- Frame-Independent Logic: Integrated a global
timeScale(Delta Time) system. Game speed, movement, and animations now remain consistent across all monitor refresh rates (60Hz, 144Hz, 240Hz+). - Survival Mechanics:
- Invincibility Frames (I-Frames): Taking damage now triggers a brief window of invulnerability, preventing "shotgunning" (dying instantly to multiple overlapping hitboxes).
- Defensive Knockback: Taking damage generates a localized shockwave that pushes nearby enemies away, providing critical breathing room in tight situations.
- Hardcore Mode: A new gamemode with reduced player HP and more aggressive enemies. Rewards players with a 2x Score Multiplier.
- Collision Engine 2.0:
- Fire Pool Integration: lingering AOE fire pools are now processed through the spatial grid, drastically reducing the performance hit during late-game chaos.
- Squared Distance Calculations: Replaced expensive square root operations with squared distance checks for all proximity and collision logic, resulting in a significant CPU performance boost.
- Combat Synchronization: Refined the game clock and attack timers to ensure enemy aggression and weapon fire rates are perfectly telegraphed and consistent regardless of frame rate fluctuations.
- Mobile Polish: Retained all v1.13 features (Robust detection, vertical choice menus, and adaptive UI) with improved joystick lerping and bug fixes for auto-fire behavior.
The project utilizes a centralized state object (defined in main.js) to manage all core modules. This reduces reliance on the global scope and ensures a clean data flow.
- Standardized Resets: Every game module (
player,guns,mobs, etc.) implements adefaultsgetter and areset()method. Callingstate.resetAll()performs anObject.assignto restore the game to its pristine initial state. - Constructor Encapsulation: All game entities (Players, Mobs, Bullets) receive the
statereference in their constructor, allowing them to interact with other systems (likesimulationorupgrades) safely.
The simulation now calculates dt using high-resolution timestamps from requestAnimationFrame. This dt is normalized into a timeScale factor (target 1.0 @ 60fps) that is passed to every update() call in the game. This ensures that a projectile moving at speed X covers the same physical distance per second, whether the game is rendering 30 or 300 frames per second.
- Supabase Integration: The game communicates with a Supabase backend to store and retrieve high scores.
- Persistent Profile: Usernames are stored in
localStorage, allowing for automatic identification without interruptive popups. - Async Feedback: The death screen utilizes a reactive status message system to inform players of the leaderboard submission progress.
- Property Protection: Implemented defensive setters for
velocity,damageDone, andfireRate. These setters automatically "un-multiply" temporary buffs before applying permanent upgrades, preventing exponential stat leakage.
- Context Filtering: Utilizes
draw.filterto apply real-time desaturation to the game world based on player health or death state without affecting the UI layer.
- Timed Buff Management: Power-up durations (like Invulnerability) are calculated against
simulation.timerather than real-world time. This ensures that durations are preserved when the game is paused or when the player is in a choice menu.
- Threshold System: Difficulty tiers are triggered based on the
currentlevel number. - Dynamic Formulas: Spawn counts support both static integers and string-based formulas (e.g.,
"c - 10") which are interpreted at runtime.
The game features a difficulty slider in the Settings menu ranging from 0.2x to 5.0x.
- Probabilistic Spawning: To handle fractional multipliers (e.g., spawning 0.3 mobs), the engine uses a weighted random roll. This ensures that statistically, the average number of spawns matches the selected difficulty over time.
- Melee (Knife): A high-damage sweeping attack with a visual fade-out slash.
- Ballistics: A wide variety of weapons including Rifles, Snipers, Shotguns, and Miniguns.
- Specialty: Homing Missiles that accelerate towards their target, Balls 😋, Flamethrowers, and instant-hit Lasers.
- Steering Guidance: Homing projectiles use a steering-force algorithm rather than direct angle assignment, allowing for natural arc-based movement.
The upgrade system supports prerequisites via a requirements property. Notable mechanics include:
- Vampirism: Heal a percentage of damage dealt to enemies.
- Napalm: Flamethrower projectiles leave lingering AOE fire pools.
- Cluster Bombs: Explosive weapons trigger secondary sub-explosions.
- Incendiary Munitions: Standard bullets gain explosive properties upon contact.
- Iron Will: Multiplies the base duration of invulnerability power-ups.
- Reinforced Shields: Increases the effectiveness/magnitude of shield power-ups.
- Default: Standard melee units.
- Sentry: Stationary turrets that fire glowing red projectiles with trail effects.
- Tank: High health, high damage, but slow movement.
- Archer/Grenadier: Ranged units that use predictive aiming.
- Bosses: Unique entities like the Pentagon Boss (laser telegraphs) and Void Boss (gravitational pull).
- Ghost Boss: A spectral entity that phases between states, becoming invulnerable to damage.
- Collision Grid: A spatial partitioning grid (100px cells) optimizes collision checks. Includes defensive boundary checks to prevent
TypeErrorduring coordinate queries. - Performance Optimization: Beyond the grid, the engine utilizes Squared Distance checks (
dx*dx + dy*dy <= r*r) for most proximity logic, avoiding the computational cost ofMath.sqrt()millions of times per minute. - Visual Polish:
- Geometric Background: A low-opacity grid rendered in the simulation background to provide a frame of reference for player movement.
- Muzzle Flashes: Triggered on weapon fire.
- Particle System: Manages lifesteal tracers, smoke trails for missiles, particle ribbons for bouncy balls, and more.
- Shadow Glow: Used on projectiles and the player for a "bullet-hell" aesthetic, with color shifting based on projectile speed.
- Persistence: Settings are automatically saved to
localStorageand persist across sessions.
- Eliel-isCool47: Art, Code, Game Design.
- Project URL: github.com/Eliel-isCool47/Tetragon
- Feedback Link: https://forms.gle/xokJpH3U76hHibot7
The game loop runs at a fixed 60 FPS. All rendering is performed on a single HTML5 Canvas context. To modify levels or balancing, edit levels.json or the defaults getters within individual JS files.
- Gun Sprites: The gun sprites haven't been in the game since February 15th, so I might reädd them in the future. It's not guaranteed, nor likely, that they return.