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
- WASD - Move your ship
- Mouse - Aim (ship points toward cursor)
- Auto-fire - Bullets fire automatically
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:
- +1 Health - Increase max health
- Upgrade Speed - Move faster
- Upgrade Bullet Speed - Reduce fire cooldown
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
- Basic - Small, fast, 1 HP
- Boss - Large, slower, 5 HP (spawns every 150 score)
Difficulty Scaling
The game gets harder over time:
- Enemy spawn rate increases every 500 frames (+1%)
- Enemy cap: 150 maximum on screen
- Bosses pause normal spawning until defeated
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:
- D-Pad - Virtual directional buttons for movement
- Joystick - Touch joystick for aiming
Mobile Detection
function checkMobileDevice() {
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i
.test(navigator.userAgent)) {
return true;
}
}
Technical Details
- Framework: p5.js
- Backend: Firebase Realtime Database (leaderboard)
- Audio: 7 music tracks + sound effects
- Rendering: 60 FPS target with FPS counter
- Input: Keyboard/mouse + mobile touch controls