🎮ArcadeLab

天天酷跑

by ShadowCoder44
522 lines17.9 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>天天酷跑</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: #2c3e50;
            font-family: "Microsoft Yahei", sans-serif;
        }
        #gameCanvas {
            border: 3px solid #fff;
            border-radius: 8px;
            background: linear-gradient(#74b9ff 0%, #a29bfe 60%, #fdcb6e 100%);
            cursor: pointer;
        }
    </style>
</head>
<body>
    <canvas id="gameCanvas" width="480" height="700"></canvas>
    <!-- 欢快风格背景音乐 -->
    <audio id="bgm" loop preload="auto">
        <source src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3" type="audio/mpeg">
    

    <script>
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const bgm = document.getElementById('bgm');
        const W = canvas.width;
        const H = canvas.height;

        // 游戏状态
        let gameState = 'start';
        let score = 0;
        let coinCount = 0;
        let gameSpeed = 1.5;
        const maxGameSpeed = 2.8;
        let frameCount = 0;
        let nextObstacleFrame = 0;

        // 地面参数
        const groundHeight = 100;
        const groundY = H - groundHeight;
        let groundOffset = 0;

        // 玩家对象
        const player = {
            x: 80,
            y: groundY - 80,
            width: 50,
            height: 80,
            velocityY: 0,
            gravity: 0.25,
            jumpPower: -8,
            jumpCount: 0,
            maxJump: 2,
            landSmoothRange: 12,
            // 飞行属性 - 延长至8秒
            isFlying: false,
            flyDuration: 480, // 8秒(60帧/秒)
            flyTimer: 0,
            flyTargetY: groundY - 180,
            // 护盾属性 - 延长至10秒
            hasShield: false,
            shieldDuration: 600, // 10秒
            shieldTimer: 0
        };

        // 实体数组
        let obstacles = [];
        let coins = [];
        let powerups = [];

        // 初始化游戏
        function initGame() {
            score = 0;
            coinCount = 0;
            gameSpeed = 1.5;
            frameCount = 0;
            nextObstacleFrame = 180;
            obstacles = [];
            coins = [];
            powerups = [];
            player.y = groundY - player.height;
            player.velocityY = 0;
            player.jumpCount = 0;
            player.isFlying = false;
            player.flyTimer = 0;
            player.hasShield = false;
            player.shieldTimer = 0;
        }

        // 跳跃
        function jump() {
            if (gameState === 'start') {
                gameState = 'playing';
                initGame();
                bgm.play().catch(() => {});
                return;
            }
            if (gameState === 'over') {
                gameState = 'start';
                bgm.pause();
                bgm.currentTime = 0;
                return;
            }
            
            if (!player.isFlying && player.jumpCount < player.maxJump) {
                player.velocityY = player.jumpPower;
                player.jumpCount++;
            }
        }

        // 生成随机障碍物
        function spawnObstacle() {
            const width = 35 + Math.random() * 15;
            const height = 45 + Math.random() * 25;
            obstacles.push({
                x: W,
                y: groundY - height,
                width: width,
                height: height,
                type: 'ground'
            });
            const minInterval = 230;
            const maxInterval = 370;
            const randomInterval = minInterval + Math.random() * (maxInterval - minInterval);
            nextObstacleFrame = frameCount + Math.floor(randomInterval);
        }

        // 生成金币
        function spawnCoin() {
            const y = groundY - 120 - Math.random() * 100;
            coins.push({
                x: W,
                y: y,
                radius: 15
            });
        }

        // 生成随机道具
        function spawnPowerup() {
            const types = ['fly', 'shield'];
            const type = types[Math.floor(Math.random() * types.length)];
            const y = groundY - 130 - Math.random() * 80;
            powerups.push({
                x: W,
                y: y,
                radius: 18,
                type: type
            });
        }

        // 碰撞检测
        function checkCollision(rect1, rect2) {
            return rect1.x < rect2.x + rect2.width &&
                   rect1.x + rect1.width > rect2.x &&
                   rect1.y < rect2.y + rect2.height &&
                   rect1.y + rect1.height > rect2.y;
        }

        // 更新游戏逻辑
        function update() {
            if (gameState !== 'playing') return;

            frameCount++;
            score += 1;
            
            if (frameCount % 1500 === 0 && gameSpeed < maxGameSpeed) {
                gameSpeed += 0.1;
            }

            groundOffset -= gameSpeed;
            if (groundOffset <= -W) {
                groundOffset = 0;
            }

            // 飞行状态处理
            if (player.isFlying) {
                player.flyTimer--;
                if (player.flyTimer <= 0) {
                    player.isFlying = false;
                    player.velocityY = 0;
                } else {
                    player.velocityY = 0;
                    player.y += (player.flyTargetY - player.y) * 0.05;
                }
            }

            // 护盾状态处理
            if (player.hasShield) {
                player.shieldTimer--;
                if (player.shieldTimer <= 0) {
                    player.hasShield = false;
                }
            }

            // 玩家物理
            if (!player.isFlying) {
                player.velocityY += player.gravity;
            }
            player.y += player.velocityY;

            // 落地滑行缓冲
            if (!player.isFlying) {
                const distanceToGround = groundY - (player.y + player.height);
                if (distanceToGround < player.landSmoothRange && distanceToGround > 0 && player.velocityY > 0) {
                    player.velocityY *= 0.65;
                }

                if (player.y + player.height >= groundY) {
                    player.y = groundY - player.height;
                    player.velocityY = 0;
                    player.jumpCount = 0;
                }
            }

            // 生成障碍物
            if (frameCount >= nextObstacleFrame) {
                spawnObstacle();
            }

            // 生成金币
            if (frameCount % 160 === 0) {
                spawnCoin();
            }

            // 生成道具
            if (frameCount % 350 === 0 && Math.random() > 0.3) {
                spawnPowerup();
            }

            // 更新障碍物
            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);
                    continue;
                }

                const playerRect = {
                    x: player.x + 10,
                    y: player.y + 10,
                    width: player.width - 20,
                    height: player.height - 20
                };

                if (checkCollision(playerRect, obstacles[i])) {
                    if (!player.hasShield && !player.isFlying) {
                        gameState = 'over';
                        bgm.pause();
                    }
                }
            }

            // 更新金币
            for (let i = coins.length - 1; i >= 0; i--) {
                coins[i].x -= gameSpeed;
                if (coins[i].x + coins[i].radius < 0) {
                    coins.splice(i, 1);
                    continue;
                }

                const playerRect = {
                    x: player.x,
                    y: player.y,
                    width: player.width,
                    height: player.height
                };
                const coinRect = {
                    x: coins[i].x - coins[i].radius,
                    y: coins[i].y - coins[i].radius,
                    width: coins[i].radius * 2,
                    height: coins[i].radius * 2
                };

                if (checkCollision(playerRect, coinRect)) {
                    coinCount++;
                    score += 100;
                    coins.splice(i, 1);
                }
            }

            // 更新道具
            for (let i = powerups.length - 1; i >= 0; i--) {
                powerups[i].x -= gameSpeed;
                if (powerups[i].x + powerups[i].radius < 0) {
                    powerups.splice(i, 1);
                    continue;
                }

                const playerRect = {
                    x: player.x,
                    y: player.y,
                    width: player.width,
                    height: player.height
                };
                const powerupRect = {
                    x: powerups[i].x - powerups[i].radius,
                    y: powerups[i].y - powerups[i].radius,
                    width: powerups[i].radius * 2,
                    height: powerups[i].radius * 2
                };

                if (checkCollision(playerRect, powerupRect)) {
                    if (powerups[i].type === 'fly') {
                        player.isFlying = true;
                        player.flyTimer = player.flyDuration;
                    } else if (powerups[i].type === 'shield') {
                        player.hasShield = true;
                        player.shieldTimer = player.shieldDuration;
                    }
                    powerups.splice(i, 1);
                }
            }
        }

        // 绘制画面
        function render() {
            ctx.clearRect(0, 0, W, H);

            // 云朵
            ctx.fillStyle = 'rgba(255,255,255,0.8)';
            drawCloud(100 - (frameCount * 0.15) % 600, 80);
            drawCloud(350 - (frameCount * 0.1) % 600, 150);

            // 地面
            ctx.fillStyle = '#8B4513';
            ctx.fillRect(0, groundY, W, groundHeight);
            ctx.fillStyle = '#654321';
            for (let i = 0; i < 3; i++) {
                ctx.fillRect(groundOffset + i * W, groundY + 20, W, 5);
                ctx.fillRect(groundOffset + i * W, groundY + 50, W, 5);
            }
            ctx.fillStyle = '#27ae60';
            ctx.fillRect(0, groundY, W, 15);

            // 障碍物
            obstacles.forEach(obs => {
                ctx.fillStyle = '#2c3e50';
                ctx.fillRect(obs.x, obs.y, obs.width, obs.height);
                ctx.fillStyle = '#34495e';
                const spikeCount = Math.floor(obs.width / 20);
                for (let i = 0; i < spikeCount; i++) {
                    ctx.beginPath();
                    ctx.moveTo(obs.x + i*20, obs.y);
                    ctx.lineTo(obs.x + i*20 + 10, obs.y - 12);
                    ctx.lineTo(obs.x + i*20 + 20, obs.y);
                    ctx.fill();
                }
            });

            // 金币
            coins.forEach(coin => {
                ctx.fillStyle = '#f1c40f';
                ctx.beginPath();
                ctx.arc(coin.x, coin.y, coin.radius, 0, Math.PI * 2);
                ctx.fill();
                ctx.fillStyle = '#f39c12';
                ctx.font = 'bold 16px Arial';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillText('$', coin.x, coin.y);
            });

            // 道具
            powerups.forEach(p => {
                if (p.type === 'fly') {
                    ctx.fillStyle = '#0984e3';
                    ctx.beginPath();
                    ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.fillStyle = '#fff';
                    ctx.font = 'bold 14px Microsoft Yahei';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText('飞行', p.x, p.y);
                } else {
                    ctx.fillStyle = '#00b894';
                    ctx.beginPath();
                    ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.fillStyle = '#fff';
                    ctx.font = 'bold 14px Microsoft Yahei';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText('护盾', p.x, p.y);
                }
            });

            // 玩家
            ctx.fillStyle = '#e74c3c';
            ctx.fillRect(player.x, player.y, player.width, player.height);
            ctx.fillStyle = '#f39c12';
            ctx.beginPath();
            ctx.arc(player.x + player.width/2, player.y + 15, 18, 0, Math.PI * 2);
            ctx.fill();

            // 护盾特效
            if (player.hasShield) {
                const pulse = Math.sin(frameCount * 0.1) * 3;
                ctx.strokeStyle = 'rgba(0, 184, 148, 0.7)';
                ctx.lineWidth = 3;
                ctx.beginPath();
                ctx.ellipse(
                    player.x + player.width/2,
                    player.y + player.height/2,
                    player.width/2 + 8 + pulse,
                    player.height/2 + 8 + pulse,
                    0, 0, Math.PI * 2
                );
                ctx.stroke();
            }

            // 飞行翅膀特效
            if (player.isFlying) {
                const flap = Math.sin(frameCount * 0.3) * 5;
                ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';
                ctx.beginPath();
                ctx.moveTo(player.x, player.y + player.height/2);
                ctx.lineTo(player.x - 28 - flap, player.y + 8);
                ctx.lineTo(player.x - 22 - flap, player.y + player.height - 8);
                ctx.closePath();
                ctx.fill();
                ctx.beginPath();
                ctx.moveTo(player.x + player.width, player.y + player.height/2);
                ctx.lineTo(player.x + player.width + 28 + flap, player.y + 8);
                ctx.lineTo(player.x + player.width + 22 + flap, player.y + player.height - 8);
                ctx.closePath();
                ctx.fill();
            }

            // 分数与状态
            ctx.fillStyle = '#fff';
            ctx.font = 'bold 24px Microsoft Yahei';
            ctx.textAlign = 'left';
            ctx.shadowColor = '#000';
            ctx.shadowBlur = 4;
            ctx.fillText(`分数: ${score}`, 20, 40);
            ctx.fillText(`金币: ${coinCount}`, 20, 75);
            
            if (player.isFlying) {
                ctx.fillStyle = '#74b9ff';
                ctx.fillText(`飞行: ${Math.ceil(player.flyTimer / 60)}s`, 20, 110);
            }
            if (player.hasShield) {
                ctx.fillStyle = '#55efc4';
                ctx.fillText(`护盾: ${Math.ceil(player.shieldTimer / 60)}s`, 20, 145);
            }
            ctx.shadowBlur = 0;

            // 开始界面
            if (gameState === 'start') {
                ctx.fillStyle = 'rgba(0,0,0,0.6)';
                ctx.fillRect(0, 0, W, H);
                ctx.fillStyle = '#fff';
                ctx.font = 'bold 40px Microsoft Yahei';
                ctx.textAlign = 'center';
                ctx.fillText('天天酷跑', W/2, H/2 - 80);
                ctx.font = '20px Microsoft Yahei';
                ctx.fillText('空格/↑键/点击屏幕 跳跃(可二段跳)', W/2, H/2 - 30);
                ctx.fillText('收集飞行道具可腾空8秒', W/2, H/2 + 5);
                ctx.fillText('收集护盾道具可10秒无敌', W/2, H/2 + 40);
                ctx.fillText('点击屏幕开始游戏', W/2, H/2 + 90);
            }

            // 结束界面
            if (gameState === 'over') {
                ctx.fillStyle = 'rgba(0,0,0,0.7)';
                ctx.fillRect(0, 0, W, H);
                ctx.fillStyle = '#e74c3c';
                ctx.font = 'bold 44px Microsoft Yahei';
                ctx.textAlign = 'center';
                ctx.fillText('游戏结束', W/2, H/2 - 80);
                ctx.fillStyle = '#fff';
                ctx.font = '24px Microsoft Yahei';
                ctx.fillText(`最终得分: ${score}`, W/2, H/2 - 20);
                ctx.fillText(`收集金币: ${coinCount}`, W/2, H/2 + 20);
                ctx.fillStyle = '#2ecc71';
                ctx.fillText('点击重新开始', W/2, H/2 + 90);
            }
        }

        // 画云朵
        function drawCloud(x, y) {
            ctx.beginPath();
            ctx.arc(x, y, 25, 0, Math.PI * 2);
            ctx.arc(x + 25, y - 10, 30, 0, Math.PI * 2);
            ctx.arc(x + 55, y, 25, 0, Math.PI * 2);
            ctx.fill();
        }

        // 游戏主循环
        function gameLoop() {
            update();
            render();
            requestAnimationFrame(gameLoop);
        }

        // 操作事件
        canvas.addEventListener('click', jump);
        document.addEventListener('keydown', (e) => {
            if (e.code === 'Space' || e.code === 'ArrowUp') {
                e.preventDefault();
                jump();
            }
        });

        gameLoop();
    </script>
</body>
</html>

Game Source: 天天酷跑

Creator: ShadowCoder44

Libraries: none

Complexity: complex (522 lines, 17.9 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-shadowcoder44" to link back to the original. Then publish at arcadelab.ai/publish.