// Wormate.io clone game logic const socket = io('https://wormate.io'); // Connect to wormate.io server const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreDisplay = document.getElementById('score-display'); const leaderboard = document.getElementById('leaderboard'); const playBtn = document.getElementById('play-btn'); // Set canvas to full window size function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', resizeCanvas); resizeCanvas(); // Game state let gameStarted = false; let playerId = null; let players = {}; let foods = [ { x: Math.random() * canvas.width, y: Math.random() * canvas.height, radius: 10, color: getRandomColor() } ]; let powerUps = []; let score = 0; // Player controls const keys = { ArrowUp: false, ArrowDown: false, ArrowLeft: false, ArrowRight: false }; // Handle keyboard input window.addEventListener('keydown', (e) => { if (keys.hasOwnProperty(e.key)) { keys[e.key] = true; e.preventDefault(); } }); window.addEventListener('keyup', (e) => { if (keys.hasOwnProperty(e.key)) { keys[e.key] = false; e.preventDefault(); } }); // Socket event handlers socket.on('connect', () => { playerId = socket.id; console.log('Connected to server with ID:', playerId); }); socket.on('gameState', (gameState) => { players = gameState.players; foods = gameState.foods; powerUps = gameState.powerUps; if (players[playerId]) { score = players[playerId].score; scoreDisplay.textContent = `Score: ${score}`; } updateLeaderboard(); renderGame(); }); socket.on('playerDied', (data) => { if (data.playerId === playerId) { gameStarted = false; playBtn.style.display = 'block'; alert(`Game Over! Your score: ${score}`); } }); // Game loop function gameLoop() { if (gameStarted) { const direction = getDirection(); socket.emit('playerInput', direction); } requestAnimationFrame(gameLoop); } gameLoop(); // Helper functions function getDirection() { if (keys.ArrowUp) return 'up'; if (keys.ArrowDown) return 'down'; if (keys.ArrowLeft) return 'left'; if (keys.ArrowRight) return 'right'; return null; } function updateLeaderboard() { const sortedPlayers = Object.values(players).sort((a, b) => b.score - a.score); leaderboard.innerHTML = '

Leaderboard

' + sortedPlayers.map(p => `
${p.name} ${p.score}
` ).join(''); } function renderGame() { // Clear canvas ctx.fillStyle = '#1a1a2e'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw foods foods.forEach(food => { ctx.fillStyle = food.color; ctx.beginPath(); ctx.arc(food.x, food.y, food.radius, 0, Math.PI * 2); ctx.fill(); }); // Draw power-ups powerUps.forEach(powerUp => { ctx.save(); ctx.translate(powerUp.x, powerUp.y); ctx.rotate(Date.now() / 200); ctx.fillStyle = powerUp.color; ctx.fillRect(-powerUp.size/2, -powerUp.size/2, powerUp.size, powerUp.size); ctx.restore(); }); // Draw players Object.values(players).forEach(player => { // Draw worm segments player.segments.forEach((segment, i) => { const gradient = ctx.createRadialGradient( segment.x, segment.y, 0, segment.x, segment.y, segment.radius ); gradient.addColorStop(0, player.color); gradient.addColorStop(1, darkenColor(player.color, 0.3)); ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(segment.x, segment.y, segment.radius, 0, Math.PI * 2); ctx.fill(); // Draw eyes on head if (i === 0) { const angle = Math.atan2( player.segments[1].y - segment.y, player.segments[1].x - segment.x ); const eyeRadius = segment.radius * 0.3; const eyeOffset = segment.radius * 0.6; // Left eye ctx.fillStyle = 'white'; ctx.beginPath(); ctx.arc( segment.x + Math.cos(angle + Math.PI/2) * eyeOffset, segment.y + Math.sin(angle + Math.PI/2) * eyeOffset, eyeRadius, 0, Math.PI * 2 ); ctx.fill(); // Right eye ctx.beginPath(); ctx.arc( segment.x + Math.cos(angle - Math.PI/2) * eyeOffset, segment.y + Math.sin(angle - Math.PI/2) * eyeOffset, eyeRadius, 0, Math.PI * 2 ); ctx.fill(); // Pupils ctx.fillStyle = 'black'; ctx.beginPath(); ctx.arc( segment.x + Math.cos(angle + Math.PI/2) * eyeOffset + Math.cos(angle) * eyeRadius/2, segment.y + Math.sin(angle + Math.PI/2) * eyeOffset + Math.sin(angle) * eyeRadius/2, eyeRadius/2, 0, Math.PI * 2 ); ctx.fill(); ctx.beginPath(); ctx.arc( segment.x + Math.cos(angle - Math.PI/2) * eyeOffset + Math.cos(angle) * eyeRadius/2, segment.y + Math.sin(angle - Math.PI/2) * eyeOffset + Math.sin(angle) * eyeRadius/2, eyeRadius/2, 0, Math.PI * 2 ); ctx.fill(); } }); // Draw player name if (player.segments.length > 0) { const head = player.segments[0]; ctx.fillStyle = 'white'; ctx.font = '12px "Press Start 2P", cursive'; ctx.textAlign = 'center'; ctx.fillText(player.name, head.x, head.y - head.radius - 10); } }); } function darkenColor(color, amount) { // Convert hex to RGB let r = parseInt(color.substr(1, 2), 16); let g = parseInt(color.substr(3, 2), 16); let b = parseInt(color.substr(5, 2), 16); // Darken each component r = Math.max(0, Math.floor(r * (1 - amount))); g = Math.max(0, Math.floor(g * (1 - amount))); b = Math.max(0, Math.floor(b * (1 - amount))); // Convert back to hex return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`; } // Start game playBtn.addEventListener('click', () => { const playerName = prompt('Enter your name:', 'Player' + Math.floor(Math.random() * 1000)); if (playerName) { socket.emit('joinGame', { name: playerName, color: getRandomColor() }); gameStarted = true; playBtn.style.display = 'none'; } }); function getRandomColor() { const colors = [ '#FF5252', '#FF4081', '#E040FB', '#7C4DFF', '#536DFE', '#448AFF', '#40C4FF', '#18FFFF', '#64FFDA', '#69F0AE', '#B2FF59', '#EEFF41', '#FFFF00', '#FFD740', '#FFAB40', '#FF6E40' ]; return colors[Math.floor(Math.random() * colors.length)]; }