spaxa / index.html
SignorNessuno's picture
Add 2 files
42d0306 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Space Battle 2D</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: 'Arial', sans-serif;
touch-action: none;
}
#gameContainer {
position: relative;
width: 100vw;
height: 100vh;
}
#gameCanvas {
background-color: #000;
display: block;
background-image: radial-gradient(circle at center, #111 0%, #000 100%);
position: absolute;
top: 0;
left: 0;
}
#uiContainer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.health-bar {
position: absolute;
top: 20px;
height: 30px;
border: 2px solid #fff;
border-radius: 5px;
overflow: hidden;
}
#player1Health {
left: 20px;
width: 200px;
}
#player2Health {
right: 20px;
width: 200px;
}
.health-fill {
height: 100%;
transition: width 0.3s;
}
#player1Health .health-fill {
background: linear-gradient(to right, #f00, #f80);
}
#player2Health .health-fill {
background: linear-gradient(to right, #0af, #08f);
}
#timer {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
color: #fff;
font-size: 24px;
text-shadow: 0 0 5px #0ff;
}
#startScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 10;
}
#startButton {
margin-top: 20px;
padding: 15px 30px;
font-size: 20px;
background: linear-gradient(to right, #f80, #f00);
border: none;
border-radius: 10px;
color: white;
cursor: pointer;
transition: transform 0.2s;
}
#startButton:hover {
transform: scale(1.05);
}
.controls {
margin-top: 30px;
text-align: center;
background-color: rgba(0, 0, 0, 0.5);
padding: 15px;
border-radius: 10px;
max-width: 80%;
}
.player-controls {
display: inline-block;
margin: 0 20px;
vertical-align: top;
}
#gameOverScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 10;
}
#winnerText {
font-size: 36px;
margin-bottom: 20px;
text-shadow: 0 0 10px #0ff;
}
#restartButton {
margin-top: 20px;
padding: 15px 30px;
font-size: 20px;
background: linear-gradient(to right, #0af, #08f);
border: none;
border-radius: 10px;
color: white;
cursor: pointer;
transition: transform 0.2s;
}
#restartButton:hover {
transform: scale(1.05);
}
.mobile-controls {
position: absolute;
bottom: 20px;
width: 100%;
display: none;
justify-content: space-between;
padding: 0 20px;
box-sizing: border-box;
}
.mobile-joystick {
width: 100px;
height: 100px;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 50%;
position: relative;
}
.mobile-fire {
width: 80px;
height: 80px;
background-color: rgba(255, 0, 0, 0.5);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: white;
}
@media (max-width: 768px) {
.mobile-controls {
display: flex;
}
.controls {
display: none;
}
}
</style>
</head>
<body>
<div id="gameContainer">
<canvas id="gameCanvas"></canvas>
<div id="uiContainer">
<div id="player1Health" class="health-bar">
<div class="health-fill" style="width: 100%"></div>
</div>
<div id="player2Health" class="health-bar">
<div class="health-fill" style="width: 100%"></div>
</div>
<div id="timer">02:00</div>
<div class="mobile-controls">
<div class="mobile-joystick" id="player1Joystick"></div>
<div class="mobile-fire" id="player1Fire">FIRE</div>
</div>
</div>
<div id="startScreen">
<h1>SPACE BATTLE</h1>
<p>Defeat your opponent before time runs out!</p>
<div class="controls">
<div class="player-controls">
<h3>Player 1 (Red)</h3>
<p>Move: WASD</p>
<p>Fire: Space</p>
</div>
<div class="player-controls">
<h3>Player 2 (Blue)</h3>
<p>Move: Arrow Keys</p>
<p>Fire: Enter</p>
</div>
</div>
<button id="startButton">START BATTLE</button>
</div>
<div id="gameOverScreen">
<h1>GAME OVER</h1>
<div id="winnerText"></div>
<button id="restartButton">PLAY AGAIN</button>
</div>
</div>
<script>
// Game setup
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startScreen = document.getElementById('startScreen');
const startButton = document.getElementById('startButton');
const gameOverScreen = document.getElementById('gameOverScreen');
const restartButton = document.getElementById('restartButton');
const winnerText = document.getElementById('winnerText');
const timerElement = document.getElementById('timer');
const player1HealthFill = document.querySelector('#player1Health .health-fill');
const player2HealthFill = document.querySelector('#player2Health .health-fill');
// Set canvas size
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// Game state
let gameRunning = false;
let gameTime = 120; // 2 minutes in seconds
let lastTime = 0;
// Players
const players = {
player1: {
x: 200,
y: canvas.height / 2,
width: 40,
height: 30,
color: '#f80',
speed: 5,
health: 100,
maxHealth: 100,
lastShot: 0,
shotCooldown: 500, // ms
keys: {
up: 'w',
down: 's',
left: 'a',
right: 'd',
fire: ' '
},
activeKeys: {
up: false,
down: false,
left: false,
right: false
}
},
player2: {
x: canvas.width - 200,
y: canvas.height / 2,
width: 40,
height: 30,
color: '#08f',
speed: 5,
health: 100,
maxHealth: 100,
lastShot: 0,
shotCooldown: 500, // ms
keys: {
up: 'ArrowUp',
down: 'ArrowDown',
left: 'ArrowLeft',
right: 'ArrowRight',
fire: 'Enter'
},
activeKeys: {
up: false,
down: false,
left: false,
right: false
}
}
};
// Projectiles
const projectiles = [];
const projectileSpeed = 10;
const projectileSize = 5;
// Stars for background
const stars = [];
for (let i = 0; i < 100; i++) {
stars.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: Math.random() * 2,
opacity: Math.random()
});
}
// Input handling
const keysPressed = {};
window.addEventListener('keydown', (e) => {
keysPressed[e.key] = true;
// Check player 1 controls
if (e.key === players.player1.keys.up) players.player1.activeKeys.up = true;
if (e.key === players.player1.keys.down) players.player1.activeKeys.down = true;
if (e.key === players.player1.keys.left) players.player1.activeKeys.left = true;
if (e.key === players.player1.keys.right) players.player1.activeKeys.right = true;
// Check player 2 controls
if (e.key === players.player2.keys.up) players.player2.activeKeys.up = true;
if (e.key === players.player2.keys.down) players.player2.activeKeys.down = true;
if (e.key === players.player2.keys.left) players.player2.activeKeys.left = true;
if (e.key === players.player2.keys.right) players.player2.activeKeys.right = true;
// Fire controls
if (gameRunning) {
const now = Date.now();
if (e.key === players.player1.keys.fire && now - players.player1.lastShot > players.player1.shotCooldown) {
fireProjectile(players.player1);
players.player1.lastShot = now;
}
if (e.key === players.player2.keys.fire && now - players.player2.lastShot > players.player2.shotCooldown) {
fireProjectile(players.player2);
players.player2.lastShot = now;
}
}
});
window.addEventListener('keyup', (e) => {
keysPressed[e.key] = false;
// Check player 1 controls
if (e.key === players.player1.keys.up) players.player1.activeKeys.up = false;
if (e.key === players.player1.keys.down) players.player1.activeKeys.down = false;
if (e.key === players.player1.keys.left) players.player1.activeKeys.left = false;
if (e.key === players.player1.keys.right) players.player1.activeKeys.right = false;
// Check player 2 controls
if (e.key === players.player2.keys.up) players.player2.activeKeys.up = false;
if (e.key === players.player2.keys.down) players.player2.activeKeys.down = false;
if (e.key === players.player2.keys.left) players.player2.activeKeys.left = false;
if (e.key === players.player2.keys.right) players.player2.activeKeys.right = false;
});
// Mobile touch controls
const player1Joystick = document.getElementById('player1Joystick');
const player1Fire = document.getElementById('player1Fire');
let joystickActive = false;
let joystickStartX = 0;
let joystickStartY = 0;
let joystickX = 0;
let joystickY = 0;
player1Joystick.addEventListener('touchstart', (e) => {
const rect = player1Joystick.getBoundingClientRect();
joystickStartX = rect.left + rect.width / 2;
joystickStartY = rect.top + rect.height / 2;
joystickActive = true;
handleJoystickMove(e.touches[0]);
e.preventDefault();
});
document.addEventListener('touchmove', (e) => {
if (joystickActive) {
handleJoystickMove(e.touches[0]);
e.preventDefault();
}
});
document.addEventListener('touchend', () => {
joystickActive = false;
players.player1.activeKeys.up = false;
players.player1.activeKeys.down = false;
players.player1.activeKeys.left = false;
players.player1.activeKeys.right = false;
});
player1Fire.addEventListener('touchstart', (e) => {
const now = Date.now();
if (now - players.player1.lastShot > players.player1.shotCooldown) {
fireProjectile(players.player1);
players.player1.lastShot = now;
}
e.preventDefault();
});
function handleJoystickMove(touch) {
if (!joystickActive) return;
const dx = touch.clientX - joystickStartX;
const dy = touch.clientY - joystickStartY;
const distance = Math.sqrt(dx * dx + dy * dy);
const maxDistance = 50;
if (distance > maxDistance) {
joystickX = (dx / distance) * maxDistance;
joystickY = (dy / distance) * maxDistance;
} else {
joystickX = dx;
joystickY = dy;
}
// Update player controls based on joystick position
const threshold = 20;
players.player1.activeKeys.up = joystickY < -threshold;
players.player1.activeKeys.down = joystickY > threshold;
players.player1.activeKeys.left = joystickX < -threshold;
players.player1.activeKeys.right = joystickX > threshold;
}
// Projectile functions
function fireProjectile(player) {
const direction = player === players.player1 ? 1 : -1;
projectiles.push({
x: player.x + (player.width / 2 * direction),
y: player.y,
width: projectileSize,
height: projectileSize,
speed: projectileSpeed * direction,
color: player.color,
owner: player === players.player1 ? 'player1' : 'player2'
});
}
// Collision detection
function checkCollisions() {
for (let i = projectiles.length - 1; i >= 0; i--) {
const proj = projectiles[i];
// Check if projectile is out of bounds
if (proj.x < 0 || proj.x > canvas.width) {
projectiles.splice(i, 1);
continue;
}
// Check collision with player 1
if (proj.owner === 'player2' &&
proj.x < players.player1.x + players.player1.width &&
proj.x + proj.width > players.player1.x &&
proj.y < players.player1.y + players.player1.height &&
proj.y + proj.height > players.player1.y) {
players.player1.health -= 10;
player1HealthFill.style.width = `${(players.player1.health / players.player1.maxHealth) * 100}%`;
projectiles.splice(i, 1);
if (players.player1.health <= 0) {
endGame('Player 2 (Blue)');
}
continue;
}
// Check collision with player 2
if (proj.owner === 'player1' &&
proj.x < players.player2.x + players.player2.width &&
proj.x + proj.width > players.player2.x &&
proj.y < players.player2.y + players.player2.height &&
proj.y + proj.height > players.player2.y) {
players.player2.health -= 10;
player2HealthFill.style.width = `${(players.player2.health / players.player2.maxHealth) * 100}%`;
projectiles.splice(i, 1);
if (players.player2.health <= 0) {
endGame('Player 1 (Red)');
}
}
}
}
// Game control functions
function startGame() {
gameRunning = true;
gameTime = 120;
lastTime = Date.now();
startScreen.style.display = 'none';
gameOverScreen.style.display = 'none';
// Reset players
players.player1.x = 200;
players.player1.y = canvas.height / 2;
players.player1.health = 100;
player1HealthFill.style.width = '100%';
players.player2.x = canvas.width - 200;
players.player2.y = canvas.height / 2;
players.player2.health = 100;
player2HealthFill.style.width = '100%';
// Clear projectiles
projectiles.length = 0;
// Start game loop
requestAnimationFrame(gameLoop);
}
function endGame(winner) {
gameRunning = false;
winnerText.textContent = `${winner} Wins!`;
gameOverScreen.style.display = 'flex';
}
function updateTimer() {
const now = Date.now();
const delta = (now - lastTime) / 1000;
lastTime = now;
if (gameRunning) {
gameTime -= delta;
if (gameTime <= 0) {
gameTime = 0;
gameRunning = false;
if (players.player1.health > players.player2.health) {
endGame('Player 1 (Red)');
} else if (players.player2.health > players.player1.health) {
endGame('Player 2 (Blue)');
} else {
endGame('Draw!');
}
}
const minutes = Math.floor(gameTime / 60);
const seconds = Math.floor(gameTime % 60);
timerElement.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}
}
// Drawing functions
function drawBackground() {
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw stars
ctx.save();
stars.forEach(star => {
ctx.fillStyle = `rgba(255, 255, 255, ${star.opacity})`;
ctx.beginPath();
ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);
ctx.fill();
// Move stars for parallax effect
star.y += 0.5;
if (star.y > canvas.height) {
star.y = 0;
star.x = Math.random() * canvas.width;
}
});
ctx.restore();
}
function drawPlayers() {
// Player 1
ctx.save();
ctx.fillStyle = players.player1.color;
ctx.translate(players.player1.x, players.player1.y);
ctx.beginPath();
ctx.moveTo(players.player1.width, players.player1.height / 2);
ctx.lineTo(0, 0);
ctx.lineTo(0, players.player1.height);
ctx.closePath();
ctx.fill();
ctx.restore();
// Player 2
ctx.save();
ctx.fillStyle = players.player2.color;
ctx.translate(players.player2.x, players.player2.y);
ctx.beginPath();
ctx.moveTo(0, players.player2.height / 2);
ctx.lineTo(players.player2.width, 0);
ctx.lineTo(players.player2.width, players.player2.height);
ctx.closePath();
ctx.fill();
ctx.restore();
}
function drawProjectiles() {
projectiles.forEach(proj => {
ctx.fillStyle = proj.color;
ctx.fillRect(proj.x, proj.y, proj.width, proj.height);
});
}
// Game loop
function gameLoop() {
if (!gameRunning) return;
// Update game state
updateTimer();
updatePlayers();
updateProjectiles();
checkCollisions();
// Draw everything
drawBackground();
drawPlayers();
drawProjectiles();
// Continue the game loop
requestAnimationFrame(gameLoop);
}
function updatePlayers() {
// Player 1 movement
if (players.player1.activeKeys.up) players.player1.y -= players.player1.speed;
if (players.player1.activeKeys.down) players.player1.y += players.player1.speed;
if (players.player1.activeKeys.left) players.player1.x -= players.player1.speed;
if (players.player1.activeKeys.right) players.player1.x += players.player1.speed;
// Player 2 movement
if (players.player2.activeKeys.up) players.player2.y -= players.player2.speed;
if (players.player2.activeKeys.down) players.player2.y += players.player2.speed;
if (players.player2.activeKeys.left) players.player2.x -= players.player2.speed;
if (players.player2.activeKeys.right) players.player2.x += players.player2.speed;
// Keep players within bounds
players.player1.x = Math.max(0, Math.min(canvas.width - players.player1.width, players.player1.x));
players.player1.y = Math.max(0, Math.min(canvas.height - players.player1.height, players.player1.y));
players.player2.x = Math.max(0, Math.min(canvas.width - players.player2.width, players.player2.x));
players.player2.y = Math.max(0, Math.min(canvas.height - players.player2.height, players.player2.y));
}
function updateProjectiles() {
for (let i = 0; i < projectiles.length; i++) {
projectiles[i].x += projectiles[i].speed;
}
}
// Event listeners for buttons
startButton.addEventListener('click', startGame);
restartButton.addEventListener('click', startGame);
</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 <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
</html>