import { useEffect, useRef, useState } from "react"; export default function EndlessRunner() { const canvasRef = useRef(null); const [running, setRunning] = useState(true); const player = { x: 50, y: 150, width: 20, height: 20, dy: 0 }; const gravity = 0.5; let obstacles = []; let score = 0; useEffect(() => { const canvas = canvasRef.current; const ctx = canvas.getContext("2d"); canvas.width = window.innerWidth; canvas.height = 300; function update() { if (!running) return; ctx.clearRect(0, 0, canvas.width, canvas.height); // Player physics player.dy += gravity; player.y += player.dy; if (player.y > 150) { player.y = 150; player.dy = 0; } // Draw player ctx.fillStyle = "blue"; ctx.fillRect(player.x, player.y, player.width, player.height); // Obstacles if (Math.random() < 0.02) { obstacles.push({ x: canvas.width, y: 150, width: 20, height: 20 }); } obstacles = obstacles.map(obstacle => ({ ...obstacle, x: obstacle.x - 5 })); obstacles = obstacles.filter(obstacle => obstacle.x + obstacle.width > 0); obstacles.forEach(obstacle => { ctx.fillStyle = "red"; ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height); // Collision detection if ( player.x < obstacle.x + obstacle.width && player.x + player.width > obstacle.x && player.y < obstacle.y + obstacle.height && player.y + player.height > obstacle.y ) { setRunning(false); } }); // Score score++; ctx.fillStyle = "black"; ctx.fillText("Score: " + score, 10, 20); requestAnimationFrame(update); } update(); }, [running]); function jump() { if (player.y >= 150) { player.dy = -10; } } return (
{!running && }
); }