zaido / index.html
Mohabedalgani's picture
Add 1 files
7a2efe0 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Moving Brick Attacker</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>
#gameCanvas {
background-color: #1a202c;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
touch-action: none;
}
.game-container {
position: relative;
}
.game-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.7);
color: white;
border-radius: 8px;
}
.hidden {
display: none;
}
.brick {
border-radius: 2px;
}
.heart-icon {
color: #f56565;
}
.bullet {
position: absolute;
width: 4px;
height: 12px;
background-color: #f6e05e;
border-radius: 2px;
}
#attacker {
position: absolute;
width: 50px;
height: 80px;
background-color: #4a5568;
border-radius: 8px;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
z-index: 10;
}
#gun {
position: absolute;
width: 30px;
height: 10px;
background-color: #2d3748;
top: -10px;
left: 10px;
border-radius: 2px;
transform-origin: left center;
z-index: 20;
}
#gun-barrel {
position: absolute;
width: 30px;
height: 4px;
background-color: #2d3748;
top: 3px;
left: 30px;
border-radius: 2px;
}
/* Animation for special bricks */
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.start-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 18px;
font-weight: bold;
margin: 10px 2px;
cursor: pointer;
border-radius: 50px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.start-btn:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
.start-btn:active {
transform: translateY(1px);
}
.start-btn::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0) 100%);
opacity: 0;
transition: opacity 0.3s ease;
}
.start-btn:hover::after {
opacity: 1;
}
.start-btn i {
margin-right: 10px;
}
</style>
</head>
<body class="bg-gray-900 min-h-screen flex flex-col items-center justify-center p-4">
<div class="max-w-4xl w-full">
<h1 class="text-3xl font-bold text-center text-white mb-6">Moving Brick Attacker</h1>
<div class="flex justify-between items-center mb-4">
<div class="flex items-center space-x-2">
<span class="text-white font-semibold">Score:</span>
<span id="score" class="text-yellow-300 font-bold text-xl">0</span>
</div>
<div class="flex items-center space-x-2">
<span class="text-white font-semibold">Lives:</span>
<div id="lives" class="flex space-x-1">
<i class="fas fa-heart heart-icon"></i>
<i class="fas fa-heart heart-icon"></i>
<i class="fas fa-heart heart-icon"></i>
</div>
</div>
</div>
<div class="game-container relative">
<canvas id="gameCanvas" width="800" height="500" class="w-full"></canvas>
<div id="startScreen" class="game-overlay">
<h2 class="text-4xl font-bold mb-6 text-yellow-300">Brick Attacker</h2>
<p class="text-xl mb-8 text-center max-w-md">Shoot the moving bricks before they reach the bottom!</p>
<button id="startButton" class="start-btn">
<i class="fas fa-play"></i> Start Game
</button>
</div>
<div id="gameOverScreen" class="game-overlay hidden">
<h2 class="text-4xl font-bold mb-4 text-red-500">Game Over</h2>
<p class="text-2xl mb-2">Your score: <span id="finalScore" class="text-yellow-300">0</span></p>
<button id="restartButton" class="start-btn mt-6">
<i class="fas fa-redo"></i> Play Again
</button>
</div>
</div>
<div class="mt-6 flex justify-center">
<div class="bg-gray-800 p-4 rounded-lg max-w-md">
<h3 class="text-white font-semibold mb-2">Controls:</h3>
<ul class="text-gray-300 space-y-1">
<li><i class="fas fa-mouse-pointer mr-2"></i> Move mouse to aim</li>
<li><i class="fas fa-mouse mr-2"></i> Click to shoot</li>
<li><i class="fas fa-arrows-alt mr-2"></i> Arrow keys to move</li>
</ul>
</div>
</div>
</div>
<script>
// Game variables
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startScreen = document.getElementById('startScreen');
const gameOverScreen = document.getElementById('gameOverScreen');
const startButton = document.getElementById('startButton');
const restartButton = document.getElementById('restartButton');
const scoreElement = document.getElementById('score');
const finalScoreElement = document.getElementById('finalScore');
const livesElement = document.getElementById('lives');
let gameRunning = false;
let score = 0;
let lives = 3;
let bricks = [];
let bullets = [];
let attackerX = canvas.width / 2;
let attackerWidth = 50;
let gunAngle = 0;
let mouseX = 0;
let mouseY = 0;
let animationId;
let brickSpeed = 2;
let brickSpawnRate = 60;
let frameCount = 0;
// Attacker element (for visual representation)
const attacker = document.createElement('div');
attacker.id = 'attacker';
document.querySelector('.game-container').appendChild(attacker);
const gun = document.createElement('div');
gun.id = 'gun';
attacker.appendChild(gun);
const gunBarrel = document.createElement('div');
gunBarrel.id = 'gun-barrel';
gun.appendChild(gunBarrel);
// Event listeners
startButton.addEventListener('click', startGame);
restartButton.addEventListener('click', startGame);
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
mouseX = e.clientX - rect.left;
mouseY = e.clientY - rect.top;
// Calculate gun angle based on mouse position
const dx = mouseX - (attackerX + attackerWidth / 2);
const dy = mouseY - (canvas.height - 90);
gunAngle = Math.atan2(dy, dx);
// Update gun position and rotation
gun.style.transform = `rotate(${gunAngle}rad)`;
});
canvas.addEventListener('click', shoot);
document.addEventListener('keydown', (e) => {
if (!gameRunning) return;
if (e.key === 'ArrowLeft') {
attackerX = Math.max(0, attackerX - 20);
} else if (e.key === 'ArrowRight') {
attackerX = Math.min(canvas.width - attackerWidth, attackerX + 20);
}
});
// Game functions
function startGame() {
gameRunning = true;
score = 0;
lives = 3;
bricks = [];
bullets = [];
brickSpeed = 2;
brickSpawnRate = 60;
frameCount = 0;
scoreElement.textContent = score;
updateLives();
startScreen.classList.add('hidden');
gameOverScreen.classList.add('hidden');
// Reset attacker position
attackerX = canvas.width / 2 - attackerWidth / 2;
// Start game loop
animationId = requestAnimationFrame(gameLoop);
}
function gameLoop() {
if (!gameRunning) return;
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Update attacker position
attacker.style.left = `${attackerX}px`;
// Spawn bricks
if (frameCount % brickSpawnRate === 0) {
spawnBrick();
}
// Update bricks
updateBricks();
// Update bullets
updateBullets();
// Check collisions
checkCollisions();
// Increase difficulty
if (frameCount % 500 === 0) {
brickSpeed = Math.min(brickSpeed + 0.2, 6);
brickSpawnRate = Math.max(brickSpawnRate - 5, 20);
}
frameCount++;
animationId = requestAnimationFrame(gameLoop);
}
function spawnBrick() {
const width = Math.random() * 60 + 40;
const x = Math.random() * (canvas.width - width);
const color = getRandomColor();
// 10% chance for special brick
const isSpecial = Math.random() < 0.1;
bricks.push({
x,
y: 0,
width,
height: 20,
color,
isSpecial,
health: isSpecial ? 3 : 1
});
}
function getRandomColor() {
const colors = [
'#f56565', // red
'#48bb78', // green
'#4299e1', // blue
'#ed8936', // orange
'#9f7aea', // purple
'#ecc94b' // yellow
];
return colors[Math.floor(Math.random() * colors.length)];
}
function updateBricks() {
for (let i = bricks.length - 1; i >= 0; i--) {
const brick = bricks[i];
// Move brick down
brick.y += brickSpeed;
// Draw brick
ctx.fillStyle = brick.color;
ctx.fillRect(brick.x, brick.y, brick.width, brick.height);
// Draw special effects
if (brick.isSpecial) {
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 2;
ctx.strokeRect(brick.x, brick.y, brick.width, brick.height);
// Draw health indicator
ctx.fillStyle = '#ffffff';
ctx.font = '10px Arial';
ctx.fillText('★'.repeat(brick.health), brick.x + 5, brick.y + 15);
}
// Remove bricks that go off screen
if (brick.y > canvas.height) {
bricks.splice(i, 1);
loseLife();
}
}
}
function updateBullets() {
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
// Move bullet
bullet.x += bullet.dx * 10;
bullet.y += bullet.dy * 10;
// Draw bullet
const bulletElement = document.createElement('div');
bulletElement.className = 'bullet';
bulletElement.style.left = `${bullet.x}px`;
bulletElement.style.top = `${bullet.y}px`;
document.querySelector('.game-container').appendChild(bulletElement);
// Remove bullet after a short delay to allow animation
setTimeout(() => {
if (bulletElement.parentNode) {
bulletElement.parentNode.removeChild(bulletElement);
}
}, 16);
// Remove bullets that go off screen
if (bullet.x < 0 || bullet.x > canvas.width ||
bullet.y < 0 || bullet.y > canvas.height) {
bullets.splice(i, 1);
}
}
}
function checkCollisions() {
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
for (let j = bricks.length - 1; j >= 0; j--) {
const brick = bricks[j];
if (bullet.x > brick.x && bullet.x < brick.x + brick.width &&
bullet.y > brick.y && bullet.y < brick.y + brick.height) {
// Hit brick
brick.health--;
if (brick.health <= 0) {
// Brick destroyed
bricks.splice(j, 1);
score += brick.isSpecial ? 5 : 1;
scoreElement.textContent = score;
}
// Remove bullet
bullets.splice(i, 1);
break;
}
}
}
}
function shoot() {
if (!gameRunning) return;
const startX = attackerX + attackerWidth / 2;
const startY = canvas.height - 90;
bullets.push({
x: startX,
y: startY,
dx: Math.cos(gunAngle),
dy: Math.sin(gunAngle)
});
}
function loseLife() {
lives--;
updateLives();
if (lives <= 0) {
gameOver();
}
}
function updateLives() {
livesElement.innerHTML = '';
for (let i = 0; i < lives; i++) {
const heart = document.createElement('i');
heart.className = 'fas fa-heart heart-icon';
livesElement.appendChild(heart);
}
}
function gameOver() {
gameRunning = false;
cancelAnimationFrame(animationId);
finalScoreElement.textContent = score;
gameOverScreen.classList.remove('hidden');
}
</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=Mohabedalgani/zaido" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>