先看效果
再上代码
<!DOCTYPE html>
<html>
<head><title>火柴人跑酷</title><style>body {margin: 0;overflow: hidden;background: #87CEEB;}#gameCanvas {background: linear-gradient(to bottom, #87CEEB 0%, #87CEEB 50%, #228B22 50%, #228B22 100%);}#ui {position: fixed;top: 20px;left: 20px;font-family: Arial;font-size: 24px;color: white;text-shadow: 2px 2px 4px rgba(0,0,0,0.5);}#gameOver {display: none;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);background: rgba(0,0,0,0.8);color: white;padding: 20px;text-align: center;border-radius: 10px;}</style>
</head>
<body><div id="ui">得分: <span id="score">0</span></div><div id="gameOver"><h2>游戏结束!</h2><p>最终得分: <span id="finalScore">0</span></p><button onclick="restartGame()">重玩</button></div><canvas id="gameCanvas"></canvas><script>const canvas = document.getElementById('gameCanvas');const ctx = canvas.getContext('2d');let canvasWidth = window.innerWidth;let canvasHeight = window.innerHeight;canvas.width = canvasWidth;canvas.height = canvasHeight;// 游戏参数let gameSpeed = 10;let isJumping = false;let isGameOver = false;let score = 0;let gravity = 0.8;let jumpForce = -21;let groundLevel = canvasHeight * 0.8;// 火柴人参数let stickman = {x: 100,y: groundLevel - 60,width: 40,height: 80,velocityY: 0,isOnGround: true};// 障碍物数组let obstacles = [];let obstacleTypes = [{ width: 30, height: 50 },{ width: 50, height: 30 },{ width: 40, height: 40 }];// 游戏循环function gameLoop() {if (!isGameOver) {ctx.clearRect(0, 0, canvasWidth, canvasHeight);updateStickman();updateObstacles();checkCollisions();drawGround();drawStickman();drawObstacles();updateScore();requestAnimationFrame(gameLoop);}}function drawStickman() {// 绘制火柴人ctx.fillStyle = '#000';// 身体ctx.beginPath();ctx.moveTo(stickman.x + stickman.width/2, stickman.y);ctx.lineTo(stickman.x + stickman.width/2, stickman.y + stickman.height);ctx.stroke();// 头部ctx.beginPath();ctx.arc(stickman.x + stickman.width/2, stickman.y - 10, 15, 0, Math.PI * 2);ctx.stroke();// 腿ctx.beginPath();ctx.moveTo(stickman.x + stickman.width/2, stickman.y + stickman.height);ctx.lineTo(stickman.x, stickman.y + stickman.height + 30);ctx.moveTo(stickman.x + stickman.width/2, stickman.y + stickman.height);ctx.lineTo(stickman.x + stickman.width, stickman.y + stickman.height + 30);ctx.stroke();}function updateStickman() {// 重力应用if (!stickman.isOnGround) {stickman.velocityY += gravity;stickman.y += stickman.velocityY;}// 地面检测if (stickman.y + stickman.height > groundLevel) {stickman.y = groundLevel - stickman.height;stickman.velocityY = 0;stickman.isOnGround = true;}}function drawGround() {ctx.fillStyle = '#228B22';ctx.fillRect(0, groundLevel, canvasWidth, canvasHeight - groundLevel);}function generateObstacle() {if (Math.random() < 0.02) {let type = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];obstacles.push({x: canvasWidth,y: groundLevel - type.height,width: type.width,height: type.height,passed: false});}}function updateObstacles() {generateObstacle();for (let i = obstacles.length - 1; i >= 0; i--) {obstacles[i].x -= gameSpeed;if (obstacles[i].x + obstacles[i].width < 0) {obstacles.splice(i, 1);}}}function drawObstacles() {ctx.fillStyle = '#8B4513';obstacles.forEach(obstacle => {ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);});}function checkCollisions() {obstacles.forEach(obstacle => {if (stickman.x < obstacle.x + obstacle.width &&stickman.x + stickman.width > obstacle.x &&stickman.y < obstacle.y + obstacle.height &&stickman.y + stickman.height > obstacle.y) {gameOver();}if (!obstacle.passed && obstacle.x + obstacle.width < stickman.x) {obstacle.passed = true;score += 10;}});}function updateScore() {document.getElementById('score').textContent = score;gameSpeed += 0.001;}function gameOver() {isGameOver = true;document.getElementById('gameOver').style.display = 'block';document.getElementById('finalScore').textContent = score;}function restartGame() {isGameOver = false;score = 0;gameSpeed = 10;obstacles = [];stickman.y = groundLevel - 60;stickman.velocityY = 0;document.getElementById('gameOver').style.display = 'none';gameLoop();}// 事件监听document.addEventListener('keydown', (e) => {if ((e.code === 'Space' || e.code === 'ArrowUp') && stickman.isOnGround) {stickman.velocityY = jumpForce;stickman.isOnGround = false;}});// 窗口调整window.addEventListener('resize', () => {canvasWidth = window.innerWidth;canvasHeight = window.innerHeight;canvas.width = canvasWidth;canvas.height = canvasHeight;groundLevel = canvasHeight * 0.8;});// 启动游戏gameLoop();</script>
</body>
</html>