Canvas залипаловка из тик-ток (Рейтинг: 0)
Сахар
07.02.2025 / 03:34
html+js код генератора залипаловки для вставки в видео для тт или рилсов. Настройка генератора производится путем редактирования констант.
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>Rotating Rings Game</title> <style> body { background: black; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; overflow: hidden; touch-action: none; } canvas { background: black; display: block; } #retryButton { display: none; position: absolute; top: 10px; padding: 10px 20px; font-size: 20px; cursor: pointer; background: white; border: none; border-radius: 5px; } </style> </head> <body> <canvas id="gameCanvas"></canvas> <button id="retryButton">Retry</button> <script> const canvas = document.getElementById("gameCanvas"); const ctx = canvas.getContext("2d"); let CENTER_X, CENTER_Y, BALL_RADIUS, RING_WIDTH, GAP_ANGLE, NUM_RINGS, GRAVITY, TRAIL_LENGTH, BOUNCE_REDUCTION; let rings = []; let ball; let gameOver = false; function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; CENTER_X = canvas.width / 2; CENTER_Y = canvas.height / 2; const minSize = Math.min(canvas.width, canvas.height); BALL_RADIUS = minSize * 0.015; RING_WIDTH = minSize * 0.005; GAP_ANGLE = 40; NUM_RINGS = 12; GRAVITY = minSize * 0.0003; TRAIL_LENGTH = 20; BOUNCE_REDUCTION = 0.99; resetGame(); } window.addEventListener("resize", resizeCanvas); class Ring { constructor(index) { this.radius = (Math.min(canvas.width, canvas.height) * 0.4) * (index / NUM_RINGS) + BALL_RADIUS * 3; this.angle = Math.random() * 360; this.speed = 0.5 + index * 0.05; this.color = "green"; } update() { this.angle = (this.angle + this.speed) % 360; } draw() { ctx.strokeStyle = this.color; ctx.lineWidth = RING_WIDTH; ctx.beginPath(); let startAngle = (this.angle + GAP_ANGLE) * (Math.PI / 180); let endAngle = (this.angle + 360) * (Math.PI / 180); ctx.arc(CENTER_X, CENTER_Y, this.radius, startAngle, endAngle); ctx.stroke(); } checkCollision(ball) { let distance = Math.hypot(ball.x - CENTER_X, ball.y - CENTER_Y); if (distance >= this.radius - BALL_RADIUS && distance <= this.radius + BALL_RADIUS) { let angleToBall = Math.atan2(ball.y - CENTER_Y, ball.x - CENTER_X) * (180 / Math.PI); if (angleToBall < 0) angleToBall += 360; if (angleToBall >= this.angle && angleToBall <= this.angle + GAP_ANGLE) { return "pass"; } else { return "hit"; } } return "none"; } reflectBall(ball) { let angle = Math.atan2(ball.y - CENTER_Y, ball.x - CENTER_X); let speed = Math.hypot(ball.vx, ball.vy) * BOUNCE_REDUCTION; let normal = angle + Math.PI / 2; let tangent = Math.atan2(ball.vy, ball.vx); let reflectAngle = 2 * normal - tangent; ball.vx = speed * Math.cos(reflectAngle); ball.vy = speed * Math.sin(reflectAngle); this.changeColor(); } changeColor() { const colors = ["red", "blue", "yellow", "cyan", "magenta", "lime"]; this.color = colors[Math.floor(Math.random() * colors.length)]; } } function resetGame() { rings = []; for (let i = 0; i < NUM_RINGS; i++) { rings.push(new Ring(i)); } ball = { x: CENTER_X, y: CENTER_Y, vx: (Math.random() - 0.5) * 5, vy: (Math.random() - 0.5) * 5, trail: [] }; gameOver = false; document.getElementById("retryButton").style.display = "none"; gameLoop(); } function updateBall() { if (gameOver) return; ball.x += ball.vx; ball.y += ball.vy; ball.vy += GRAVITY; ball.trail.push({ x: ball.x, y: ball.y }); if (ball.trail.length > TRAIL_LENGTH) { ball.trail.shift(); } for (let i = rings.length - 1; i >= 0; i--) { let ring = rings[i]; let collision = ring.checkCollision(ball); if (collision === "pass") { rings.splice(i, 1); } else if (collision === "hit") { ring.reflectBall(ball); } } if (ball.y + BALL_RADIUS >= canvas.height) { ball.y = canvas.height - BALL_RADIUS; ball.vy *= -BOUNCE_REDUCTION; } } function drawBall() { for (let i = 0; i < ball.trail.length; i++) { let alpha = i / ball.trail.length; ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`; let size = BALL_RADIUS * (i / ball.trail.length); ctx.beginPath(); ctx.arc(ball.trail[i].x, ball.trail[i].y, size, 0, Math.PI * 2); ctx.fill(); } ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(ball.x, ball.y, BALL_RADIUS, 0, Math.PI * 2); ctx.fill(); } function gameLoop() { ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); if (rings.length === 0) { ctx.fillStyle = "white"; ctx.font = `${Math.min(canvas.width, canvas.height) * 0.05}px Arial`; ctx.fillText("You Win!", CENTER_X - 80, CENTER_Y); document.getElementById("retryButton").style.display = "block"; gameOver = true; return; } for (let ring of rings) { ring.update(); ring.draw(); } updateBall(); drawBall(); requestAnimationFrame(gameLoop); } document.getElementById("retryButton").addEventListener("click", resetGame); resizeCanvas(); </script> </body> </html>
Рейтинг:
0
Коментарі (0)
»
Коментарів ще немає!
Для виконання дії необхідно авторизуватися!