qween3made / index.html
offerpk3's picture
Update index.html
cfeb181 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Breakout Game</title>
<style>
body {
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
font-family: 'Arial', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
color: white;
}
.game-container {
text-align: center;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
position: relative;
}
canvas {
border: 3px solid #00d4ff;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 212, 255, 0.3);
background: linear-gradient(180deg, #0a0a0a, #1a1a1a);
}
.ui {
margin-top: 15px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 18px;
font-weight: bold;
}
.controls {
margin-top: 10px;
font-size: 14px;
opacity: 0.8;
}
.powerup-info {
margin-top: 10px;
font-size: 14px;
opacity: 0.7;
}
.game-over, .game-won {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
padding: 30px;
border-radius: 15px;
text-align: center;
display: none;
border: 2px solid #00d4ff;
z-index: 10;
}
.restart-btn {
background: linear-gradient(45deg, #00d4ff, #0099cc);
border: none;
padding: 12px 24px;
border-radius: 8px;
color: white;
font-size: 16px;
cursor: pointer;
margin-top: 15px;
transition: transform 0.2s;
}
.restart-btn:hover {
transform: scale(1.05);
}
.upgrade-menu {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.95);
padding: 25px;
border-radius: 15px;
text-align: center;
border: 2px solid #00d4ff;
display: none;
z-index: 10;
}
.upgrade-option {
margin: 15px 0;
padding: 10px 20px;
background: rgba(255, 255, 255, 0.1);
border-radius: 8px;
cursor: pointer;
transition: transform 0.2s;
}
.upgrade-option:hover {
transform: scale(1.05);
}
</style>
</head>
<body>
<div class="game-container">
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div class="ui">
<div>Score: <span id="score">0</span></div>
<div>Lives: <span id="lives">3</span></div>
<div>Level: <span id="level">1</span></div>
</div>
<div class="controls">
Use A/D or Arrow Keys to move paddle • Click to start/restart
</div>
<div class="powerup-info" id="powerupInfo">
Powerups: <span id="powerups">None active</span>
</div>
<div class="game-over" id="gameOver">
<h2>Game Over!</h2>
<p>Final Score: <span id="finalScore">0</span></p>
<button class="restart-btn" onclick="restartGame()">Play Again</button>
</div>
<div class="game-won" id="gameWon">
<h2>Congratulations!</h2>
<p>You cleared all blocks!</p>
<p>Final Score: <span id="winScore">0</span></p>
<button class="restart-btn" onclick="showUpgradeMenu()">Next Level</button>
</div>
<div class="upgrade-menu" id="upgradeMenu">
<h2>Select Upgrade</h2>
<div class="upgrade-option" onclick="selectUpgrade('ballSpeed')">Increase Ball Speed</div>
<div class="upgrade-option" onclick="selectUpgrade('paddleWidth')">Wider Paddle</div>
<div class="upgrade-option" onclick="selectUpgrade('extraLife')">Extra Life</div>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Game state
let gameState = 'waiting'; // waiting, playing, gameOver, won, upgrading
let score = 0;
let lives = 3;
let level = 1;
let coins = 0;
// Paddle
const paddle = {
x: canvas.width / 2 - 60,
y: canvas.height - 30,
width: 120,
height: 15,
speed: 8,
originalWidth: 120
};
// Ball
const ball = {
x: canvas.width / 2,
y: canvas.height / 2,
radius: 8,
dx: 4,
dy: -4,
baseSpeed: 4,
speed: 4
};
// Blocks
let blocks = [];
const blockRows = 6;
const blockCols = 10;
const blockColors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4', '#feca57', '#ff9ff3'];
// Powerups
let powerups = [];
let activePowerups = [];
let powerupInterval = null;
// Particles
let particles = [];
// Input handling
const keys = {};
document.addEventListener('keydown', (e) => {
keys[e.key.toLowerCase()] = true;
});
document.addEventListener('keyup', (e) => {
keys[e.key.toLowerCase()] = false;
});
canvas.addEventListener('click', () => {
if (gameState === 'waiting') {
startGame();
}
});
// Initialize blocks
function createBlocks() {
blocks = [];
const blockWidth = canvas.width / blockCols;
const blockHeight = 25;
for (let row = 0; row < blockRows; row++) {
for (let col = 0; col < blockCols; col++) {
blocks.push({
x: col * blockWidth,
y: row * blockHeight + 60,
width: blockWidth - 2,
height: blockHeight - 2,
color: blockColors[row],
points: (blockRows - row) * 10,
visible: true,
hasPowerup: Math.random() < 0.15 // 15% chance for powerup
});
}
}
}
// Start game
function startGame() {
gameState = 'playing';
ball.x = canvas.width / 2;
ball.y = canvas.height / 2;
ball.dx = (Math.random() > 0.5 ? 1 : -1) * ball.speed;
ball.dy = -ball.speed;
}
// Update paddle
function updatePaddle() {
if (keys['arrowleft'] || keys['a']) {
paddle.x = Math.max(0, paddle.x - paddle.speed);
}
if (keys['arrowright'] || keys['d']) {
paddle.x = Math.min(canvas.width - paddle.width, paddle.x + paddle.speed);
}
}
// Update ball
function updateBall() {
if (gameState !== 'playing') return;
ball.x += ball.dx;
ball.y += ball.dy;
// Wall collisions
if (ball.x <= ball.radius || ball.x >= canvas.width - ball.radius) {
ball.dx = -ball.dx;
ball.x = Math.max(ball.radius, Math.min(canvas.width - ball.radius, ball.x));
}
if (ball.y <= ball.radius) {
ball.dy = -ball.dy;
ball.y = ball.radius;
}
// Paddle collision
if (ball.y + ball.radius >= paddle.y &&
ball.x >= paddle.x &&
ball.x <= paddle.x + paddle.width &&
ball.dy > 0) {
const hitPos = (ball.x - paddle.x) / paddle.width;
const angle = (hitPos - 0.5) * Math.PI / 3;
const speed = Math.sqrt(ball.dx * ball.dx + ball.dy * ball.dy);
ball.dx = Math.sin(angle) * speed;
ball.dy = -Math.abs(Math.cos(angle) * speed);
ball.y = paddle.y - ball.radius;
}
// Block collisions
for (let block of blocks) {
if (!block.visible) continue;
if (ball.x + ball.radius >= block.x &&
ball.x - ball.radius <= block.x + block.width &&
ball.y + ball.radius >= block.y &&
ball.y - ball.radius <= block.y + block.height) {
block.visible = false;
score += block.points;
// Check if block had a powerup
if (block.hasPowerup) {
spawnPowerup(block.x + block.width/2, block.y + block.height/2);
}
// Determine collision side
const ballCenterX = ball.x;
const ballCenterY = ball.y;
const blockCenterX = block.x + block.width / 2;
const blockCenterY = block.y + block.height / 2;
const deltaX = ballCenterX - blockCenterX;
const deltaY = ballCenterY - blockCenterY;
if (Math.abs(deltaX / block.width) > Math.abs(deltaY / block.height)) {
ball.dx = -ball.dx;
} else {
ball.dy = -ball.dy;
}
// Create particle effect
createParticles(block.x + block.width/2, block.y + block.height/2, block.color);
break;
}
}
// Ball out of bounds
if (ball.y > canvas.height) {
lives--;
if (lives <= 0) {
gameState = 'gameOver';
document.getElementById('finalScore').textContent = score;
document.getElementById('gameOver').style.display = 'block';
} else {
resetBallAndPaddle();
gameState = 'waiting';
}
}
// Check win condition
if (blocks.every(block => !block.visible)) {
gameState = 'won';
document.getElementById('winScore').textContent = score;
document.getElementById('gameWon').style.display = 'block';
}
}
// Powerups
function spawnPowerup(x, y) {
const types = ['expandPaddle', 'fastBall', 'slowBall'];
const type = types[Math.floor(Math.random() * types.length)];
powerups.push({
x: x,
y: y,
dy: 2,
type: type,
width: 20,
height: 20,
color: {
'expandPaddle': '#4ecdc4',
'fastBall': '#ff9ff3',
'slowBall': '#feca57'
}[type]
});
}
function updatePowerups() {
for (let i = powerups.length - 1; i >= 0; i--) {
const p = powerups[i];
p.y += p.dy;
// Paddle collision
if (p.y + p.height >= paddle.y &&
p.x + p.width/2 >= paddle.x &&
p.x - p.width/2 <= paddle.x + paddle.width) {
activatePowerup(p.type);
powerups.splice(i, 1);
continue;
}
// Remove off screen
if (p.y > canvas.height) {
powerups.splice(i, 1);
}
}
}
function activatePowerup(type) {
let duration = 10000; // 10 seconds
// Deactivate same type if already active
activePowerups = activePowerups.filter(p => p.type !== type);
activePowerups.push({type, timer: 0});
switch(type) {
case 'expandPaddle':
paddle.width = paddle.originalWidth * 1.5;
setTimeout(() => {
paddle.width = paddle.originalWidth;
updateActivePowerupsDisplay();
}, duration);
break;
case 'fastBall':
ball.speed *= 1.5;
setTimeout(() => {
ball.speed /= 1.5;
updateActivePowerupsDisplay();
}, duration);
break;
case 'slowBall':
ball.speed *= 0.66;
setTimeout(() => {
ball.speed /= 0.66;
updateActivePowerupsDisplay();
}, duration);
break;
}
updateActivePowerupsDisplay();
}
function updateActivePowerupsDisplay() {
const names = {
'expandPaddle': 'Wide Paddle',
'fastBall': 'Fast Ball',
'slowBall': 'Slow Ball'
};
if (activePowerups.length > 0) {
const activeNames = activePowerups.map(p => names[p.type]).join(', ');
document.getElementById('powerups').textContent = activeNames;
} else {
document.getElementById('powerups').textContent = 'None active';
}
}
// Particle system
function createParticles(x, y, color) {
for (let i = 0; i < 8; i++) {
particles.push({
x: x,
y: y,
dx: (Math.random() - 0.5) * 6,
dy: (Math.random() - 0.5) * 6,
life: 30,
maxLife: 30,
color: color
});
}
}
function updateParticles() {
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.x += p.dx;
p.y += p.dy;
p.life--;
if (p.life <= 0) {
particles.splice(i, 1);
}
}
}
// Reset ball and paddle
function resetBallAndPaddle() {
ball.x = canvas.width / 2;
ball.y = canvas.height / 2;
paddle.x = canvas.width / 2 - paddle.width / 2;
}
// Restart game
function restartGame() {
if (gameState === 'won') {
level++;
ball.baseSpeed += 0.5;
} else {
score = 0;
lives = 3;
level = 1;
ball.baseSpeed = 4;
}
ball.speed = ball.baseSpeed;
gameState = 'waiting';
createBlocks();
resetBallAndPaddle();
document.getElementById('gameOver').style.display = 'none';
document.getElementById('gameWon').style.display = 'none';
}
function showUpgradeMenu() {
gameState = 'upgrading';
document.getElementById('upgradeMenu').style.display = 'block';
}
function selectUpgrade(type) {
document.getElementById('upgradeMenu').style.display = 'none';
gameState = 'waiting';
switch(type) {
case 'ballSpeed':
ball.baseSpeed += 1;
ball.speed = ball.baseSpeed;
break;
case 'paddleWidth':
paddle.originalWidth = Math.min(paddle.originalWidth * 1.2, canvas.width * 0.6);
paddle.width = paddle.originalWidth;
break;
case 'extraLife':
lives = Math.min(lives + 1, 5);
break;
}
restartGame();
}
// Render functions
function drawPaddle() {
const gradient = ctx.createLinearGradient(paddle.x, paddle.y, paddle.x, paddle.y + paddle.height);
gradient.addColorStop(0, '#00d4ff');
gradient.addColorStop(1, '#0099cc');
ctx.fillStyle = gradient;
ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 2;
ctx.strokeRect(paddle.x, paddle.y, paddle.width, paddle.height);
}
function drawBall() {
const gradient = ctx.createRadialGradient(ball.x, ball.y, 0, ball.x, ball.y, ball.radius);
gradient.addColorStop(0, '#ffffff');
gradient.addColorStop(1, '#00d4ff');
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = gradient;
ctx.fill();
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 2;
ctx.stroke();
}
function drawBlocks() {
for (let block of blocks) {
if (!block.visible) continue;
const gradient = ctx.createLinearGradient(block.x, block.y, block.x, block.y + block.height);
gradient.addColorStop(0, block.color);
gradient.addColorStop(1, darkenColor(block.color, 0.3));
ctx.fillStyle = gradient;
ctx.fillRect(block.x, block.y, block.width, block.height);
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 1;
ctx.strokeRect(block.x, block.y, block.width, block.height);
// Draw powerup indicator
if (block.hasPowerup) {
ctx.beginPath();
ctx.arc(block.x + block.width/2, block.y + block.height/2, 5, 0, Math.PI*2);
ctx.fillStyle = '#ffff00';
ctx.fill();
}
}
}
function drawPowerups() {
for (let p of powerups) {
ctx.beginPath();
ctx.rect(p.x - p.width/2, p.y - p.height/2, p.width, p.height);
ctx.fillStyle = p.color;
ctx.fill();
// Add glow effect
ctx.shadowBlur = 10;
ctx.shadowColor = p.color;
ctx.beginPath();
ctx.rect(p.x - p.width/2, p.y - p.height/2, p.width, p.height);
ctx.fillStyle = p.color;
ctx.fill();
ctx.shadowBlur = 0;
}
}
function drawParticles() {
for (let p of particles) {
const alpha = p.life / p.maxLife;
ctx.save();
ctx.globalAlpha = alpha;
ctx.fillStyle = p.color;
ctx.beginPath();
ctx.arc(p.x, p.y, 3, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
}
function darkenColor(color, factor) {
const hex = color.replace('#', '');
const r = Math.floor(parseInt(hex.substr(0, 2), 16) * (1 - factor));
const g = Math.floor(parseInt(hex.substr(2, 2), 16) * (1 - factor));
const b = Math.floor(parseInt(hex.substr(4, 2), 16) * (1 - factor));
return `rgb(${r}, ${g}, ${b})`;
}
// Game loop
function gameLoop() {
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Update
updatePaddle();
updateBall();
updatePowerups();
updateParticles();
// Draw
drawBlocks();
drawPowerups();
drawPaddle();
drawBall();
drawParticles();
// Draw start message
if (gameState === 'waiting') {
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.font = '24px Arial';
ctx.textAlign = 'center';
ctx.fillText('Click to Start', canvas.width / 2, canvas.height / 2 + 50);
}
// Update UI
document.getElementById('score').textContent = score;
document.getElementById('lives').textContent = lives;
document.getElementById('level').textContent = level;
requestAnimationFrame(gameLoop);
}
// Initialize game
createBlocks();
gameLoop();
</script>
</body>
</html>