function draw() {
background(10, 10, 30);
// Draw starfield
for (let star of stars) {
star.update();
star.display();
}
if (!modeSelected) {
drawModeSelection();
return;
}
if (!gameStarted) {
drawStartScreen();
return;
}
if (gameOver) {
drawGameOver();
return;
}
// Black hole mode effects
if (gameMode === 'BLACK-HOLE' && blackHole) {
blackHole.update();
blackHole.display();
}
// Boss warning effect
if (showBossWarning) {
bossWarningTimer++;
if (bossWarningTimer > 120) { // 2 seconds
showBossWarning = false;
bossWarningTimer = 0;
}
drawBossWarning();
}
// Update and display players
player1.update();
player1.display();
if (gameMode === '2P-COOP' || gameMode === '2P-VS' || gameMode === 'BLACK-HOLE') {
if (player2) {
player2.update();
player2.display();
}
}
// Update and display bullets
for (let i = bullets.length - 1; i >= 0; i--) {
bullets[i].update();
bullets[i].display();
if (bullets[i].offScreen()) {
bullets.splice(i, 1);
continue;
}
// Black hole gravity on bullets
if (gameMode === 'BLACK-HOLE' && blackHole) {
blackHole.applyGravity(bullets[i]);
if (blackHole.consumes(bullets[i])) {
bullets.splice(i, 1);
}
}
}
// Spawn enemies
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnRate) {
enemies.push(new Enemy());
enemySpawnTimer = 0;
// Increase difficulty
if (enemySpawnRate > 20) {
enemySpawnRate -= 0.3;
}
}
// Boss spawn logic (not in black hole mode)
if (gameMode !== 'BLACK-HOLE') {
bossSpawnTimer++;
if (bossSpawnTimer >= bossSpawnInterval - 120 && !showBossWarning && bosses.length === 0) {
showBossWarning = true;
playSound(bossSound, 80, 0.3, 200);
}
if (bossSpawnTimer >= bossSpawnInterval && bosses.length === 0) {
let bossType = floor(random(3));
bosses.push(new Boss(bossType));
bossSpawnTimer = 0;
showBossWarning = false;
bossWarningTimer = 0;
if (bossSpawnInterval > 600) {
bossSpawnInterval -= 100;
}
}
}
// Update and display bosses
for (let i = bosses.length - 1; i >= 0; i--) {
let target = player1;
if ((gameMode === '2P-COOP' || gameMode === '2P-VS') && player2) {
let dist1 = dist(bosses[i].x, bosses[i].y, player1.x, player1.y);
let dist2 = dist(bosses[i].x, bosses[i].y, player2.x, player2.y);
if (dist2 < dist1) target = player2;
}
bosses[i].update(target);
bosses[i].display();
if (bosses[i].hits(player1)) {
health1 -= 30;
playSound(hitSound, 220, 0.3, 150);
createExplosion(player1.x, player1.y, color(255, 100, 100));
bosses[i].takeDamage(20);
if (health1 <= 0) {
checkGameOver();
}
}
if ((gameMode === '2P-COOP' || gameMode === '2P-VS') && player2 && bosses[i].hits(player2)) {
health2 -= 30;
playSound(hitSound, 220, 0.3, 150);
createExplosion(player2.x, player2.y, color(255, 100, 100));
bosses[i].takeDamage(20);
if (health2 <= 0) {
checkGameOver();
}
}
for (let j = bullets.length - 1; j >= 0; j--) {
if (bosses[i].hits(bullets[j])) {
bosses[i].takeDamage(10);
if (gameMode === '2P-VS') {
if (bullets[j].owner === 1) score1 += 5;
else score2 += 5;
} else {
score1 += 5;
if (gameMode === '2P-COOP') score2 = score1;
}
playSound(hitSound, 300, 0.15, 40);
createExplosion(bullets[j].x, bullets[j].y, color(255, 200, 0));
bullets.splice(j, 1);
}
}
if (bosses[i].health <= 0) {
if (gameMode === '2P-VS') {
score1 += 200;
score2 += 200;
} else {
score1 += 200;
if (gameMode === '2P-COOP' || gameMode === 'BLACK-HOLE') score2 = score1;
}
playSound(explosionSound, 60, 0.5, 300);
createBigExplosion(bosses[i].x, bosses[i].y);
for (let k = 0; k < 3; k++) {
powerUps.push(new PowerUp(
bosses[i].x + random(-40, 40),
bosses[i].y + random(-40, 40)
));
}
bosses.splice(i, 1);
bossesDefeated++;
}
}
// Update and display enemies
for (let i = enemies.length - 1; i >= 0; i--) {
enemies[i].update();
enemies[i].display();
// Black hole gravity on enemies
if (gameMode === 'BLACK-HOLE' && blackHole) {
blackHole.applyGravity(enemies[i]);
if (blackHole.consumes(enemies[i])) {
createExplosion(enemies[i].x, enemies[i].y, color(150, 0, 255));
enemies.splice(i, 1);
continue;
}
}
if (enemies[i].hits(player1)) {
health1 -= 20;
playSound(hitSound, 220, 0.2, 100);
createExplosion(enemies[i].x, enemies[i].y, color(255, 100, 100));
enemies.splice(i, 1);
if (health1 <= 0) {
checkGameOver();
}
continue;
}
if ((gameMode === '2P-COOP' || gameMode === '2P-VS' || gameMode === 'BLACK-HOLE') && player2 && enemies[i].hits(player2)) {
health2 -= 20;
playSound(hitSound, 220, 0.2, 100);
createExplosion(enemies[i].x, enemies[i].y, color(255, 100, 100));
enemies.splice(i, 1);
if (health2 <= 0) {
checkGameOver();
}
continue;
}
for (let j = bullets.length - 1; j >= 0; j--) {
if (enemies[i].hits(bullets[j])) {
if (gameMode === '2P-VS') {
if (bullets[j].owner === 1) score1 += 10;
else score2 += 10;
} else {
score1 += 10;
if (gameMode === '2P-COOP' || gameMode === 'BLACK-HOLE') score2 = score1;
}
playSound(explosionSound, 100, 0.3, 80);
createExplosion(enemies[i].x, enemies[i].y, color(255, 150, 0));
if (gameMode !== 'SURVIVAL' && random() < 0.15) {
powerUps.push(new PowerUp(enemies[i].x, enemies[i].y));
}
enemies.splice(i, 1);
bullets.splice(j, 1);
break;
}
}
if (i >= 0 && enemies[i] && enemies[i].offScreen()) {
enemies.splice(i, 1);
}
}
// Update and display power-ups
for (let i = powerUps.length - 1; i >= 0; i--) {
powerUps[i].update();
powerUps[i].display();
// Black hole gravity on power-ups
if (gameMode === 'BLACK-HOLE' && blackHole) {
blackHole.applyGravity(powerUps[i]);
if (blackHole.consumes(powerUps[i])) {
powerUps.splice(i, 1);
continue;
}
}
let collected = false;
if (powerUps[i].hits(player1)) {
health1 = min(100, health1 + 30);
if (gameMode === '2P-VS') score1 += 50;
else score1 += 50;
collected = true;
}
if ((gameMode === '2P-COOP' || gameMode === '2P-VS' || gameMode === 'BLACK-HOLE') && player2 && powerUps[i].hits(player2)) {
health2 = min(100, health2 + 30);
if (gameMode === '2P-VS') score2 += 50;
else score2 += 50;
collected = true;
}
if (collected) {
playSound(powerUpSound, 660, 0.2, 100);
createExplosion(powerUps[i].x, powerUps[i].y, color(100, 255, 100));
powerUps.splice(i, 1);
} else if (powerUps[i].offScreen()) {
powerUps.splice(i, 1);
}
}
// Update and display particles
for (let i = particles.length - 1; i >= 0; i--) {
particles[i].update();
particles[i].display();
if (particles[i].isDead()) {
particles.splice(i, 1);
}
}
// Check if players are consumed by black hole
if (gameMode === 'BLACK-HOLE' && blackHole) {
blackHole.applyGravity(player1);
if (blackHole.consumes(player1)) {
health1 = 0;
checkGameOver();
}
if (player2) {
blackHole.applyGravity(player2);
if (blackHole.consumes(player2)) {
health2 = 0;
checkGameOver();
}
}
}
// Draw UI
drawUI();
}