| | <!DOCTYPE html> |
| | <html lang="en"> |
| | <head> |
| | <meta charset="UTF-8"> |
| | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | <title>Slither Game</title> |
| | <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> |
| | <style> |
| | body { |
| | margin: 0; |
| | overflow: hidden; |
| | background: #000; |
| | } |
| | canvas { |
| | display: block; |
| | } |
| | </style> |
| | </head> |
| | <body> |
| | <canvas id="gameCanvas"></canvas> |
| | |
| | <script> |
| | const canvas = document.getElementById('gameCanvas'); |
| | const ctx = canvas.getContext('2d'); |
| | |
| | canvas.width = window.innerWidth; |
| | canvas.height = window.innerHeight; |
| | |
| | |
| | const player = { |
| | x: canvas.width / 2, |
| | y: canvas.height / 2, |
| | size: 10, |
| | speed: 3, |
| | trail: [], |
| | maxTrail: 100, |
| | color: '#00FF00' |
| | }; |
| | |
| | const food = { |
| | x: Math.random() * canvas.width, |
| | y: Math.random() * canvas.height, |
| | size: 5, |
| | color: '#FF0000' |
| | }; |
| | |
| | let direction = { x: 0, y: 0 }; |
| | |
| | |
| | window.addEventListener('mousemove', (e) => { |
| | const angle = Math.atan2(e.clientY - player.y, e.clientX - player.x); |
| | direction.x = Math.cos(angle) * player.speed; |
| | direction.y = Math.sin(angle) * player.speed; |
| | }); |
| | |
| | |
| | window.addEventListener('touchmove', (e) => { |
| | e.preventDefault(); |
| | const touch = e.touches[0]; |
| | const angle = Math.atan2(touch.clientY - player.y, touch.clientX - player.x); |
| | direction.x = Math.cos(angle) * player.speed; |
| | direction.y = Math.sin(angle) * player.speed; |
| | }); |
| | |
| | function gameLoop() { |
| | |
| | ctx.fillStyle = '#000'; |
| | ctx.fillRect(0, 0, canvas.width, canvas.height); |
| | |
| | |
| | player.x += direction.x; |
| | player.y += direction.y; |
| | |
| | |
| | if (player.x < 0) player.x = canvas.width; |
| | if (player.x > canvas.width) player.x = 0; |
| | if (player.y < 0) player.y = canvas.height; |
| | if (player.y > canvas.height) player.y = 0; |
| | |
| | |
| | player.trail.push({ x: player.x, y: player.y }); |
| | if (player.trail.length > player.maxTrail) { |
| | player.trail.shift(); |
| | } |
| | |
| | |
| | for (let i = 0; i < player.trail.length; i++) { |
| | const segment = player.trail[i]; |
| | const size = player.size * (i / player.trail.length); |
| | ctx.fillStyle = player.color; |
| | ctx.beginPath(); |
| | ctx.arc(segment.x, segment.y, size, 0, Math.PI * 2); |
| | ctx.fill(); |
| | } |
| | |
| | |
| | ctx.fillStyle = player.color; |
| | ctx.beginPath(); |
| | ctx.arc(player.x, player.y, player.size, 0, Math.PI * 2); |
| | ctx.fill(); |
| | |
| | |
| | ctx.fillStyle = food.color; |
| | ctx.beginPath(); |
| | ctx.arc(food.x, food.y, food.size, 0, Math.PI * 2); |
| | ctx.fill(); |
| | |
| | |
| | const dist = Math.sqrt( |
| | Math.pow(player.x - food.x, 2) + |
| | Math.pow(player.y - food.y, 2) |
| | ); |
| | |
| | if (dist < player.size + food.size) { |
| | |
| | player.maxTrail += 50; |
| | |
| | |
| | food.x = Math.random() * canvas.width; |
| | food.y = Math.random() * canvas.height; |
| | } |
| | |
| | requestAnimationFrame(gameLoop); |
| | } |
| | |
| | gameLoop(); |
| | |
| | |
| | window.addEventListener('resize', () => { |
| | canvas.width = window.innerWidth; |
| | canvas.height = window.innerHeight; |
| | }); |
| | </script> |
| | </body> |
| | </html> |