Invaders-2 / index.html
Luis-Filipe's picture
Rename space-invaders.html to index.html
bac74cf verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Space Invaders - Transparent Sprites</title>
<style>
body {
margin: 0;
padding: 20px;
background: #000;
font-family: 'Courier New', monospace;
color: #00ff00;
display: flex;
flex-direction: column;
align-items: center;
user-select: none;
}
.title {
margin-bottom: 20px;
text-shadow: 0 0 10px #00ff00;
}
#gameCanvas {
border: 3px solid #00ff00;
box-shadow: 0 0 20px rgba(0, 255, 0, 0.3);
background: #000;
}
.hud {
margin: 15px 0;
font-size: 20px;
font-weight: bold;
text-shadow: 0 0 5px #00ff00;
}
.controls {
margin: 10px 0;
color: #00cc00;
font-size: 14px;
}
.game-btn {
margin: 15px 0;
padding: 12px 24px;
background: transparent;
border: 2px solid #00ff00;
color: #00ff00;
font-family: 'Courier New', monospace;
cursor: pointer;
font-size: 16px;
transition: all 0.3s;
}
.game-btn:hover {
background: #00ff00;
color: #000;
box-shadow: 0 0 15px #00ff00;
}
.status {
margin: 10px 0;
font-size: 14px;
color: #008800;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<h1 class="title">๐Ÿš€ SPACE INVADERS - TRANSPARENT SPRITES ๐Ÿš€</h1>
<div class="hud">
SCORE: <span id="score">000000</span> |
LIVES: <span id="lives">3</span> |
LEVEL: <span id="level">1</span>
</div>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div class="controls">
๐ŸŽฎ MOVE: Arrow Keys or A/D | ๐Ÿš€ SHOOT: SPACEBAR
</div>
<button class="game-btn" id="startBtn" onclick="startGame()">START GAME</button>
<button class="game-btn hidden" id="restartBtn" onclick="restartGame()">RESTART</button>
<div class="status" id="status">Loading transparent sprites...</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
let gameState = 'menu';
let score = 0;
let lives = 3;
let level = 1;
// Game objects
let player = {
x: 380,
y: 550,
width: 40,
height: 30,
speed: 6,
lastShot: 0,
shootDelay: 250
};
let invaders = [];
let bullets = [];
// Your transparent sprites
let sprites = {
loaded: false,
ship: null,
invader: null,
bullet: null
};
// Game settings
const INVADER_ROWS = 5;
const INVADER_COLS = 11;
const INVADER_WIDTH = 35;
const INVADER_HEIGHT = 25;
// Movement
let invaderDirection = 1;
let invaderSpeed = 1;
let invaderDropDistance = 20;
// Input
const keys = {};
// Setup
function init() {
updateStatus('Loading transparent sprites...');
loadTransparentSprites();
createInvaders();
drawInitialScreen();
// Keyboard events
document.addEventListener('keydown', (e) => {
keys[e.code] = true;
if (e.code === 'Space') {
e.preventDefault();
if (gameState === 'playing') {
shoot();
}
}
});
document.addEventListener('keyup', (e) => {
keys[e.code] = false;
});
}
function loadTransparentSprites() {
console.log('Loading your transparent sprites...');
// Use your transparent sprites
const spriteFiles = {
ship: 'assets/ship-transparent.png',
invader: 'assets/invader-transparent.png',
bullet: 'assets/bullet-transparent.png'
};
let loadedCount = 0;
const totalSprites = Object.keys(spriteFiles).length;
Object.keys(spriteFiles).forEach(key => {
const img = new Image();
img.onload = () => {
console.log(`โœ“ Loaded transparent ${key} sprite: ${img.width}x${img.height}px`);
sprites[key] = img;
loadedCount++;
if (loadedCount === totalSprites) {
sprites.loaded = true;
updateStatus('โœ“ All transparent sprites loaded! Game ready!');
console.log('All transparent sprites loaded successfully!');
}
};
img.onerror = () => {
console.error(`โœ— Failed to load transparent ${key} sprite`);
updateStatus(`โœ— Failed to load ${key} sprite - using fallback shapes`);
};
img.src = spriteFiles[key];
});
}
function drawInitialScreen() {
// Clear
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw stars
ctx.fillStyle = '#003300';
for (let i = 0; i < 50; i++) {
const x = (i * 137) % canvas.width;
const y = (i * 173) % canvas.height;
ctx.fillRect(x, y, 2, 2);
}
// Draw title text
ctx.fillStyle = '#00ff00';
ctx.font = '32px Courier New';
ctx.textAlign = 'center';
ctx.fillText('SPACE INVADERS - TRANSPARENT SPRITES', canvas.width/2, canvas.height/2 - 50);
ctx.font = '20px Courier New';
ctx.fillText('Click START GAME to begin!', canvas.width/2, canvas.height/2 + 20);
ctx.fillText('Use ARROW KEYS + SPACEBAR', canvas.width/2, canvas.height/2 + 50);
// Test sprite display
if (sprites.loaded) {
ctx.drawImage(sprites.ship, canvas.width/2 - 20, canvas.height/2 + 80, 40, 30);
ctx.drawImage(sprites.invader, canvas.width/2 - 17, canvas.height/2 + 120, 35, 25);
}
}
function createInvaders() {
invaders = [];
const startX = 50;
const startY = 80;
const spacingX = 60;
const spacingY = 40;
for (let row = 0; row < INVADER_ROWS; row++) {
for (let col = 0; col < INVADER_COLS; col++) {
invaders.push({
x: startX + col * spacingX,
y: startY + row * spacingY,
width: INVADER_WIDTH,
height: INVADER_HEIGHT,
alive: true,
row: row,
col: col
});
}
}
}
function startGame() {
gameState = 'playing';
score = 0;
lives = 3;
level = 1;
player.x = 380;
createInvaders();
bullets = [];
invaderDirection = 1;
invaderSpeed = 1;
document.getElementById('startBtn').classList.add('hidden');
document.getElementById('restartBtn').classList.add('hidden');
updateStatus('Game started! Destroy all invaders!');
gameLoop();
}
function restartGame() {
gameState = 'menu';
document.getElementById('startBtn').classList.remove('hidden');
document.getElementById('restartBtn').classList.add('hidden');
drawInitialScreen();
updateStatus('Game ready! Click START GAME');
}
function shoot() {
const now = Date.now();
if (now - player.lastShot < player.shootDelay) return;
player.lastShot = now;
bullets.push({
x: player.x + player.width/2 - 2,
y: player.y,
width: 4,
height: 10
});
}
function update() {
if (gameState !== 'playing') return;
// Player movement
if (keys['ArrowLeft'] || keys['KeyA']) {
player.x = Math.max(0, player.x - player.speed);
}
if (keys['ArrowRight'] || keys['KeyD']) {
player.x = Math.min(canvas.width - player.width, player.x + player.speed);
}
// Update bullets
bullets = bullets.filter(bullet => {
bullet.y -= 8;
return bullet.y > -20;
});
// Update invaders
updateInvaders();
// Check collisions
checkCollisions();
// Check win/lose conditions
checkGameConditions();
}
function updateInvaders() {
const aliveInvaders = invaders.filter(inv => inv.alive);
if (aliveInvaders.length === 0) return;
const rightmost = Math.max(...aliveInvaders.map(inv => inv.x + inv.width));
const leftmost = Math.min(...aliveInvaders.map(inv => inv.x));
let shouldDrop = false;
if ((rightmost >= canvas.width - 50 && invaderDirection > 0) ||
(leftmost <= 50 && invaderDirection < 0)) {
shouldDrop = true;
}
if (shouldDrop) {
invaderDirection *= -1;
aliveInvaders.forEach(invader => {
invader.y += invaderDropDistance;
});
invaderSpeed += 0.1;
} else {
aliveInvaders.forEach(invader => {
invader.x += invaderSpeed * invaderDirection;
});
}
}
function checkCollisions() {
bullets.forEach((bullet, bulletIndex) => {
invaders.forEach(invader => {
if (invader.alive &&
bullet.x < invader.x + invader.width &&
bullet.x + bullet.width > invader.x &&
bullet.y < invader.y + invader.height &&
bullet.y + bullet.height > invader.y) {
invader.alive = false;
bullets.splice(bulletIndex, 1);
score += 10 * level;
updateHUD();
createExplosion(invader.x + invader.width/2, invader.y + invader.height/2);
}
});
});
}
function createExplosion(x, y) {
ctx.save();
ctx.fillStyle = '#ff6600';
ctx.beginPath();
ctx.arc(x, y, 15, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#ffff00';
ctx.beginPath();
ctx.arc(x, y, 8, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
function checkGameConditions() {
const aliveInvaders = invaders.filter(inv => inv.alive);
if (aliveInvaders.length === 0) {
levelComplete();
return;
}
const bottomInvader = Math.max(...aliveInvaders.map(inv => inv.y));
if (bottomInvader >= canvas.height - 100) {
gameOver();
return;
}
}
function levelComplete() {
updateStatus(`Level ${level} complete!`);
level++;
createInvaders();
updateHUD();
}
function gameOver() {
gameState = 'gameover';
updateStatus(`GAME OVER! Final Score: ${score}`);
document.getElementById('restartBtn').classList.remove('hidden');
}
function draw() {
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawStars();
if (gameState === 'playing') {
drawPlayer();
drawInvaders();
drawBullets();
}
}
function drawStars() {
ctx.fillStyle = '#003300';
for (let i = 0; i < 30; i++) {
const x = (i * 47) % canvas.width;
const y = (i * 83) % canvas.height;
ctx.fillRect(x, y, 1, 1);
}
}
function drawPlayer() {
if (sprites.loaded && sprites.ship) {
ctx.drawImage(sprites.ship, player.x, player.y, player.width, player.height);
} else {
// Fallback to red triangle
ctx.fillStyle = '#ff0000';
ctx.beginPath();
ctx.moveTo(player.x + player.width/2, player.y);
ctx.lineTo(player.x, player.y + player.height);
ctx.lineTo(player.x + player.width, player.y + player.height);
ctx.closePath();
ctx.fill();
}
}
function drawInvaders() {
invaders.forEach(invader => {
if (invader.alive) {
if (sprites.loaded && sprites.invader) {
ctx.drawImage(sprites.invader, invader.x, invader.y, invader.width, invader.height);
} else {
// Fallback to green rectangle
ctx.fillStyle = '#00ff00';
ctx.fillRect(invader.x, invader.y, invader.width, invader.height);
ctx.fillStyle = '#008800';
ctx.fillRect(invader.x + 5, invader.y + 5, invader.width - 10, invader.height - 10);
}
}
});
}
function drawBullets() {
if (sprites.loaded && sprites.bullet) {
bullets.forEach(bullet => {
ctx.drawImage(sprites.bullet, bullet.x, bullet.y, bullet.width, bullet.height);
});
} else {
// Fallback to yellow rectangles
ctx.fillStyle = '#ffff00';
bullets.forEach(bullet => {
ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
});
}
}
function updateHUD() {
document.getElementById('score').textContent = score.toString().padStart(6, '0');
document.getElementById('lives').textContent = lives;
document.getElementById('level').textContent = level;
}
function updateStatus(message) {
document.getElementById('status').textContent = message;
console.log(message);
}
function gameLoop() {
if (gameState !== 'playing') return;
update();
draw();
requestAnimationFrame(gameLoop);
}
// Initialize game
init();
updateHUD();
</script>
</body>
</html>