19-de-mar-o-de-2025 / index.html
Xacodavt's picture
Add 3 files
76eaf9e verified
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cosmic Defender PRO</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.pulse { animation: pulse 1.5s infinite; }
.star {
position: absolute;
background: white;
border-radius: 50%;
animation: twinkle var(--duration) infinite ease-in-out;
}
@keyframes twinkle {
0%, 100% { opacity: 0.2; }
50% { opacity: 1; }
}
#gameCanvas {
box-shadow: 0 0 30px rgba(0, 100, 255, 0.5);
border-radius: 10px;
}
.explosion {
position: absolute;
width: 40px;
height: 40px;
background: radial-gradient(circle, yellow, orange, red);
border-radius: 50%;
opacity: 0;
transform: scale(0);
animation: explode 0.5s forwards;
}
@keyframes explode {
0% { transform: scale(0); opacity: 1; }
100% { transform: scale(3); opacity: 0; }
}
.powerup {
position: absolute;
width: 20px;
height: 20px;
background: radial-gradient(circle, #10b981, #047857);
border-radius: 50%;
animation: float 2s infinite ease-in-out;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.shield {
position: absolute;
width: 60px;
height: 60px;
border: 2px dashed rgba(59, 130, 246, 0.7);
border-radius: 50%;
animation: shieldPulse 2s infinite;
}
@keyframes shieldPulse {
0%, 100% { transform: scale(1); opacity: 0.7; }
50% { transform: scale(1.1); opacity: 0.4; }
}
.boss-health {
height: 20px;
background: linear-gradient(to right, #ef4444, #f59e0b);
border-radius: 10px;
transition: width 0.3s;
}
</style>
</head>
<body class="bg-gray-900 text-white flex flex-col items-center justify-center min-h-screen p-4 overflow-hidden">
<!-- Background Elements -->
<div class="absolute inset-0 overflow-hidden">
<div id="stars"></div>
</div>
<!-- Game UI -->
<div class="z-10 w-full max-w-4xl">
<!-- Header -->
<header class="flex justify-between items-center mb-4">
<div class="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-600">
COSMIC DEFENDER <span class="text-xs bg-blue-600 text-white px-2 py-1 rounded">PRO</span>
</div>
<div class="flex space-x-6">
<div class="text-lg font-mono">
<i class="fas fa-star text-yellow-400 mr-1"></i> <span id="score">0</span>
</div>
<div class="text-lg font-mono">
<i class="fas fa-heart text-red-500 mr-1"></i> <span id="lives">3</span>
</div>
<div class="text-lg font-mono">
<i class="fas fa-bolt text-yellow-400 mr-1"></i> <span id="level">1</span>
</div>
</div>
</header>
<!-- Game Container -->
<div class="relative">
<canvas id="gameCanvas" width="800" height="600" class="w-full border-2 border-blue-500"></canvas>
<!-- Start Screen -->
<div id="startScreen" class="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-90 rounded-lg p-6 text-center">
<h2 class="text-5xl font-bold mb-2 bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-600">
COSMIC DEFENDER PRO
</h2>
<p class="text-xl mb-8 text-gray-300">Defend the galaxy from alien invasion!</p>
<div class="grid grid-cols-2 gap-8 mb-8">
<div class="bg-gray-800 p-4 rounded-lg">
<h3 class="text-blue-400 font-semibold mb-2"><i class="fas fa-gamepad mr-2"></i>Controls</h3>
<ul class="text-left space-y-2">
<li><i class="fas fa-arrow-left mr-2 text-blue-400"></i> Move Left</li>
<li><i class="fas fa-arrow-right mr-2 text-blue-400"></i> Move Right</li>
<li><i class="fas fa-space-shuttle mr-2 text-blue-400"></i> Shoot (Space)</li>
<li><i class="fas fa-bolt mr-2 text-blue-400"></i> Special (Shift)</li>
</ul>
</div>
<div class="bg-gray-800 p-4 rounded-lg">
<h3 class="text-purple-400 font-semibold mb-2"><i class="fas fa-trophy mr-2"></i>Powerups</h3>
<ul class="text-left space-y-2">
<li><span class="w-3 h-3 bg-green-500 rounded-full inline-block mr-2"></span> Health</li>
<li><span class="w-3 h-3 bg-blue-500 rounded-full inline-block mr-2"></span> Shield</li>
<li><span class="w-3 h-3 bg-yellow-500 rounded-full inline-block mr-2"></span> Rapid Fire</li>
<li><span class="w-3 h-3 bg-red-500 rounded-full inline-block mr-2"></span> Nuke</li>
</ul>
</div>
</div>
<div class="flex space-x-4">
<button id="startBtn" class="px-8 py-3 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 rounded-lg text-xl font-semibold transition-all pulse">
<i class="fas fa-play mr-2"></i>Start Mission
</button>
<button id="settingsBtn" class="px-8 py-3 bg-gray-700 hover:bg-gray-600 rounded-lg text-xl font-semibold transition-all">
<i class="fas fa-cog mr-2"></i>Settings
</button>
</div>
</div>
<!-- Game Over Screen -->
<div id="gameOver" class="hidden absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-90 rounded-lg p-6">
<h2 class="text-5xl font-bold text-red-500 mb-4">MISSION FAILED</h2>
<div class="bg-gray-800 p-6 rounded-lg mb-6 w-64">
<div class="text-2xl font-mono mb-2">Score: <span id="finalScore">0</span></div>
<div class="text-lg mb-4">Level Reached: <span id="finalLevel">1</span></div>
<div class="text-lg">Enemies Defeated: <span id="enemiesDefeated">0</span></div>
</div>
<div class="flex space-x-4">
<button id="restartBtn" class="px-6 py-2 bg-blue-600 hover:bg-blue-700 rounded-lg text-lg font-semibold transition-all">
<i class="fas fa-redo mr-2"></i>Retry
</button>
<button id="menuBtn" class="px-6 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg text-lg font-semibold transition-all">
<i class="fas fa-home mr-2"></i>Main Menu
</button>
</div>
</div>
<!-- Pause Screen -->
<div id="pauseScreen" class="hidden absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-90 rounded-lg">
<h2 class="text-4xl font-bold text-yellow-400 mb-6">MISSION PAUSED</h2>
<button id="resumeBtn" class="px-8 py-3 bg-green-600 hover:bg-green-700 rounded-lg text-xl font-semibold transition-all mb-4">
<i class="fas fa-play mr-2"></i>Resume
</button>
<button id="quitBtn" class="px-8 py-3 bg-gray-700 hover:bg-gray-600 rounded-lg text-xl font-semibold transition-all">
<i class="fas fa-sign-out-alt mr-2"></i>Quit Mission
</button>
</div>
<!-- Boss Health Bar -->
<div id="bossHealthContainer" class="hidden absolute top-4 left-1/2 transform -translate-x-1/2 w-64 bg-gray-800 rounded-lg p-2">
<div class="text-center text-yellow-400 font-bold mb-1">BOSS</div>
<div class="boss-health" id="bossHealthBar"></div>
</div>
</div>
<!-- Footer -->
<footer class="mt-4 text-center text-gray-500 text-sm">
<p>Use arrow keys to move, SPACE to shoot, SHIFT for special attack | P to pause</p>
<p class="mt-1">© 2023 Cosmic Defender PRO | All rights reserved</p>
</footer>
</div>
<script>
// =============================================
// GAME INITIALIZATION
// =============================================
// Create stars background
const starsContainer = document.getElementById('stars');
for (let i = 0; i < 200; i++) {
const star = document.createElement('div');
star.className = 'star';
star.style.left = `${Math.random() * 100}%`;
star.style.top = `${Math.random() * 100}%`;
star.style.width = `${Math.random() * 3}px`;
star.style.height = star.style.width;
star.style.setProperty('--duration', `${2 + Math.random() * 3}s`);
starsContainer.appendChild(star);
}
// Game canvas setup
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
// UI Elements
const scoreDisplay = document.getElementById('score');
const finalScoreDisplay = document.getElementById('finalScore');
const livesDisplay = document.getElementById('lives');
const levelDisplay = document.getElementById('level');
const finalLevelDisplay = document.getElementById('finalLevel');
const enemiesDefeatedDisplay = document.getElementById('enemiesDefeated');
const gameOverScreen = document.getElementById('gameOver');
const startScreen = document.getElementById('startScreen');
const pauseScreen = document.getElementById('pauseScreen');
const bossHealthContainer = document.getElementById('bossHealthContainer');
const bossHealthBar = document.getElementById('bossHealthBar');
// Buttons
const startBtn = document.getElementById('startBtn');
const restartBtn = document.getElementById('restartBtn');
const menuBtn = document.getElementById('menuBtn');
const resumeBtn = document.getElementById('resumeBtn');
const quitBtn = document.getElementById('quitBtn');
const settingsBtn = document.getElementById('settingsBtn');
// =============================================
// GAME STATE
// =============================================
// Player
let player = {
x: canvas.width / 2 - 25,
y: canvas.height - 80,
w: 50,
h: 60,
speed: 5,
fireRate: 300, // ms between shots
lastShot: 0,
specialCharge: 0,
maxSpecial: 100,
hasShield: false,
shieldTimer: 0,
rapidFire: false,
rapidFireTimer: 0
};
// Game objects
let shots = [];
let enemies = [];
let powerups = [];
let explosions = [];
let particles = [];
let boss = null;
// Game state
let score = 0;
let lives = 3;
let level = 1;
let enemiesDefeated = 0;
let gameOver = false;
let gameStarted = false;
let gamePaused = false;
let keys = {};
let enemySpawnRate = 1500; // ms
let enemySpeed = 2;
let lastEnemySpawn = 0;
let lastPowerupSpawn = 0;
let powerupSpawnRate = 10000; // ms
let backgroundOffset = 0;
let parallaxStars = [];
// Create parallax stars
for (let i = 0; i < 100; i++) {
parallaxStars.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: Math.random() * 3,
speed: 0.5 + Math.random() * 2,
alpha: 0.2 + Math.random() * 0.8
});
}
// =============================================
// EVENT LISTENERS
// =============================================
document.addEventListener('keydown', (e) => {
keys[e.key] = true;
// Start game with space if not started
if (e.key === ' ' && !gameStarted && !gameOver) {
startGame();
}
// Pause game
if (e.key === 'p' && gameStarted && !gameOver) {
togglePause();
}
});
document.addEventListener('keyup', (e) => {
keys[e.key] = false;
});
// Button event listeners
startBtn.addEventListener('click', startGame);
restartBtn.addEventListener('click', restartGame);
menuBtn.addEventListener('click', returnToMenu);
resumeBtn.addEventListener('click', togglePause);
quitBtn.addEventListener('click', returnToMenu);
settingsBtn.addEventListener('click', () => {
alert('Settings will be available in the next update!');
});
// =============================================
// GAME FUNCTIONS
// =============================================
function startGame() {
gameStarted = true;
gameOver = false;
startScreen.classList.add('hidden');
resetGame();
gameLoop();
}
function restartGame() {
gameOver = false;
gameOverScreen.classList.add('hidden');
resetGame();
gameLoop();
}
function returnToMenu() {
gameOver = false;
gamePaused = false;
gameOverScreen.classList.add('hidden');
pauseScreen.classList.add('hidden');
startScreen.classList.remove('hidden');
}
function togglePause() {
gamePaused = !gamePaused;
if (gamePaused) {
pauseScreen.classList.remove('hidden');
} else {
pauseScreen.classList.add('hidden');
}
}
function resetGame() {
// Reset player
player = {
x: canvas.width / 2 - 25,
y: canvas.height - 80,
w: 50,
h: 60,
speed: 5,
fireRate: 300,
lastShot: 0,
specialCharge: 0,
maxSpecial: 100,
hasShield: false,
shieldTimer: 0,
rapidFire: false,
rapidFireTimer: 0
};
// Reset game objects
shots = [];
enemies = [];
powerups = [];
explosions = [];
particles = [];
boss = null;
bossHealthContainer.classList.add('hidden');
// Reset game state
score = 0;
lives = 3;
level = 1;
enemiesDefeated = 0;
enemySpawnRate = 1500;
enemySpeed = 2;
lastEnemySpawn = 0;
lastPowerupSpawn = 0;
powerupSpawnRate = 10000;
// Update UI
updateUI();
}
function updateUI() {
scoreDisplay.textContent = score;
livesDisplay.textContent = lives;
levelDisplay.textContent = level;
finalScoreDisplay.textContent = score;
finalLevelDisplay.textContent = level;
enemiesDefeatedDisplay.textContent = enemiesDefeated;
}
function createExplosion(x, y, size = 1) {
// Create visual explosion
const explosion = document.createElement('div');
explosion.className = 'explosion';
explosion.style.left = `${x - 20}px`;
explosion.style.top = `${y - 20}px`;
explosion.style.transform = `scale(${size})`;
document.body.appendChild(explosion);
// Remove after animation
setTimeout(() => {
explosion.remove();
}, 500);
// Create particles
for (let i = 0; i < 15 * size; i++) {
particles.push({
x: x,
y: y,
size: 2 + Math.random() * 3 * size,
color: `hsl(${Math.random() * 30 + 10}, 100%, 50%)`,
speedX: -5 + Math.random() * 10,
speedY: -5 + Math.random() * 10,
life: 30 + Math.random() * 30
});
}
}
function spawnEnemy() {
const now = Date.now();
if (now - lastEnemySpawn < enemySpawnRate || gameOver || gamePaused) return;
lastEnemySpawn = now;
// Every 5 levels, spawn a boss
if (level % 5 === 0 && !boss) {
spawnBoss();
return;
}
// Regular enemies
const colors = ['#ef4444', '#f97316', '#ec4899', '#8b5cf6'];
const types = ['basic', 'fast', 'tank', 'shooter'];
const type = types[Math.floor(Math.random() * types.length)];
let enemy = {
x: Math.random() * (canvas.width - 40),
y: -40,
w: 40,
h: 40,
color: colors[Math.floor(Math.random() * colors.length)],
type: type,
health: type === 'tank' ? 3 : 1,
speed: enemySpeed * (type === 'fast' ? 1.5 : 1),
lastShot: 0,
canShoot: type === 'shooter'
};
enemies.push(enemy);
}
function spawnBoss() {
boss = {
x: canvas.width / 2 - 100,
y: -150,
w: 200,
h: 150,
color: '#dc2626',
health: 10 + level * 2,
maxHealth: 10 + level * 2,
speed: enemySpeed * 0.7,
phase: 1,
lastShot: 0,
pattern: 'down',
moveTimer: 0
};
bossHealthContainer.classList.remove('hidden');
updateBossHealth();
}
function updateBossHealth() {
const percent = (boss.health / boss.maxHealth) * 100;
bossHealthBar.style.width = `${percent}%`;
}
function spawnPowerup() {
const now = Date.now();
if (now - lastPowerupSpawn < powerupSpawnRate || gameOver || gamePaused) return;
lastPowerupSpawn = now;
const types = ['health', 'shield', 'rapidfire', 'nuke'];
const type = types[Math.floor(Math.random() * types.length)];
powerups.push({
x: Math.random() * (canvas.width - 20),
y: -20,
w: 20,
h: 20,
type: type,
color: type === 'health' ? '#10b981' :
type === 'shield' ? '#3b82f6' :
type === 'rapidfire' ? '#f59e0b' : '#ef4444',
speed: 2
});
}
function activatePowerup(powerup) {
switch(powerup.type) {
case 'health':
lives = Math.min(5, lives + 1);
createExplosion(powerup.x + powerup.w/2, powerup.y + powerup.h/2, 0.5);
break;
case 'shield':
player.hasShield = true;
player.shieldTimer = 10000; // 10 seconds
createExplosion(powerup.x + powerup.w/2, powerup.y + powerup.h/2, 0.5);
break;
case 'rapidfire':
player.rapidFire = true;
player.rapidFireTimer = 8000; // 8 seconds
player.fireRate = 100;
createExplosion(powerup.x + powerup.w/2, powerup.y + powerup.h/2, 0.5);
break;
case 'nuke':
// Destroy all enemies
enemies.forEach(enemy => {
createExplosion(enemy.x + enemy.w/2, enemy.y + enemy.h/2, 1.5);
score += 10 * level;
enemiesDefeated++;
});
enemies = [];
if (boss) {
boss.health -= 5;
updateBossHealth();
createExplosion(boss.x + boss.w/2, boss.y + boss.h/2, 3);
if (boss.health <= 0) {
defeatBoss();
}
}
break;
}
updateUI();
}
function defeatBoss() {
createExplosion(boss.x + boss.w/2, boss.y + boss.h/2, 4);
score += 500 * level;
enemiesDefeated++;
boss = null;
bossHealthContainer.classList.add('hidden');
level++;
enemySpawnRate = Math.max(500, enemySpawnRate - 100);
enemySpeed = Math.min(6, enemySpeed + 0.3);
updateUI();
}
function shoot() {
const now = Date.now();
if (now - player.lastShot < player.fireRate) return;
player.lastShot = now;
// Main shot
shots.push({
x: player.x + player.w/2 - 2,
y: player.y,
w: 4,
h: 15,
color: '#10b981',
speed: 8,
damage: 1
});
// Side shots when special is charged
if (player.specialCharge >= player.maxSpecial) {
player.specialCharge = 0;
// Left shot
shots.push({
x: player.x + 10,
y: player.y + 20,
w: 6,
h: 20,
color: '#3b82f6',
speed: 10,
damage: 2,
angle: -0.2
});
// Right shot
shots.push({
x: player.x + player.w - 16,
y: player.y + 20,
w: 6,
h: 20,
color: '#3b82f6',
speed: 10,
damage: 2,
angle: 0.2
});
}
}
function specialAttack() {
if (player.specialCharge < player.maxSpecial) return;
player.specialCharge = 0;
// Create a powerful wave attack
for (let i = 0; i < 10; i++) {
shots.push({
x: player.x + player.w/2 - 3 + (i * 6) - 27,
y: player.y,
w: 6,
h: 25,
color: '#ec4899',
speed: 12,
damage: 3
});
}
}
function enemyShoot(enemy) {
const now = Date.now();
if (now - enemy.lastShot < 2000 || !enemy.canShoot) return;
enemy.lastShot = now;
shots.push({
x: enemy.x + enemy.w/2 - 3,
y: enemy.y + enemy.h,
w: 6,
h: 15,
color: '#ef4444',
speed: -5,
damage: 1,
isEnemy: true
});
}
function bossShoot() {
const now = Date.now();
if (now - boss.lastShot < 1000) return;
boss.lastShot = now;
// Pattern based on boss phase
if (boss.phase === 1) {
// Single shot
shots.push({
x: boss.x + boss.w/2 - 5,
y: boss.y + boss.h,
w: 10,
h: 25,
color: '#ef4444',
speed: -4,
damage: 2,
isEnemy: true
});
} else if (boss.phase === 2) {
// Triple shot
for (let i = 0; i < 3; i++) {
shots.push({
x: boss.x + boss.w/2 - 5 + (i * 15) - 15,
y: boss.y + boss.h,
w: 10,
h: 25,
color: '#ef4444',
speed: -4,
damage: 2,
isEnemy: true,
angle: (i - 1) * 0.2
});
}
} else {
// Spread shot
for (let i = 0; i < 5; i++) {
shots.push({
x: boss.x + boss.w/2 - 5 + (i * 15) - 30,
y: boss.y + boss.h,
w: 10,
h: 25,
color: '#ef4444',
speed: -4,
damage: 2,
isEnemy: true,
angle: (i - 2) * 0.15
});
}
}
}
function checkCollisions() {
// Player with enemies
enemies.forEach((enemy, i) => {
if (collision(player, enemy)) {
if (player.hasShield) {
player.hasShield = false;
player.shieldTimer = 0;
} else {
lives--;
if (lives <= 0) {
gameOver = true;
}
}
createExplosion(enemy.x + enemy.w/2, enemy.y + enemy.h/2);
enemies.splice(i, 1);
updateUI();
}
});
// Player with boss
if (boss && collision(player, boss)) {
if (player.hasShield) {
player.hasShield = false;
player.shieldTimer = 0;
} else {
lives -= 2;
if (lives <= 0) {
gameOver = true;
}
}
createExplosion(boss.x + boss.w/2, boss.y + boss.h/2, 2);
updateUI();
}
// Player with enemy shots
shots.forEach((shot, i) => {
if (shot.isEnemy && collision(player, shot)) {
if (player.hasShield) {
player.hasShield = false;
player.shieldTimer = 0;
} else {
lives--;
if (lives <= 0) {
gameOver = true;
}
}
shots.splice(i, 1);
updateUI();
}
});
// Player with powerups
powerups.forEach((powerup, i) => {
if (collision(player, powerup)) {
activatePowerup(powerup);
powerups.splice(i, 1);
}
});
// Player shots with enemies
shots.forEach((shot, i) => {
if (!shot.isEnemy) {
enemies.forEach((enemy, j) => {
if (collision(shot, enemy)) {
enemy.health -= shot.damage;
shots.splice(i, 1);
if (enemy.health <= 0) {
createExplosion(enemy.x + enemy.w/2, enemy.y + enemy.h/2);
enemies.splice(j, 1);
score += 10 * level;
enemiesDefeated++;
// Chance to drop powerup
if (Math.random() < 0.1) {
spawnPowerup();
}
}
updateUI();
}
});
// Player shots with boss
if (boss && collision(shot, boss)) {
boss.health -= shot.damage;
shots.splice(i, 1);
updateBossHealth();
// Boss phase changes
if (boss.health <= boss.maxHealth * 0.66 && boss.phase === 1) {
boss.phase = 2;
boss.speed *= 1.2;
} else if (boss.health <= boss.maxHealth * 0.33 && boss.phase === 2) {
boss.phase = 3;
boss.speed *= 1.2;
} else if (boss.health <= 0) {
defeatBoss();
}
}
}
});
}
function collision(a, b) {
return a.x < b.x + b.w &&
a.x + a.w > b.x &&
a.y < b.y + b.h &&
a.y + a.h > b.y;
}
function updateGameObjects() {
// Update player
if (keys['ArrowLeft'] || keys['a']) player.x -= player.speed;
if (keys['ArrowRight'] || keys['d']) player.x += player.speed;
if (keys[' ']) shoot();
if (keys['Shift']) specialAttack();
// Keep player in bounds
player.x = Math.max(0, Math.min(canvas.width - player.w, player.x));
// Update special charge
if (player.specialCharge < player.maxSpecial) {
player.specialCharge += 0.2;
}
// Update shield timer
if (player.hasShield) {
player.shieldTimer -= 16; // Assuming 60fps
if (player.shieldTimer <= 0) {
player.hasShield = false;
}
}
// Update rapid fire timer
if (player.rapidFire) {
player.rapidFireTimer -= 16;
if (player.rapidFireTimer <= 0) {
player.rapidFire = false;
player.fireRate = 300;
}
}
// Update shots
shots.forEach((shot, i) => {
// Apply angle if exists
if (shot.angle) {
shot.x += Math.sin(shot.angle) * 3;
}
shot.y -= shot.speed;
// Remove if out of bounds
if (shot.y < -shot.h || shot.y > canvas.height) {
shots.splice(i, 1);
}
});
// Update enemies
enemies.forEach((enemy, i) => {
enemy.y += enemy.speed;
// Enemy shooting
if (enemy.canShoot && Math.random() < 0.02) {
enemyShoot(enemy);
}
// Remove if out of bounds
if (enemy.y > canvas.height + enemy.h) {
enemies.splice(i, 1);
}
});
// Update boss
if (boss) {
// Boss movement pattern
boss.moveTimer += 1;
if (boss.pattern === 'down') {
boss.y += boss.speed;
if (boss.y > 50) {
boss.pattern = 'left';
boss.moveTimer = 0;
}
} else if (boss.pattern === 'left') {
boss.x -= boss.speed;
if (boss.moveTimer > 120 || boss.x < 50) {
boss.pattern = 'right';
boss.moveTimer = 0;
}
} else if (boss.pattern === 'right') {
boss.x += boss.speed;
if (boss.moveTimer > 120 || boss.x > canvas.width - boss.w - 50) {
boss.pattern = 'left';
boss.moveTimer = 0;
}
}
// Boss shooting
if (Math.random() < 0.03) {
bossShoot();
}
}
// Update powerups
powerups.forEach((powerup, i) => {
powerup.y += powerup.speed;
// Remove if out of bounds
if (powerup.y > canvas.height + powerup.h) {
powerups.splice(i, 1);
}
});
// Update particles
particles.forEach((particle, i) => {
particle.x += particle.speedX;
particle.y += particle.speedY;
particle.life--;
if (particle.life <= 0) {
particles.splice(i, 1);
}
});
}
function drawBackground() {
// Dark space background
ctx.fillStyle = 'rgba(10, 10, 20, 0.8)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw parallax stars
ctx.fillStyle = 'white';
parallaxStars.forEach(star => {
ctx.globalAlpha = star.alpha;
star.y += star.speed;
if (star.y > canvas.height) {
star.y = 0;
star.x = Math.random() * canvas.width;
}
ctx.fillRect(star.x, star.y, star.size, star.size);
});
ctx.globalAlpha = 1;
}
function drawPlayer() {
// Draw ship body
ctx.fillStyle = '#3b82f6';
ctx.beginPath();
ctx.moveTo(player.x + player.w / 2, player.y);
ctx.lineTo(player.x + player.w, player.y + player.h);
ctx.lineTo(player.x, player.y + player.h);
ctx.closePath();
ctx.fill();
// Draw ship details
ctx.fillStyle = '#93c5fd';
ctx.fillRect(player.x + player.w / 2 - 5, player.y + 15, 10, 15);
// Draw engine glow
if (keys['ArrowLeft'] || keys['ArrowRight'] || keys['a'] || keys['d']) {
ctx.fillStyle = '#f59e0b';
ctx.beginPath();
ctx.moveTo(player.x + player.w / 2 - 10, player.y + player.h);
ctx.lineTo(player.x + player.w / 2 + 10, player.y + player.h);
ctx.lineTo(player.x + player.w / 2, player.y + player.h + 15);
ctx.closePath();
ctx.fill();
}
// Draw shield if active
if (player.hasShield) {
ctx.strokeStyle = 'rgba(59, 130, 246, 0.7)';
ctx.lineWidth = 2;
ctx.setLineDash([5, 5]);
ctx.beginPath();
ctx.arc(player.x + player.w/2, player.y + player.h/2, player.w + 10, 0, Math.PI * 2);
ctx.stroke();
ctx.setLineDash([]);
}
}
function drawShots() {
shots.forEach(shot => {
ctx.fillStyle = shot.color;
ctx.fillRect(shot.x, shot.y, shot.w, shot.h);
// Add glow to special shots
if (shot.damage > 1) {
ctx.shadowColor = shot.color;
ctx.shadowBlur = 10;
ctx.fillRect(shot.x, shot.y, shot.w, shot.h);
ctx.shadowBlur = 0;
}
});
}
function drawEnemies() {
enemies.forEach(enemy => {
ctx.fillStyle = enemy.color;
ctx.beginPath();
ctx.moveTo(enemy.x + enemy.w / 2, enemy.y);
ctx.lineTo(enemy.x + enemy.w, enemy.y + enemy.h);
ctx.lineTo(enemy.x, enemy.y + enemy.h);
ctx.closePath();
ctx.fill();
// Draw health for tank enemies
if (enemy.type === 'tank' && enemy.health > 1) {
ctx.fillStyle = 'white';
ctx.font = '10px Arial';
ctx.fillText(`${enemy.health}`, enemy.x + enemy.w/2 - 5, enemy.y + enemy.h/2 + 3);
}
});
// Draw boss
if (boss) {
ctx.fillStyle = boss.color;
ctx.beginPath();
ctx.moveTo(boss.x + boss.w / 2, boss.y);
ctx.lineTo(boss.x + boss.w, boss.y + boss.h);
ctx.lineTo(boss.x, boss.y + boss.h);
ctx.closePath();
ctx.fill();
// Draw boss details
ctx.fillStyle = '#fca5a5';
ctx.fillRect(boss.x + boss.w/2 - 20, boss.y + 30, 40, 10);
ctx.fillRect(boss.x + boss.w/2 - 15, boss.y + 50, 30, 20);
}
}
function drawPowerups() {
powerups.forEach(powerup => {
ctx.fillStyle = powerup.color;
ctx.beginPath();
ctx.arc(powerup.x + powerup.w/2, powerup.y + powerup.h/2, powerup.w/2, 0, Math.PI * 2);
ctx.fill();
// Add icon based on type
ctx.fillStyle = 'white';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
if (powerup.type === 'health') {
ctx.fillText('+', powerup.x + powerup.w/2, powerup.y + powerup.h/2 + 1);
} else if (powerup.type === 'shield') {
ctx.fillText('⛉', powerup.x + powerup.w/2, powerup.y + powerup.h/2 + 1);
} else if (powerup.type === 'rapidfire') {
ctx.fillText('»', powerup.x + powerup.w/2, powerup.y + powerup.h/2 + 1);
} else {
ctx.fillText('!', powerup.x + powerup.w/2, powerup.y + powerup.h/2 + 1);
}
});
}
function drawParticles() {
particles.forEach(particle => {
ctx.globalAlpha = particle.life / 60;
ctx.fillStyle = particle.color;
ctx.fillRect(particle.x, particle.y, particle.size, particle.size);
});
ctx.globalAlpha = 1;
}
function drawUI() {
// Draw special charge bar
const chargeWidth = (player.specialCharge / player.maxSpecial) * 100;
ctx.fillStyle = '#3b82f6';
ctx.fillRect(canvas.width - 110, 10, chargeWidth, 10);
ctx.strokeStyle = 'white';
ctx.strokeRect(canvas.width - 110, 10, 100, 10);
// Draw special charge text
ctx.fillStyle = 'white';
ctx.font = '12px Arial';
ctx.fillText('SPECIAL', canvas.width - 105, 20);
// Draw rapid fire indicator
if (player.rapidFire) {
ctx.fillStyle = 'rgba(245, 158, 11, 0.3)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
}
// =============================================
// GAME LOOP
// =============================================
function gameLoop() {
if (gameOver) {
gameOverScreen.classList.remove('hidden');
return;
}
if (gamePaused) {
requestAnimationFrame(gameLoop);
return;
}
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Update game state
spawnEnemy();
spawnPowerup();
updateGameObjects();
checkCollisions();
// Draw everything
drawBackground();
drawParticles();
drawEnemies();
drawShots();
drawPowerups();
drawPlayer();
drawUI();
// Continue the loop
requestAnimationFrame(gameLoop);
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Xacodavt/19-de-mar-o-de-2025" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>