Marvyn Bailly

PhD Candidate in Applied Mathematics & Scientific Computation

PewPewPew

An Asteroids-Inspired Arcade Game

PewPewPew is a fast-paced arcade shooter built with p5.js. Survive waves of enemies, collect power-ups, defeat bosses, and climb the global leaderboard. Features custom music, mobile support, and an RPG-style upgrade system.

Special thanks to my friend Uriah Barzola for creating the amazing menu art! It is my fault that the resolution is wrong on the image.

Gameplay

Controls

Objective

Survive as long as possible while destroying enemies. Each kill increases your score and contributes to your level progress. Every 150 points spawns a boss fight!

The Player

The player ship is more than just a triangle - it's a full RPG character with health, levels, and temporary power-up states.

Player Properties

class player {
    constructor(x, y) {
        this.pos = createVector(x, y);
        this.vel = createVector(0, 0);
        this.heading = 0;
        this.maxSpeed = 5;
        this.health = 3;
        this.alive = true;
        
        // Power-up states
        this.shield = false;
        this.minigun = false;
        this.multishot = false;
        
        // Leveling system
        this.level = 1;
        this.levelMax = 10;
        this.levelProgress = 0;
        
        // Invincibility frames after upgrade
        this.invincible = false;
    }
}

Level-Up System

Kill enemies to fill your level bar. When it's full, the game pauses and you choose an upgrade:

Each level requires more kills than the last: levelMax = 10 + 2 × level

Power-Ups

Six different power-ups spawn randomly throughout the game:

Power-Up Effect
❤️ Health Pack +1 Health
🛡️ Shield Absorb one hit without losing health
🔫 Minigun Continuous rapid fire for 250 frames (with recoil!)
🔱 Multishot Fire 3 bullets in a spread pattern for 500 frames
💥 Nuke Instantly destroy all enemies on screen
❄️ Freeze Stop all enemy movement for 200 frames

Power-Up Implementation

action(player) {
    if (this.type.Name == "Nuke") {
        let scoreIncrease = enemies.length;
        enemies = [];  // Clear all enemies
        score += scoreIncrease;
        
        // Level up for each kill
        for (let i = 0; i < scoreIncrease; i++) {
            ship.levelUp('enemy');
        }
    }
}

Enemy AI

Enemies use steering behaviors to chase the player. The arrive() function implements smooth pursuit:

Steering Behavior

arrive(target) {
    // Calculate desired velocity toward target
    let desired = p5.Vector.sub(target, this.pos);
    desired.setMag(this.maxspeed);
    
    // Steering = desired - current velocity
    let steer = p5.Vector.sub(desired, this.velocity);
    steer.limit(this.maxforce);
    
    this.applyForce(steer);
}

Enemy Types

Difficulty Scaling

The game gets harder over time:

Minigun Physics

The minigun power-up includes realistic recoil - continuous fire pushes the ship backward!

Recoil Implementation

if (ship.minigun) {
    // Fire bullet with slight random spread
    bullets.push(new Bullet(
        ship.pos.x, ship.pos.y,
        ship.heading + random(-0.1, 0.1)
    ));
    
    // Calculate opposite direction for knockback
    let oppDir = p5.Vector.fromAngle(ship.heading + PI);
    oppDir.normalize();
    
    // More recoil with multishot active
    if (ship.multishot) {
        oppDir.mult(0.75);
    } else {
        oppDir.mult(0.25);
    }
    
    ship.move(oppDir);
}

Global Leaderboard

The game features a Firebase-powered global leaderboard. When you die, you can submit your score with a username.

Score Submission

function submitScore() {
    var data = {
        name: initUsername.value(),
        score: score
    }
    ref.push(data);
    
    // Hide to prevent multiple entries
    submitButton.hide();
    initUsername.hide();
}

Music System

Seven original music tracks play randomly during gameplay:

Random Track Selection

function playMusic() {
    if (currentTrack == null) {
        currentTrack = getRandomSong();
    }
    if (!currentTrack.isPlaying()) {
        currentTrack = getRandomSong();
        currentTrack.play();
    }
}

function getRandomSong() {
    return tracks[Math.floor(Math.random() * tracks.length)];
}

Mobile Support

The game detects mobile devices and provides touch controls:

Mobile Detection

function checkMobileDevice() {
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i
        .test(navigator.userAgent)) {
        return true;
    }
}

Technical Details

Play Now