Добавить breakout.html
This commit is contained in:
+154
@@ -0,0 +1,154 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Breakout</title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
background: #0a0a1a;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
font-family: 'Segoe UI', sans-serif;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
h1 { color: #00bfff; margin-bottom: 10px; text-shadow: 0 0 15px #00bfff; }
|
||||||
|
#stats { display: flex; gap: 20px; margin-bottom: 10px; font-size: 1.1em; }
|
||||||
|
canvas { border: 2px solid #00bfff; border-radius: 8px; box-shadow: 0 0 30px rgba(0,191,255,0.3); cursor: none; }
|
||||||
|
#info { margin-top: 10px; color: #888; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>🧱 Breakout</h1>
|
||||||
|
<div id="stats"><span>Счёт: <b id="sc">0</b></span><span>Жизни: <b id="lv">3</b></span></div>
|
||||||
|
<canvas id="game" width="480" height="360"></canvas>
|
||||||
|
<div id="info">Мышь / стрелки — управление платформой</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const canvas = document.getElementById('game');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const W = canvas.width, H = canvas.height;
|
||||||
|
|
||||||
|
let paddle, ball, bricks, score, lives, running, animId;
|
||||||
|
const brickRows = 5, brickCols = 8, brickW = 52, brickH = 18, brickPad = 5, brickOffTop = 30, brickOffLeft = 14;
|
||||||
|
const colors = ['#ff0040','#ff8800','#ffdd00','#00cc44','#0088ff'];
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
paddle = { x: W / 2 - 40, y: H - 25, w: 80, h: 12 };
|
||||||
|
ball = { x: W / 2, y: H - 40, r: 7, dx: 3, dy: -3 };
|
||||||
|
score = 0; lives = 3;
|
||||||
|
bricks = [];
|
||||||
|
for (let r = 0; r < brickRows; r++)
|
||||||
|
for (let c = 0; c < brickCols; c++)
|
||||||
|
bricks.push({ x: brickOffLeft + c * (brickW + brickPad), y: brickOffTop + r * (brickH + brickPad), w: brickW, h: brickH, alive: true, color: colors[r] });
|
||||||
|
running = true;
|
||||||
|
document.getElementById('sc').textContent = 0;
|
||||||
|
document.getElementById('lv').textContent = 3;
|
||||||
|
cancelAnimationFrame(animId);
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loop() {
|
||||||
|
update();
|
||||||
|
draw();
|
||||||
|
if (running) animId = requestAnimationFrame(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
if (!running) return;
|
||||||
|
ball.x += ball.dx;
|
||||||
|
ball.y += ball.dy;
|
||||||
|
if (ball.x - ball.r < 0 || ball.x + ball.r > W) ball.dx *= -1;
|
||||||
|
if (ball.y - ball.r < 0) ball.dy *= -1;
|
||||||
|
if (ball.y + ball.r > H) {
|
||||||
|
lives--;
|
||||||
|
document.getElementById('lv').textContent = lives;
|
||||||
|
if (lives <= 0) { running = false; return; }
|
||||||
|
ball.x = W / 2; ball.y = H - 40; ball.dx = 3 * (Math.random() > 0.5 ? 1 : -1); ball.dy = -3;
|
||||||
|
}
|
||||||
|
if (ball.y + ball.r >= paddle.y && ball.y + ball.r <= paddle.y + paddle.h &&
|
||||||
|
ball.x >= paddle.x && ball.x <= paddle.x + paddle.w) {
|
||||||
|
ball.dy = -Math.abs(ball.dy);
|
||||||
|
let hit = (ball.x - paddle.x) / paddle.w - 0.5;
|
||||||
|
ball.dx = hit * 6;
|
||||||
|
}
|
||||||
|
bricks.forEach(b => {
|
||||||
|
if (!b.alive) return;
|
||||||
|
if (ball.x + ball.r > b.x && ball.x - ball.r < b.x + b.w &&
|
||||||
|
ball.y + ball.r > b.y && ball.y - ball.r < b.y + b.h) {
|
||||||
|
b.alive = false;
|
||||||
|
ball.dy *= -1;
|
||||||
|
score += 10;
|
||||||
|
document.getElementById('sc').textContent = score;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (bricks.every(b => !b.alive)) { running = false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
ctx.fillStyle = '#0a0a1a';
|
||||||
|
ctx.fillRect(0, 0, W, H);
|
||||||
|
bricks.forEach(b => {
|
||||||
|
if (!b.alive) return;
|
||||||
|
ctx.fillStyle = b.color;
|
||||||
|
ctx.shadowColor = b.color;
|
||||||
|
ctx.shadowBlur = 8;
|
||||||
|
ctx.fillRect(b.x, b.y, b.w, b.h);
|
||||||
|
});
|
||||||
|
ctx.shadowBlur = 0;
|
||||||
|
ctx.fillStyle = '#00bfff';
|
||||||
|
ctx.shadowColor = '#00bfff';
|
||||||
|
ctx.shadowBlur = 15;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.shadowBlur = 0;
|
||||||
|
const pg = ctx.createLinearGradient(paddle.x, 0, paddle.x + paddle.w, 0);
|
||||||
|
pg.addColorStop(0, '#00bfff');
|
||||||
|
pg.addColorStop(1, '#0066cc');
|
||||||
|
ctx.fillStyle = pg;
|
||||||
|
ctx.shadowColor = '#00bfff';
|
||||||
|
ctx.shadowBlur = 10;
|
||||||
|
ctx.fillRect(paddle.x, paddle.y, paddle.w, paddle.h);
|
||||||
|
ctx.shadowBlur = 0;
|
||||||
|
if (!running) {
|
||||||
|
ctx.fillStyle = 'rgba(0,0,0,0.6)';
|
||||||
|
ctx.fillRect(0, 0, W, H);
|
||||||
|
ctx.fillStyle = '#00bfff';
|
||||||
|
ctx.font = 'bold 30px Segoe UI';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
const msg = bricks.every(b => !b.alive) ? '🎉 ПОБЕДА!' : 'GAME OVER';
|
||||||
|
ctx.fillText(msg, W / 2, H / 2 - 10);
|
||||||
|
ctx.fillStyle = '#fff';
|
||||||
|
ctx.font = '18px Segoe UI';
|
||||||
|
ctx.fillText('Счёт: ' + score + ' | Клик — заново', W / 2, H / 2 + 25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.addEventListener('mousemove', e => {
|
||||||
|
const rect = canvas.getBoundingClientRect();
|
||||||
|
paddle.x = (e.clientX - rect.left) * (W / rect.width) - paddle.w / 2;
|
||||||
|
paddle.x = Math.max(0, Math.min(W - paddle.w, paddle.x));
|
||||||
|
});
|
||||||
|
canvas.addEventListener('touchmove', e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const rect = canvas.getBoundingClientRect();
|
||||||
|
paddle.x = (e.touches[0].clientX - rect.left) * (W / rect.width) - paddle.w / 2;
|
||||||
|
paddle.x = Math.max(0, Math.min(W - paddle.w, paddle.x));
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
document.addEventListener('keydown', e => {
|
||||||
|
if (e.key === 'ArrowLeft') paddle.x = Math.max(0, paddle.x - 20);
|
||||||
|
if (e.key === 'ArrowRight') paddle.x = Math.min(W - paddle.w, paddle.x + 20);
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.addEventListener('click', () => { if (!running) init(); });
|
||||||
|
|
||||||
|
init();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user