F-16FightingFalcon / index.html
offerpk3's picture
Update index.html
ba0bd55 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</title>
<style>
body {
margin: 0;
padding: 0;
background: #000;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: 'Courier New', monospace;
color: #00ff00;
}
#gameContainer {
text-align: center;
}
canvas {
border: 2px solid #00ff00;
background: #000;
}
#ui {
margin-top: 10px;
font-size: 18px;
}
#instructions {
margin-top: 10px;
font-size: 14px;
opacity: 0.8;
}
#gameOver {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 32px;
color: #ff0000;
display: none;
}
</style>
</head>
<body>
<div id="gameContainer">
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="ui">
<span>Score: <span id="score">0</span></span>
<span style="margin-left: 50px;">Lives: <span id="lives">3</span></span>
</div>
<div id="instructions">
Use ARROW KEYS or WASD to move in all directions • SPACEBAR for auto-targeted shooting • R to restart
</div>
<div id="gameOver">
GAME OVER<br>
<span style="font-size: 16px;">Press R to restart</span>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const livesElement = document.getElementById('lives');
const gameOverElement = document.getElementById('gameOver');
// Game state
let gameState = {
score: 0,
lives: 3,
gameRunning: true,
keys: {}
};
// Player
const player = {
x: canvas.width / 2 - 20,
y: canvas.height - 60,
width: 40,
height: 30,
speed: 5
};
// Arrays for game objects
let bullets = [];
let invaders = [];
let invaderBullets = [];
// Game settings
const bulletSpeed = 7;
const invaderBulletSpeed = 3;
const invaderSpeed = 1;
let invaderDirection = 1;
let invaderDropDistance = 30;
// Initialize invaders
function createInvaders() {
invaders = [];
for (let row = 0; row < 5; row++) {
for (let col = 0; col < 10; col++) {
invaders.push({
x: col * 60 + 80,
y: row * 50 + 50,
width: 40,
height: 30,
alive: true
});
}
}
}
// Input handling
document.addEventListener('keydown', (e) => {
gameState.keys[e.code] = true;
if (e.code === 'Space') {
e.preventDefault();
shoot();
}
if (e.code === 'KeyR') {
restartGame();
}
});
document.addEventListener('keyup', (e) => {
gameState.keys[e.code] = false;
});
// Player movement
function updatePlayer() {
if (gameState.keys['ArrowLeft'] || gameState.keys['KeyA']) {
player.x = Math.max(0, player.x - player.speed);
}
if (gameState.keys['ArrowRight'] || gameState.keys['KeyD']) {
player.x = Math.min(canvas.width - player.width, player.x + player.speed);
}
if (gameState.keys['ArrowUp'] || gameState.keys['KeyW']) {
player.y = Math.max(0, player.y - player.speed);
}
if (gameState.keys['ArrowDown'] || gameState.keys['KeyS']) {
player.y = Math.min(canvas.height - player.height, player.y + player.speed);
}
}
// Shooting with auto-targeting
function shoot() {
if (!gameState.gameRunning) return;
// Find nearest alive invader
let nearestInvader = null;
let minDistance = Infinity;
for (let invader of invaders) {
if (invader.alive) {
const distance = Math.sqrt(
Math.pow(invader.x + invader.width/2 - (player.x + player.width/2), 2) +
Math.pow(invader.y + invader.height/2 - player.y, 2)
);
if (distance < minDistance) {
minDistance = distance;
nearestInvader = invader;
}
}
}
if (nearestInvader) {
// Calculate direction to target
const dx = (nearestInvader.x + nearestInvader.width/2) - (player.x + player.width/2);
const dy = (nearestInvader.y + nearestInvader.height/2) - player.y;
const distance = Math.sqrt(dx * dx + dy * dy);
bullets.push({
x: player.x + player.width / 2 - 2,
y: player.y,
width: 4,
height: 10,
vx: (dx / distance) * bulletSpeed,
vy: (dy / distance) * bulletSpeed
});
}
}
// Update bullets
function updateBullets() {
bullets = bullets.filter(bullet => {
bullet.x += bullet.vx;
bullet.y += bullet.vy;
// Remove bullets that go off screen
return bullet.x > -bullet.width &&
bullet.x < canvas.width + bullet.width &&
bullet.y > -bullet.height &&
bullet.y < canvas.height + bullet.height;
});
}
// Update invader bullets
function updateInvaderBullets() {
invaderBullets = invaderBullets.filter(bullet => {
bullet.y += bullet.speed;
return bullet.y < canvas.height;
});
}
// Invader shooting
function invaderShoot() {
if (Math.random() < 0.002 && invaders.some(inv => inv.alive)) {
const aliveInvaders = invaders.filter(inv => inv.alive);
const shooter = aliveInvaders[Math.floor(Math.random() * aliveInvaders.length)];
invaderBullets.push({
x: shooter.x + shooter.width / 2 - 2,
y: shooter.y + shooter.height,
width: 4,
height: 10,
speed: invaderBulletSpeed
});
}
}
// Update invaders
function updateInvaders() {
let shouldDrop = false;
// Check if any invader hit the edge
for (let invader of invaders) {
if (!invader.alive) continue;
if ((invader.x <= 0 && invaderDirection === -1) ||
(invader.x + invader.width >= canvas.width && invaderDirection === 1)) {
shouldDrop = true;
break;
}
}
// Move invaders
for (let invader of invaders) {
if (!invader.alive) continue;
if (shouldDrop) {
invader.y += invaderDropDistance;
} else {
invader.x += invaderSpeed * invaderDirection;
}
}
if (shouldDrop) {
invaderDirection *= -1;
}
}
// Collision detection
function checkCollisions() {
// Bullet vs invaders
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
for (let j = 0; j < invaders.length; j++) {
const invader = invaders[j];
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(i, 1);
gameState.score += 10;
break;
}
}
}
// Invader bullets vs player
for (let i = invaderBullets.length - 1; i >= 0; i--) {
const bullet = invaderBullets[i];
if (bullet.x < player.x + player.width &&
bullet.x + bullet.width > player.x &&
bullet.y < player.y + player.height &&
bullet.y + bullet.height > player.y) {
invaderBullets.splice(i, 1);
gameState.lives--;
if (gameState.lives <= 0) {
gameOver();
}
}
}
// Check if invaders reached player
for (let invader of invaders) {
if (invader.alive && invader.y + invader.height >= player.y) {
gameOver();
return;
}
}
}
// Game over
function gameOver() {
gameState.gameRunning = false;
gameOverElement.style.display = 'block';
}
// Restart game
function restartGame() {
gameState.score = 0;
gameState.lives = 3;
gameState.gameRunning = true;
bullets = [];
invaderBullets = [];
invaderDirection = 1;
player.x = canvas.width / 2 - 20;
createInvaders();
gameOverElement.style.display = 'none';
}
// Check win condition
function checkWin() {
if (invaders.every(inv => !inv.alive)) {
// Create new wave
createInvaders();
gameState.score += 100; // Bonus for clearing wave
}
}
// Drawing functions
function drawPlayer() {
const x = player.x;
const y = player.y;
// F-16 Fighting Falcon design
ctx.save();
// Main fuselage
ctx.fillStyle = '#4a5568';
ctx.fillRect(x + 16, y + 5, 8, 20);
// Nose cone
ctx.fillStyle = '#2d3748';
ctx.beginPath();
ctx.moveTo(x + 20, y);
ctx.lineTo(x + 16, y + 5);
ctx.lineTo(x + 24, y + 5);
ctx.closePath();
ctx.fill();
// Main wings
ctx.fillStyle = '#718096';
ctx.fillRect(x + 8, y + 12, 24, 6);
// Wing tips
ctx.fillStyle = '#4a5568';
ctx.fillRect(x + 6, y + 14, 4, 2);
ctx.fillRect(x + 30, y + 14, 4, 2);
// Canards (small front wings)
ctx.fillStyle = '#718096';
ctx.fillRect(x + 12, y + 8, 16, 2);
// Engine exhaust
ctx.fillStyle = '#e53e3e';
ctx.fillRect(x + 17, y + 25, 6, 3);
// Cockpit
ctx.fillStyle = '#3182ce';
ctx.fillRect(x + 18, y + 6, 4, 4);
// Air intakes
ctx.fillStyle = '#2d3748';
ctx.fillRect(x + 14, y + 10, 2, 8);
ctx.fillRect(x + 24, y + 10, 2, 8);
// Wing missiles
ctx.fillStyle = '#e2e8f0';
ctx.fillRect(x + 10, y + 16, 3, 1);
ctx.fillRect(x + 27, y + 16, 3, 1);
ctx.restore();
}
function drawBullets() {
ctx.fillStyle = '#ffff00';
for (let bullet of bullets) {
ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
}
}
function drawInvaderBullets() {
ctx.fillStyle = '#ff0000';
for (let bullet of invaderBullets) {
ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
}
}
function drawInvaders() {
for (let i = 0; i < invaders.length; i++) {
const invader = invaders[i];
if (!invader.alive) continue;
const x = invader.x;
const y = invader.y;
const row = Math.floor(i / 10);
ctx.save();
// Different aircraft for different rows
if (row === 0) {
// J-10C Vigorous Dragon (Top row)
ctx.fillStyle = '#2d5016';
ctx.fillRect(x + 16, y + 5, 8, 18);
// Delta wing
ctx.beginPath();
ctx.moveTo(x + 20, y + 8);
ctx.lineTo(x + 8, y + 20);
ctx.lineTo(x + 32, y + 20);
ctx.closePath();
ctx.fill();
// Nose
ctx.fillStyle = '#1a202c';
ctx.beginPath();
ctx.moveTo(x + 20, y);
ctx.lineTo(x + 16, y + 5);
ctx.lineTo(x + 24, y + 5);
ctx.closePath();
ctx.fill();
// Canards
ctx.fillStyle = '#38a169';
ctx.fillRect(x + 12, y + 6, 16, 3);
} else if (row === 1) {
// Dassault Rafale (Second row)
ctx.fillStyle = '#2c5282';
ctx.fillRect(x + 16, y + 5, 8, 18);
// Close-coupled canard delta
ctx.fillStyle = '#3182ce';
ctx.fillRect(x + 10, y + 12, 20, 8);
// Canards
ctx.fillRect(x + 14, y + 7, 12, 3);
// Twin engines
ctx.fillStyle = '#1a202c';
ctx.fillRect(x + 14, y + 20, 4, 3);
ctx.fillRect(x + 22, y + 20, 4, 3);
} else if (row === 2) {
// JF-17 Thunder (Third row)
ctx.fillStyle = '#744210';
ctx.fillRect(x + 16, y + 5, 8, 18);
// Wings
ctx.fillStyle = '#a0522d';
ctx.fillRect(x + 8, y + 14, 24, 6);
// Single engine
ctx.fillStyle = '#8b4513';
ctx.fillRect(x + 17, y + 20, 6, 3);
// Side intakes
ctx.fillStyle = '#1a202c';
ctx.fillRect(x + 12, y + 12, 4, 4);
ctx.fillRect(x + 24, y + 12, 4, 4);
} else if (row === 3) {
// F-16 Fighting Falcon (Fourth row)
ctx.fillStyle = '#4a5568';
ctx.fillRect(x + 16, y + 5, 8, 18);
// Wings
ctx.fillStyle = '#718096';
ctx.fillRect(x + 10, y + 14, 20, 6);
// Single engine
ctx.fillStyle = '#e53e3e';
ctx.fillRect(x + 17, y + 20, 6, 3);
// Side intake
ctx.fillStyle = '#2d3748';
ctx.fillRect(x + 18, y + 12, 4, 4);
} else {
// Generic enemy fighter (Bottom row)
ctx.fillStyle = '#742a2a';
ctx.fillRect(x + 16, y + 5, 8, 18);
// Swept wings
ctx.fillStyle = '#9b2c2c';
ctx.beginPath();
ctx.moveTo(x + 12, y + 16);
ctx.lineTo(x + 8, y + 20);
ctx.lineTo(x + 32, y + 20);
ctx.lineTo(x + 28, y + 16);
ctx.lineTo(x + 20, y + 12);
ctx.closePath();
ctx.fill();
}
// Common elements for all aircraft
// Cockpit
ctx.fillStyle = '#4a90e2';
ctx.fillRect(x + 18, y + 6, 4, 3);
// Nose cone highlight
ctx.fillStyle = '#ffffff';
ctx.fillRect(x + 19, y + 2, 2, 2);
ctx.restore();
}
}
function drawUI() {
scoreElement.textContent = gameState.score;
livesElement.textContent = gameState.lives;
}
// Main game loop
function gameLoop() {
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (gameState.gameRunning) {
// Update
updatePlayer();
updateBullets();
updateInvaderBullets();
updateInvaders();
invaderShoot();
checkCollisions();
checkWin();
}
// Draw
drawPlayer();
drawBullets();
drawInvaderBullets();
drawInvaders();
drawUI();
requestAnimationFrame(gameLoop);
}
// Initialize game
createInvaders();
gameLoop();
</script>
</body>
</html>