2D,MC像素风跑酷游戏用HTML实现

《MC跑酷冒险》游戏介绍

欢迎来到《MC跑酷冒险》!这是一款基于《我的世界》风格的横版跑酷游戏,融合了经典平台跳跃玩法与随机生成世界的无限乐趣。

游戏玩法

核心控制:使用WASD键操控角色------W跳跃/上梯子,S下蹲/下梯子,AD控制左右移动。按Q在起点重生,R重新生成世界。

冒险目标:穿越随机生成的地形,避开致命陷阱(红色岩浆和尖刺),利用棕色梯子攀爬,收集蓝色钻石获得高分,借助黄色弹簧实现超远跳跃,最终到达终点旗帜!

挑战要素:每次游戏都会生成全新的地图布局,包含移动平台、动态障碍、隐藏路径等多样机关。小心别掉出地图外,也别被陷阱终结你的冒险!

游戏特色

  • 随机生成世界:每次开局都是全新地图,保证无限重玩价值

  • 多样地形元素:包含草地、石砖、木材、岩浆、弹簧等10+种方块类型

  • 动态平台系统:移动平台、升降梯子带来多变挑战

  • 粒子特效:跳跃轨迹、收集特效、死亡爆炸等视觉反馈

  • 多结局体验:既可追求快速通关,也可探索收集全钻石

适合玩家

喜欢《我的世界》风格、平台跳跃挑战和roguelike随机元素的玩家。游戏简单易上手但富有深度,考验你的反应速度、空间判断和策略规划能力。

准备好开始你的跑酷冒险了吗?每一次跳跃都是新的挑战,每一次通关都是新的成就!🎮✨


下面是源代码,希望点赞,关注,收藏,评论!

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>跑酷冒险</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Courier New', monospace;
            background: #1a1a1a;
            color: white;
            overflow: hidden;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        #game-container {
            position: relative;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background: linear-gradient(to bottom, #87CEEB 60%, #5a9c5a 100%);
        }
        
        #game-canvas {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
        
        #ui-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            z-index: 100;
        }
        
        #game-info {
            position: absolute;
            top: 20px;
            left: 20px;
            background: rgba(0,0,0,0.7);
            color: white;
            padding: 10px 15px;
            border-radius: 5px;
            font-family: 'Courier New', monospace;
            z-index: 101;
            display: flex;
            gap: 15px;
        }
        
        .info-item {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        
        .info-label {
            font-size: 12px;
            opacity: 0.8;
        }
        
        .info-value {
            font-size: 18px;
            font-weight: bold;
        }
        
        .control-btn {
            position: absolute;
            z-index: 101;
            padding: 8px 16px;
            background: rgba(0,0,0,0.7);
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            transition: all 0.2s;
            pointer-events: auto;
        }
        
        .control-btn:hover {
            background: rgba(50,50,50,0.8);
            transform: translateY(-2px);
        }
        
        #help-btn {
            top: 20px;
            right: 20px;
        }
        
        .modal {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            padding: 30px;
            background: rgba(0,0,0,0.95);
            color: white;
            text-align: center;
            z-index: 1000;
            border-radius: 15px;
            font-family: 'Courier New', monospace;
            display: none;
            border: 4px solid #3d85c6;
            box-shadow: 0 0 20px rgba(0,0,0,0.8);
            max-width: 80%;
            max-height: 80%;
            overflow-y: auto;
            pointer-events: auto;
        }
        
        .modal h3 {
            margin-bottom: 20px;
            color: #f1c27d;
            font-size: 24px;
            text-shadow: 2px 2px 0 #000;
        }
        
        .modal ul {
            list-style: none;
            padding: 0;
            max-height: 300px;
            overflow-y: auto;
        }
        
        .modal li {
            padding: 10px;
            border-bottom: 1px solid #444;
            text-align: left;
            font-size: 14px;
            display: flex;
            justify-content: space-between;
        }
        
        .modal li span:first-child {
            font-weight: bold;
            color: #FFD700;
        }
        
        .modal button {
            margin-top: 20px;
            padding: 10px 20px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-family: 'Courier New', monospace;
            font-size: 16px;
            transition: all 0.2s;
            margin: 10px;
        }
        
        .modal button:hover {
            background: #45a049;
            transform: translateY(-2px);
        }
        
        #game-over-modal {
            display: none;
        }
        
        #game-over-modal h3 {
            color: #FF4500;
        }
        
        .controls {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
            margin-top: 20px;
        }
        
        .control-item {
            background: rgba(50,50,50,0.5);
            padding: 10px;
            border-radius: 5px;
            text-align: center;
        }
        
        .key {
            display: inline-block;
            background: #333;
            color: white;
            padding: 5px 10px;
            border-radius: 4px;
            margin: 0 5px;
            font-weight: bold;
        }
        
        .jump-trail {
            position: absolute;
            width: 4px;
            height: 4px;
            background: rgba(255, 255, 255, 0.5);
            border-radius: 50%;
            z-index: 50;
            pointer-events: none;
        }
        
        .particle {
            position: absolute;
            width: 6px;
            height: 6px;
            border-radius: 50%;
            z-index: 50;
            pointer-events: none;
        }
        
        .end-point {
            position: absolute;
            width: 60px;
            height: 80px;
            z-index: 90;
            pointer-events: none;
            display: flex;
            justify-content: center;
            align-items: center;
            font-weight: bold;
            color: white;
            font-size: 16px;
        }
        
        .end-point-flag {
            position: absolute;
            width: 40px;
            height: 60px;
            background: repeating-linear-gradient(
                45deg,
                #000,
                #000 10px,
                #fff 10px,
                #fff 20px
            );
            z-index: 91;
            top: 10px;
            left: 60px;
            border: 2px solid #000;
        }
        
        .end-point-base {
            position: absolute;
            width: 60px;
            height: 20px;
            background: #FFD700;
            z-index: 90;
            bottom: 0;
            border: 2px solid #B8860B;
        }
    </style>
</head>
<body>
    <div id="game-container">
        <canvas id="game-canvas"></canvas>
        
        <div id="ui-overlay">
            <!-- 游戏信息 -->
            <div id="game-info">
                <div class="info-item">
                    <div class="info-label">得分</div>
                    <div id="score-display" class="info-value">0</div>
                </div>
            </div>
            
            <!-- 控制按钮 -->
            <button id="help-btn" class="control-btn">❓ 玩法说明</button>
        </div>
    </div>
    
    <!-- 玩法说明弹窗 -->
    <div id="help-modal" class="modal">
        <h3>🎮 跑酷冒险指南 🎮</h3>
        <p>控制方式:</p>
        <div class="controls">
            <div class="control-item"><span class="key">W</span> 跳跃/上梯子</div>
            <div class="control-item"><span class="key">S</span> 下蹲/下梯子</div>
            <div class="control-item"><span class="key">A</span> 向左移动</div>
            <div class="control-item"><span class="key">D</span> 向右移动</div>
            <div class="control-item"><span class="key">Q</span> 起点重生</div>
            <div class="control-item"><span class="key">R</span> 重新生成世界</div>
        </div>
        <p>生存目标:</p>
        <p>✅ 避开红色岩浆和尖刺!</p>
        <p>✅ 爬棕色梯子越障</p>
        <p>✅ 收集钻石获得高分</p>
        <p>✅ 使用弹簧跳得更高</p>
        <p>❌ 别掉地图外!</p>
        <p>通关条件:到达终点!</p>
        <button id="close-help">开始冒险</button>
    </div>
    
    <!-- 游戏结束弹窗 -->
    <div id="game-over-modal" class="modal">
        <h3 id="game-over-title">游戏结束</h3>
        <p id="game-over-reason">你掉出了地图</p>
        <p>收集钻石: <span id="diamonds-collected">0</span></p>
        <p>最终得分: <span id="final-score">0</span></p>
        <button id="restart-btn">重新生成世界</button>
        <button id="respawn-btn">起点重生</button>
    </div>
    
    <!-- 通关弹窗 -->
    <div id="win-modal" class="modal">
        <h3>恭喜通关!🎉</h3>
        <p>你成功到达了终点!</p>
        <p>收集钻石: <span id="win-diamonds">0</span></p>
        <p>最终得分: <span id="win-score">0</span></p>
        <button id="play-again-btn">再玩一次</button>
        <button id="new-world-btn">开启全新地图</button>
    </div>

    <script>
        // 防止WebAssembly错误
        window.WebAssembly = undefined;
        
        // ==================== 游戏核心配置 ====================
        const canvas = document.getElementById('game-canvas');
        const ctx = canvas.getContext('2d');
        const gameContainer = document.getElementById('game-container');
        
        // 设置画布尺寸
        let CANVAS_WIDTH = 1200;
        let CANVAS_HEIGHT = 700;
        
        canvas.width = CANVAS_WIDTH;
        canvas.height = CANVAS_HEIGHT;
        
        // 游戏常量
        const TILE_SIZE = 32;
        const GROUND_HEIGHT = 40;
        const GRAVITY = 0.3;
        const JUMP_POWER = -8;
        const PLAYER_SPEED = 5;
        const PLAYER_CROUCH_SPEED = 2;
        const DEATH_LINE = CANVAS_HEIGHT + 100;
        const CAMERA_SMOOTHING = 0.1;
        
        // 视角控制
        let cameraOffset = { x: 0, y: 0 };
        let targetCameraOffset = { x: 0, y: 0 };
        
        // 玩家对象
        let player = {
            x: 100,
            y: CANVAS_HEIGHT - GROUND_HEIGHT - 64,
            width: 24,
            height: 48,
            velX: 0,
            velY: 0,
            isJumping: false,
            isCrouching: false,
            isForcedCrouching: false,
            onGround: false,
            onLadder: false,
            onPlatform: false,
            gravity: GRAVITY,
            jumpPower: JUMP_POWER,
            speed: PLAYER_SPEED,
            facingRight: true,
            originalHeight: 48,
            crouchHeight: 24,
            headRotation: 0,
            limbRotation: 0,
            mouseX: 0,
            mouseY: 0,
            lastPlatform: null,
            platformVelX: 0,
            platformVelY: 0
        };
        
        // 游戏状态
        let gameStarted = false;
        let gameOver = false;
        let score = 0;
        let diamondsCollected = 0;
        
        // 游戏元素
        let tiles = [];
        let obstacles = [];
        let diamonds = [];
        let platforms = [];
        let springs = [];
        let levelGoal = 0;
        let jumpTrails = [];
        let particles = [];
        let endPoints = [];
        
        // 按键状态
        let keys = {
            'w': false,
            'a': false,
            's': false,
            'd': false,
            'q': false,
            'r': false
        };
        
        // 障碍物类型
        const TILE_TYPES = {
            GRASS: { color: '#7CFC00', fatal: false, texture: 'grass', solid: true },
            DIRT: { color: '#8B4513', fatal: false, texture: 'dirt', solid: true },
            STONE: { color: '#808080', fatal: false, texture: 'stone', solid: true },
            LAVA: { color: '#FF4500', fatal: true, texture: 'lava', solid: false },
            LADDER: { color: '#D2B48C', fatal: false, climbable: true, texture: 'ladder', solid: false },
            PILLAR: { color: '#A9A9A9', fatal: false, block: true, texture: 'stone_brick', solid: true },
            SPIKE: { color: '#FF0000', fatal: true, texture: 'spike', solid: false },
            SPRING: { color: '#FFFF00', bounce: true, texture: 'spring', solid: false },
            WOOD: { color: '#8B4513', fatal: false, texture: 'wood', solid: true },
            WATER: { color: '#1E90FF', fatal: false, slows: true, texture: 'water', solid: false },
            BEDROCK: { color: '#2F2F2F', fatal: false, texture: 'bedrock', solid: true },
            COBBLESTONE: { color: '#808080', fatal: false, texture: 'cobblestone', solid: true },
            OBSIDIAN: { color: '#2F2F2F', fatal: false, texture: 'obsidian', solid: true },
            SAND: { color: '#C2B280', fatal: false, texture: 'sand', solid: true },
            GRAVEL: { color: '#8B8680', fatal: false, texture: 'gravel', solid: true },
            NETHERRACK: { color: '#8B0000', fatal: false, texture: 'netherrack', solid: true },
            END_STONE: { color: '#D9D9A3', fatal: false, texture: 'end_stone', solid: true },
            TEMPLE_BRICK: { color: '#C19A6B', fatal: false, texture: 'temple_brick', solid: true },
            PYRAMID_BRICK: { color: '#D7B98C', fatal: false, texture: 'pyramid_brick', solid: true },
            MOUNTAIN_STONE: { color: '#A0A0A0', fatal: false, texture: 'mountain_stone', solid: true }
        };
        
        // 纹理资源
        const TEXTURES = {
            grass: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#5a9c5a';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#7CFC00';
                    for (let i = 0; i < w; i += 8) {
                        ctx.fillRect(x + i, y, 4, 2);
                    }
                }
            },
            dirt: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#8B4513';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#5a3a1e';
                    for (let i = 0; i < w; i += 6) {
                        for (let j = 0; j < h; j += 6) {
                            ctx.fillRect(x + i, y + j, 2, 2);
                        }
                    }
                }
            },
            stone: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#808080';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#666';
                    for (let i = 0; i < w; i += 6) {
                        for (let j = 0; j < h; j += 6) {
                            ctx.fillRect(x + i, y + j, 3, 3);
                        }
                    }
                }
            },
            cobblestone: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#808080';
                    ctx.fillRect(x, y, w, h);
                    ctx.strokeStyle = '#555';
                    ctx.lineWidth = 1;
                    for (let i = 0; i < w; i += 8) {
                        for (let j = 0; j < h; j += 8) {
                            ctx.strokeRect(x + i, y + j, 8, 8);
                        }
                    }
                }
            },
            stone_brick: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#808080';
                    ctx.fillRect(x, y, w, h);
                    ctx.strokeStyle = '#555';
                    ctx.lineWidth = 1;
                    for (let i = 0; i < w; i += 8) {
                        for (let j = 0; j < h; j += 8) {
                            ctx.strokeRect(x + i, y + j, 8, 8);
                        }
                    }
                }
            },
            lava: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#FF4500';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#FF5500';
                    for (let i = 0; i < w; i += 15) {
                        for (let j = 0; j < h; j += 15) {
                            ctx.fillRect(x + i, y + j, 8, 8);
                        }
                    }
                }
            },
            ladder: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#D2B48C';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#8B4513';
                    for (let i = 0; i < h; i += 8) {
                        ctx.fillRect(x, y + i, 4, 4);
                        ctx.fillRect(x + w - 4, y + i, 4, 4);
                        if (i % 16 === 0) {
                            ctx.fillRect(x + 4, y + i, w - 8, 4);
                        }
                    }
                }
            },
            spike: {
                draw: function(ctx, x, y, w, h) {
                    const spikeWidth = 10;
                    const spikeCount = Math.floor(w / spikeWidth);
                    const spikeHeight = 16;
                    
                    ctx.fillStyle = '#FF0000';
                    for (let i = 0; i < spikeCount; i++) {
                        const spikeX = x + i * spikeWidth;
                        ctx.beginPath();
                        ctx.moveTo(spikeX, y + h);
                        ctx.lineTo(spikeX + spikeWidth/2, y + h - spikeHeight);
                        ctx.lineTo(spikeX + spikeWidth, y + h);
                        ctx.closePath();
                        ctx.fill();
                    }
                }
            },
            spring: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#FFFF00';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#000';
                    ctx.beginPath();
                    ctx.moveTo(x, y + h);
                    ctx.lineTo(x + w, y + h);
                    ctx.lineTo(x + w, y);
                    ctx.lineTo(x, y);
                    ctx.closePath();
                    ctx.stroke();
                    
                    ctx.beginPath();
                    ctx.moveTo(x + w/4, y + h/3);
                    ctx.lineTo(x + w*3/4, y + h/3);
                    ctx.stroke();
                    
                    ctx.beginPath();
                    ctx.moveTo(x + w/4, y + h*2/3);
                    ctx.lineTo(x + w*3/4, y + h*2/3);
                    ctx.stroke();
                }
            },
            wood: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#8B4513';
                    ctx.fillRect(x, y, w, h);
                    ctx.strokeStyle = '#5a3a1e';
                    ctx.lineWidth = 1;
                    for (let i = 0; i < w; i += 6) {
                        ctx.beginPath();
                        ctx.moveTo(x + i, y);
                        ctx.lineTo(x + i, y + h);
                        ctx.stroke();
                    }
                }
            },
            water: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#1E90FF';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
                    for (let i = 0; i < w; i += 10) {
                        for (let j = 0; j < h; j += 10) {
                            ctx.fillRect(x + i, y + j, 6, 6);
                        }
                    }
                }
            },
            bedrock: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#2F2F2F';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#1a1a1a';
                    for (let i = 0; i < w; i += 4) {
                        for (let j = 0; j < h; j += 4) {
                            ctx.fillRect(x + i, y + j, 2, 2);
                        }
                    }
                }
            },
            obsidian: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#2F2F2F';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#1a1a1a';
                    for (let i = 0; i < w; i += 6) {
                        for (let j = 0; j < h; j += 6) {
                            ctx.fillRect(x + i, y + j, 3, 3);
                        }
                    }
                }
            },
            sand: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#C2B280';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#a8996e';
                    for (let i = 0; i < w; i += 4) {
                        for (let j = 0; j < h; j += 4) {
                            ctx.fillRect(x + i, y + j, 2, 2);
                        }
                    }
                }
            },
            gravel: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#8B8680';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#666';
                    for (let i = 0; i < w; i += 4) {
                        for (let j = 0; j < h; j += 4) {
                            ctx.fillRect(x + i, y + j, 2, 2);
                        }
                    }
                }
            },
            netherrack: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#8B0000';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#660000';
                    for (let i = 0; i < w; i += 4) {
                        for (let j = 0; j < h; j += 4) {
                            ctx.fillRect(x + i, y + j, 2, 2);
                        }
                    }
                }
            },
            end_stone: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#D9D9A3';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#b8b887';
                    for (let i = 0; i < w; i += 4) {
                        for (let j = 0; j < h; j += 4) {
                            ctx.fillRect(x + i, y + j, 2, 2);
                        }
                    }
                }
            },
            temple_brick: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#C19A6B';
                    ctx.fillRect(x, y, w, h);
                    ctx.strokeStyle = '#8B7355';
                    ctx.lineWidth = 1;
                    for (let i = 0; i < w; i += 10) {
                        for (let j = 0; j < h; j += 10) {
                            ctx.strokeRect(x + i, y + j, 10, 10);
                        }
                    }
                }
            },
            pyramid_brick: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#D7B98C';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#B89C7C';
                    for (let i = 0; i < w; i += 8) {
                        for (let j = 0; j < h; j += 8) {
                            ctx.fillRect(x + i, y + j, 4, 4);
                        }
                    }
                }
            },
            mountain_stone: {
                draw: function(ctx, x, y, w, h) {
                    ctx.fillStyle = '#A0A0A0';
                    ctx.fillRect(x, y, w, h);
                    ctx.fillStyle = '#808080';
                    for (let i = 0; i < w; i += 6) {
                        for (let j = 0; j < h; j += 6) {
                            ctx.fillRect(x + i, y + j, 3, 3);
                        }
                    }
                }
            }
        };
        
        // 预定义的关卡结构模板
        const LEVEL_TEMPLATES = [
            {
                name: "基础平台",
                structures: [
                    { type: 'PILLAR', x: 500, y: 0, width: 50, height: 3 },
                    { type: 'PILLAR', x: 800, y: 0, width: 50, height: 5 },
                    { type: 'LADDER', x: 500, y: 0, width: 32, height: 6 },
                    { type: 'PLATFORM', x: 600, y: 300, width: 100, height: 20, platformType: 'WOOD', speed: 1, direction: 1 }
                ]
            },
            {
                name: "高塔",
                structures: [
                    { type: 'PILLAR', x: 700, y: 0, width: 80, height: 8 },
                    { type: 'LADDER', x: 700, y: 0, width: 32, height: 8 },
                    { type: 'PLATFORM', x: 650, y: 200, width: 80, height: 20, platformType: 'COBBLESTONE' },
                    { type: 'PLATFORM', x: 750, y: 350, width: 80, height: 20, platformType: 'COBBLESTONE' }
                ]
            },
            {
                name: "移动平台",
                structures: [
                    { type: 'PLATFORM', x: 400, y: 200, width: 120, height: 20, platformType: 'WOOD', speed: 2, direction: 1, verticalSpeed: 1, verticalDirection: 1, minY: 150, maxY: 300 },
                    { type: 'PLATFORM', x: 700, y: 250, width: 100, height: 20, platformType: 'COBBLESTONE', speed: 1.5, direction: -1 },
                    { type: 'PLATFORM', x: 900, y: 180, width: 80, height: 20, platformType: 'WOOD', speed: 1, direction: 1 }
                ]
            },
            {
                name: "岩浆陷阱",
                structures: [
                    { type: 'LAVA', x: 600, y: 0, width: 150, height: 1 },
                    { type: 'PILLAR', x: 550, y: 0, width: 50, height: 4 },
                    { type: 'PILLAR', x: 750, y: 0, width: 50, height: 4 },
                    { type: 'PLATFORM', x: 650, y: 150, width: 80, height: 20, platformType: 'COBBLESTONE' },
                    { type: 'SPRING', x: 550, y: 0, width: 32, height: 1 }
                ]
            },
            {
                name: "复杂跳跃",
                structures: [
                    { type: 'PILLAR', x: 500, y: 0, width: 40, height: 3 },
                    { type: 'PILLAR', x: 650, y: 0, width: 40, height: 5 },
                    { type: 'PILLAR', x: 800, y: 0, width: 40, height: 4 },
                    { type: 'PLATFORM', x: 550, y: 150, width: 70, height: 20, platformType: 'WOOD' },
                    { type: 'PLATFORM', x: 700, y: 100, width: 70, height: 20, platformType: 'WOOD' },
                    { type: 'SPRING', x: 600, y: 0, width: 32, height: 1 },
                    { type: 'SPRING', x: 750, y: 0, width: 32, height: 1 }
                ]
            }
        ];
        
        // 随机种子生成器
        function generateRandomSeed() {
            return Math.floor(Math.random() * 1000000);
        }
        
        // 使用随机种子生成关卡
        let currentSeed = generateRandomSeed();
        
        function generateLevel(seed) {
            // 重置游戏状态
            tiles = [];
            obstacles = [];
            diamonds = [];
            platforms = [];
            springs = [];
            endPoints = [];
            player.x = 100;
            player.y = CANVAS_HEIGHT - GROUND_HEIGHT - player.height;
            player.velX = player.velY = 0;
            player.isJumping = false;
            player.isCrouching = false;
            player.isForcedCrouching = false;
            player.height = player.originalHeight;
            player.speed = PLAYER_SPEED;
            player.platformVelX = 0;
            player.platformVelY = 0;
            cameraOffset = { x: 0, y: 0 };
            targetCameraOffset = { x: 0, y: 0 };
            
            // 重置按键状态
            resetKeys();
            
            // 设置随机种子
            const random = seededRandom(seed);
            
            // 关卡长度
            const levelLength = 2000 + Math.floor(random() * 1000);
            
            // 生成地面
            for (let x = 0; x < levelLength; x += TILE_SIZE) {
                tiles.push({ 
                    x, 
                    y: CANVAS_HEIGHT - GROUND_HEIGHT, 
                    w: TILE_SIZE, 
                    h: TILE_SIZE, 
                    type: TILE_TYPES.GRASS 
                });
                
                for (let y = CANVAS_HEIGHT - GROUND_HEIGHT + TILE_SIZE; y < CANVAS_HEIGHT - GROUND_HEIGHT + TILE_SIZE * 3; y += TILE_SIZE) {
                    tiles.push({ 
                        x, 
                        y, 
                        w: TILE_SIZE, 
                        h: TILE_SIZE, 
                        type: TILE_TYPES.DIRT 
                    });
                }
                
                for (let y = CANVAS_HEIGHT - GROUND_HEIGHT + TILE_SIZE * 3; y < CANVAS_HEIGHT - GROUND_HEIGHT + TILE_SIZE * 6; y += TILE_SIZE) {
                    tiles.push({ 
                        x, 
                        y, 
                        w: TILE_SIZE, 
                        h: TILE_SIZE, 
                        type: TILE_TYPES.STONE 
                    });
                }
                
                for (let y = CANVAS_HEIGHT - GROUND_HEIGHT + TILE_SIZE * 6; y < CANVAS_HEIGHT; y += TILE_SIZE) {
                    tiles.push({ 
                        x, 
                        y, 
                        w: TILE_SIZE, 
                        h: TILE_SIZE, 
                        type: TILE_TYPES.BEDROCK 
                    });
                }
            }
            
            // 随机选择模板
            const templateCount = 5 + Math.floor(random() * 3);
            const selectedTemplates = [];
            
            for (let i = 0; i < templateCount; i++) {
                const templateIndex = Math.floor(random() * LEVEL_TEMPLATES.length);
                selectedTemplates.push(LEVEL_TEMPLATES[templateIndex]);
            }
            
            // 应用模板
            selectedTemplates.forEach((template, index) => {
                const offsetX = 300 + (index * (levelLength - 600) / templateCount) + (random() * 200 - 100);
                
                template.structures.forEach(structure => {
                    const adjustedX = structure.x + offsetX;
                    
                    switch(structure.type) {
                        case 'PILLAR':
                            obstacles.push({
                                x: adjustedX,
                                y: CANVAS_HEIGHT - GROUND_HEIGHT - structure.height * TILE_SIZE,
                                w: structure.width,
                                h: structure.height * TILE_SIZE,
                                type: TILE_TYPES[structure.type]
                            });
                            break;
                        case 'LADDER':
                            obstacles.push({
                                x: adjustedX,
                                y: CANVAS_HEIGHT - GROUND_HEIGHT - structure.height * TILE_SIZE,
                                w: structure.width,
                                h: structure.height * TILE_SIZE,
                                type: TILE_TYPES[structure.type]
                            });
                            break;
                        case 'LAVA':
                            obstacles.push({
                                x: adjustedX,
                                y: CANVAS_HEIGHT - GROUND_HEIGHT - structure.height * TILE_SIZE,
                                w: structure.width,
                                h: structure.height * TILE_SIZE,
                                type: TILE_TYPES[structure.type]
                            });
                            break;
                        case 'SPRING':
                            springs.push({
                                x: adjustedX,
                                y: CANVAS_HEIGHT - GROUND_HEIGHT - TILE_SIZE,
                                w: structure.width,
                                h: TILE_SIZE,
                                type: TILE_TYPES[structure.type]
                            });
                            break;
                        case 'PLATFORM':
                            platforms.push({
                                x: adjustedX,
                                y: structure.y,
                                w: structure.width,
                                h: structure.height,
                                speed: structure.speed || 0,
                                direction: structure.direction || 1,
                                type: TILE_TYPES[structure.platformType || 'WOOD'],
                                originalX: adjustedX,
                                verticalSpeed: structure.verticalSpeed || 0,
                                verticalDirection: structure.verticalDirection || 0,
                                minY: structure.minY || structure.y,
                                maxY: structure.maxY || structure.y,
                                prevX: adjustedX,
                                prevY: structure.y
                            });
                            break;
                    }
                });
            });
            
            // 添加随机障碍物
            const obstacleCount = 6 + Math.floor(random() * 8);
            for (let i = 0; i < obstacleCount; i++) {
                const x = 300 + (i * (levelLength - 600) / obstacleCount) + (random() * 200 - 100);
                const width = 50 + random() * 100;
                const height = 1 + Math.floor(random() * 3);
                
                let type;
                const rand = random();
                
                if (rand < 0.3) {
                    type = 'LAVA';
                } else if (rand < 0.5) {
                    type = 'SPIKE';
                } else if (rand < 0.7) {
                    type = 'PILLAR';
                } else {
                    type = 'LADDER';
                }
                
                obstacles.push({
                    type: TILE_TYPES[type],
                    x: x,
                    y: CANVAS_HEIGHT - GROUND_HEIGHT - height * TILE_SIZE,
                    w: type === 'LADDER' ? 32 : width,
                    h: height * TILE_SIZE
                });
            }
            
            // 添加随机弹簧
            const springCount = 2 + Math.floor(random() * 3);
            for (let i = 0; i < springCount; i++) {
                const x = 200 + (i * (levelLength - 400) / springCount) + (random() * 100 - 50);
                springs.push({
                    x: x,
                    y: CANVAS_HEIGHT - GROUND_HEIGHT - TILE_SIZE,
                    w: 32,
                    h: TILE_SIZE,
                    type: TILE_TYPES.SPRING
                });
            }
            
            // 添加随机平台
            const platformCount = Math.min(4, 2 + Math.floor(random() * 2));
            for (let i = 0; i < platformCount; i++) {
                const x = 200 + (i * (levelLength - 400) / platformCount) + (random() * 150 - 75);
                const y = 150 + random() * 300;
                const width = 80 + random() * 120;
                
                const platformTypes = ['WOOD', 'COBBLESTONE', 'STONE'];
                const type = platformTypes[Math.floor(random() * platformTypes.length)];
                
                const speed = random() * 2;
                const direction = random() > 0.5 ? 1 : -1;
                
                const platform = {
                    x: x,
                    y: y,
                    w: width,
                    h: 20,
                    speed: speed,
                    direction: direction,
                    type: TILE_TYPES[type],
                    originalX: x,
                    prevX: x,
                    prevY: y
                };
                
                if (random() > 0.7) {
                    platform.verticalSpeed = 0.5 + random() * 1.5;
                    platform.verticalDirection = random() > 0.5 ? 1 : -1;
                    platform.minY = platform.y - 80;
                    platform.maxY = platform.y + 80;
                }
                
                platforms.push(platform);
            }
            
            // 添加钻石
            const diamondCount = 6 + Math.floor(random() * 8);
            for (let i = 0; i < diamondCount; i++) {
                const x = 100 + (i * (levelLength - 200) / diamondCount) + (random() * 100 - 50);
                const y = 100 + random() * 400;
                
                diamonds.push({
                    x: x,
                    y: y,
                    w: 16,
                    h: 16,
                    collected: false
                });
            }
            
            // 添加终点
            endPoints.push({
                x: levelLength - 100,
                y: CANVAS_HEIGHT - GROUND_HEIGHT - 80,
                w: 60,
                h: 80
            });
            
            // 设置关卡目标
            levelGoal = levelLength - CANVAS_WIDTH;
        }
        
        // 随机数生成器
        function seededRandom(seed) {
            let value = seed;
            return function() {
                value = (value * 9301 + 49297) % 233280;
                return value / 233280;
            };
        }
        
        // ==================== 游戏初始化 ====================
        function init() {
            // 设置画布尺寸
            resizeCanvas();
            
            // 初始化事件监听器
            setupEventListeners();
            
            // 生成初始关卡
            generateLevel(currentSeed);
            
            // 显示玩法说明
            showHelp();
        }
        
        function resizeCanvas() {
            canvas.width = CANVAS_WIDTH;
            canvas.height = CANVAS_HEIGHT;
            
            canvas.style.position = 'absolute';
            canvas.style.left = '50%';
            canvas.style.top = '50%';
            canvas.style.transform = 'translate(-50%, -50%)';
            
            if (gameStarted && !gameOver) {
                targetCameraOffset.x = player.x - CANVAS_WIDTH / 2;
                targetCameraOffset.y = player.y - CANVAS_HEIGHT / 2;
            } else {
                player.y = CANVAS_HEIGHT - GROUND_HEIGHT - player.height;
            }
        }
        
        // ==================== 修复Bug 5: 事件监听器内存泄漏 ====================
        let eventListenersBound = false;
        
        function setupEventListeners() {
            // 只绑定一次事件监听器
            if (eventListenersBound) return;
            eventListenersBound = true;
            
            window.addEventListener('resize', resizeCanvas);
            document.addEventListener('keydown', handleKeydown);
            document.addEventListener('keyup', handleKeyup);
            canvas.addEventListener('mousemove', handleMouseMove);
            
            // UI按钮事件 - 使用事件委托
            document.addEventListener('click', function(e) {
                const target = e.target;
                
                if (target.id === 'help-btn') {
                    showHelp();
                } else if (target.id === 'close-help') {
                    document.getElementById('help-modal').style.display = 'none';
                    startGame();
                } else if (target.id === 'restart-btn') {
                    restartGame();
                } else if (target.id === 'respawn-btn') {
                    respawnAtStart();
                } else if (target.id === 'play-again-btn') {
                    playAgain();
                } else if (target.id === 'new-world-btn') {
                    newWorld();
                }
            });
        }
        
        function handleMouseMove(e) {
            const rect = canvas.getBoundingClientRect();
            player.mouseX = e.clientX - rect.left;
            player.mouseY = e.clientY - rect.top;
        }
        
        // ==================== 游戏核心逻辑 ====================
        function startGame() {
            gameStarted = true;
            gameOver = false;
            score = 0;
            diamondsCollected = 0;
            document.getElementById('score-display').textContent = score;
            
            gameLoop();
        }
        
        function handleKeydown(e) {
            const key = e.key.toLowerCase();
            if (key in keys) {
                keys[key] = true;
            }
            
            if (key === 'q') {
                respawnAtStart();
            }
            
            if (key === 'r') {
                restartGame();
            }
        }
        
        function handleKeyup(e) {
            const key = e.key.toLowerCase();
            if (key in keys) {
                keys[key] = false;
            }
        }
        
        function resetKeys() {
            for (let key in keys) {
                keys[key] = false;
            }
        }
        
        function canJump() {
            return player.onGround || player.onLadder || player.onPlatform || 
                   (player.velY >= 0 && checkGroundCollision());
        }
        
        function checkGroundCollision() {
            const playerRect = {
                x: player.x,
                y: player.y + player.height,
                width: player.width,
                height: 5
            };
            
            const items = [...tiles, ...obstacles, ...platforms];
            
            for (const item of items) {
                if (item.type && (item.type.solid || item.type === TILE_TYPES.PILLAR)) {
                    if (checkCollision(playerRect, item)) {
                        return true;
                    }
                }
            }
            return false;
        }
        
        // ==================== 修复Bug 1: 玩家下蹲时碰撞检测问题 ====================
        function checkAboveObstacle() {
            const checkHeight = 30;
            const checkRect = {
                x: player.x,
                y: player.y - checkHeight,
                width: player.width,
                height: checkHeight
            };
            
            const items = [...tiles, ...obstacles, ...platforms];
            
            for (const item of items) {
                if (item.type && (item.type.solid || item.type === TILE_TYPES.PILLAR)) {
                    if (checkCollision(checkRect, item)) {
                        // 检查是否真的会碰撞,考虑玩家站起来后的高度
                        const playerStandingRect = {
                            x: player.x,
                            y: player.y - (player.originalHeight - player.height),
                            width: player.width,
                            height: player.originalHeight
                        };
                        
                        if (checkCollision(playerStandingRect, item)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        
        function updatePlayer() {
            player.velX = 0;
            
            let movingLeft = keys['a'];
            let movingRight = keys['d'];
            
            if (movingLeft && movingRight) {
                player.velX = 0;
            } else if (movingLeft) {
                player.velX = -player.speed;
                player.facingRight = false;
            } else if (movingRight) {
                player.velX = player.speed;
                player.facingRight = true;
            }
            
            if (keys['s']) {
                if (!player.isCrouching) {
                    player.isCrouching = true;
                    const originalBottom = player.y + player.height;
                    player.height = player.crouchHeight;
                    player.y = originalBottom - player.height;
                    player.speed = PLAYER_CROUCH_SPEED;
                }
            } else {
                if (!checkAboveObstacle()) {
                    if (player.isCrouching) {
                        player.isCrouching = false;
                        const originalBottom = player.y + player.height;
                        player.height = player.originalHeight;
                        player.y = originalBottom - player.height;
                        player.speed = PLAYER_SPEED;
                        player.isForcedCrouching = false;
                    }
                } else {
                    player.isCrouching = true;
                    player.isForcedCrouching = true;
                    player.speed = PLAYER_CROUCH_SPEED;
                }
            }
            
            if (keys['w'] && canJump()) {
                player.velY = player.jumpPower;
                player.isJumping = true;
                player.onLadder = false;
                player.onPlatform = false;
                createJumpTrail();
            }
            
            if (!player.onLadder) {
                player.velY += player.gravity;
            }
            
            let newX = player.x;
            let newY = player.y;
            
            if (player.velX !== 0) {
                newX = player.x + player.velX;
                
                if (checkSolidCollision({x: newX, y: player.y, width: player.width, height: player.height})) {
                    const step = player.velX > 0 ? 1 : -1;
                    let testX = player.x;
                    
                    for (let i = 0; i < Math.abs(player.velX); i++) {
                        testX += step;
                        if (!checkSolidCollision({x: testX, y: player.y, width: player.width, height: player.height})) {
                            newX = testX;
                        } else {
                            break;
                        }
                    }
                }
            }
            
            if (player.velY !== 0) {
                newY = player.y + player.velY;
                
                if (checkSolidCollision({x: newX, y: newY, width: player.width, height: player.height})) {
                    const step = player.velY > 0 ? 1 : -1;
                    let testY = player.y;
                    
                    for (let i = 0; i < Math.abs(player.velY); i++) {
                        testY += step;
                        if (!checkSolidCollision({x: newX, y: testY, width: player.width, height: player.height})) {
                            newY = testY;
                        } else {
                            if (step > 0) {
                                const allSolids = [...tiles, ...obstacles, ...platforms];
                                let closestBlock = null;
                                let closestDistance = Infinity;
                                
                                for (const item of allSolids) {
                                    if (item.type && (item.type.solid || item.type === TILE_TYPES.PILLAR)) {
                                        if (newX < item.x + item.w &&
                                            newX + player.width > item.x &&
                                            testY + player.height > item.y &&
                                            testY < item.y + item.h) {
                                            
                                            const distance = item.y - (testY + player.height);
                                            if (distance < closestDistance) {
                                                closestDistance = distance;
                                                closestBlock = item;
                                            }
                                        }
                                    }
                                }
                                
                                if (closestBlock) {
                                    newY = closestBlock.y - player.height;
                                    player.onGround = true;
                                    player.isJumping = false;
                                    player.velY = 0;
                                    
                                    if (platforms.includes(closestBlock)) {
                                        player.onPlatform = true;
                                        player.lastPlatform = closestBlock;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
            
            player.x = newX;
            player.y = newY;
            
            if (player.x < 0) player.x = 0;
            
            if (player.velX !== 0) {
                player.limbRotation = Math.sin(Date.now() / 100) * 0.5;
            } else {
                player.limbRotation = 0;
            }
            
            const centerX = player.x + player.width / 2;
            const centerY = player.y + player.height / 2;
            const dx = (player.mouseX + cameraOffset.x) - centerX;
            player.headRotation = Math.atan2(100, dx) * 0.5;
        }
        
        function createJumpTrail() {
            for (let i = 0; i < 5; i++) {
                jumpTrails.push({
                    x: player.x + player.width / 2,
                    y: player.y + player.height,
                    size: Math.random() * 4 + 2,
                    alpha: 1,
                    life: 20
                });
            }
        }
        
        function updateJumpTrails() {
            for (let i = jumpTrails.length - 1; i >= 0; i--) {
                const trail = jumpTrails[i];
                trail.y += 2;
                trail.alpha -= 0.05;
                trail.life--;
                
                if (trail.life <= 0) {
                    jumpTrails.splice(i, 1);
                }
            }
        }
        
        function update() {
            if (!gameStarted || gameOver) return;
            
            updatePlatforms();
            updatePlayer();
            
            player.onLadder = false;
            player.onPlatform = false;
            player.onGround = false;
            
            checkCollisions();
            updateCamera();
            collectDiamonds();
            updateJumpTrails();
            updateParticles();
            checkEndPoint();
        }
        
        // ==================== 修复Bug 2: 平台移动时的玩家跟随问题 ====================
        function updatePlatforms() {
            // 先检查玩家是否还在平台上
            if (player.lastPlatform) {
                const platform = player.lastPlatform;
                const playerBottom = player.y + player.height;
                const platformTop = platform.y;
                
                // 如果玩家底部不在平台顶部5像素内,则离开平台
                if (Math.abs(playerBottom - platformTop) > 5) {
                    player.onPlatform = false;
                    player.lastPlatform = null;
                }
            }
            
            platforms.forEach(platform => {
                platform.prevX = platform.x;
                platform.prevY = platform.y;
                
                // 移动平台
                platform.x += platform.speed * platform.direction;
                if (platform.verticalSpeed) {
                    platform.y += platform.verticalSpeed * platform.verticalDirection;
                }
                
                // 边界检测
                if (platform.x <= platform.originalX - 100 || platform.x >= platform.originalX + 100) {
                    platform.direction *= -1;
                }
                if (platform.verticalSpeed && (platform.y <= platform.minY || platform.y >= platform.maxY)) {
                    platform.verticalDirection *= -1;
                }
                
                // 计算平台移动距离
                const dx = platform.x - platform.prevX;
                const dy = platform.y - platform.prevY;
                
                // 如果玩家在平台上,让玩家随平台移动
                if (player.onPlatform && player.lastPlatform === platform) {
                    player.x += dx;
                    player.y += dy;
                }
            });
        }
        
        function checkSolidCollision(rect) {
            const items = [...tiles, ...obstacles, ...platforms];
            
            for (const item of items) {
                if (item.type && (item.type.solid || item.type === TILE_TYPES.PILLAR)) {
                    if (
                        rect.x < item.x + item.w &&
                        rect.x + rect.width > item.x &&
                        rect.y < item.y + item.h &&
                        rect.y + rect.height > item.y
                    ) {
                        return true;
                    }
                }
            }
            return false;
        }
        
        function checkCollision(rect1, rect2) {
            return (
                rect1.x < rect2.x + rect2.w &&
                rect1.x + rect1.width > rect2.x &&
                rect1.y < rect2.y + rect2.h &&
                rect1.y + rect1.height > rect2.y
            );
        }
        
        function checkCollisions() {
            // 检查致命障碍物
            [...obstacles, ...platforms].forEach(item => {
                if (item.type && item.type.fatal) {
                    // 修复Bug 3: 尖刺碰撞检测
                    if (item.type === TILE_TYPES.SPIKE) {
                        const spikeRect = {
                            x: item.x,
                            y: item.y + item.h - 24,
                            width: item.w,
                            height: 24
                        };
                        
                        const playerBottom = player.y + player.height;
                        const spikeTop = spikeRect.y;
                        
                        if (playerBottom > spikeTop - 5 && playerBottom < spikeTop + 10 &&
                            player.x + player.width > spikeRect.x &&
                            player.x < spikeRect.x + spikeRect.width) {
                            
                            createDeathParticles();
                            endGame('撞上尖刺!');
                            return;
                        }
                    } else {
                        if (checkCollision(player, item)) {
                            createDeathParticles();
                            endGame(`撞上${item.type === TILE_TYPES.LAVA ? '岩浆' : '致命障碍物'}!`);
                            return;
                        }
                    }
                }
            });
            
            // ==================== 修复Bug 6: 梯子交互逻辑问题 ====================
            let onLadder = false;
            obstacles.forEach(item => {
                if (item.type === TILE_TYPES.LADDER) {
                    const ladderRect = {
                        x: item.x,
                        y: item.y,
                        w: item.w,
                        h: item.h
                    };
                    
                    const playerCenterX = player.x + player.width / 2;
                    const playerCenterY = player.y + player.height / 2;
                    
                    // 放宽梯子碰撞检测
                    if (playerCenterX > item.x - 16 && 
                        playerCenterX < item.x + item.w + 16 &&
                        playerCenterY > item.y && 
                        playerCenterY < item.y + item.h) {
                        
                        // 如果按W键并且玩家接近梯子顶部,可以爬上去
                        if (keys['w'] && player.y + player.height < item.y + item.h + 10) {
                            onLadder = true;
                            player.onLadder = true;
                            player.y -= 3;
                        }
                        // 如果按S键并且玩家在梯子顶部,可以爬下来
                        else if (keys['s'] && player.y + player.height > item.y) {
                            onLadder = true;
                            player.onLadder = true;
                            player.y += 3;
                        }
                        // 如果玩家站在梯子范围内,可以爬上爬下
                        else if (Math.abs(playerCenterX - (item.x + item.w/2)) < 20) {
                            onLadder = true;
                            player.onLadder = true;
                        }
                        
                        if (player.onLadder) {
                            player.velY = 0;
                            player.isJumping = false;
                        }
                    }
                }
            });
            
            if (!onLadder) {
                player.onLadder = false;
            }
            
            // 修复Bug 4: 玩家碰撞检测中的陷地问题
            const allSolids = [...tiles, ...obstacles, ...platforms];
            
            player.onGround = false;
            player.onPlatform = false;
            player.lastPlatform = null;
            
            if (player.velY > 0) {
                const nextY = player.y + player.velY;
                const bottom = nextY + player.height;
                
                for (const item of allSolids) {
                    if (item.type && (item.type.solid || item.type === TILE_TYPES.PILLAR)) {
                        if (bottom > item.y && bottom < item.y + 20 &&
                            player.x + player.width > item.x &&
                            player.x < item.x + item.w) {
                            
                            player.y = item.y - player.height;
                            player.velY = 0;
                            player.onGround = true;
                            player.isJumping = false;
                            
                            if (platforms.includes(item)) {
                                player.onPlatform = true;
                                player.lastPlatform = item;
                            }
                            break;
                        }
                    }
                }
            }
            
            if (player.velX !== 0) {
                const nextX = player.x + player.velX;
                
                for (const item of allSolids) {
                    if (item.type && (item.type.solid || item.type === TILE_TYPES.PILLAR)) {
                        if ((player.velX > 0 && nextX + player.width > item.x && player.x < item.x && 
                             player.y + player.height > item.y && player.y < item.y + item.h) ||
                            (player.velX < 0 && nextX < item.x + item.w && player.x > item.x &&
                             player.y + player.height > item.y && player.y < item.y + item.h)) {
                            
                            if (player.velX > 0) {
                                player.x = item.x - player.width;
                            } else {
                                player.x = item.x + item.w;
                            }
                            player.velX = 0;
                            break;
                        }
                    }
                }
            }
            
            // ==================== 修复Bug 3: 弹簧碰撞检测 ====================
            springs.forEach(spring => {
                const springRect = {
                    x: spring.x,
                    y: spring.y,
                    w: spring.w,
                    h: spring.h
                };
                
                // 只从顶部碰撞才触发弹簧
                if (player.x + player.width > springRect.x &&
                    player.x < springRect.x + springRect.w &&
                    player.y + player.height > springRect.y &&
                    player.y + player.height < springRect.y + 15) { // 只检测顶部15像素
                    
                    player.velY = -15;
                    player.isJumping = true;
                    player.onGround = false;
                    player.onPlatform = false;
                    createJumpTrail();
                    createSpringEffect(spring);
                }
            });
            
            if (player.y > DEATH_LINE) {
                createDeathParticles();
                endGame('掉出地图啦!');
                return;
            }
        }
        
        // 修复Bug 6: 终点检测问题
        function checkEndPoint() {
            endPoints.forEach(endPoint => {
                const playerRect = {
                    x: player.x,
                    y: player.y,
                    width: player.width,
                    height: player.height
                };
                
                const endRect = {
                    x: endPoint.x,
                    y: endPoint.y,
                    width: endPoint.w,
                    height: endPoint.h
                };
                
                if (playerRect.x < endRect.x + endRect.width &&
                    playerRect.x + playerRect.width > endRect.x &&
                    playerRect.y < endRect.y + endRect.height &&
                    playerRect.y + playerRect.height > endRect.y) {
                    
                    if (!gameOver) {
                        winGame();
                    }
                }
            });
        }
        
        function createSpringEffect(spring) {
            for (let i = 0; i < 15; i++) {
                particles.push({
                    x: spring.x + spring.w / 2,
                    y: spring.y,
                    size: Math.random() * 6 + 3,
                    color: '#FFFF00',
                    alpha: 1,
                    life: 30,
                    velX: (Math.random() - 0.5) * 4,
                    velY: -Math.random() * 6
                });
            }
        }
        
        // ==================== 性能优化: 限制粒子数量 ====================
        function createDeathParticles() {
            // 限制最多100个粒子
            if (particles.length > 100) return;
            
            for (let i = 0; i < 15; i++) { // 减少粒子数量
                particles.push({
                    x: player.x + player.width / 2,
                    y: player.y + player.height / 2,
                    size: Math.random() * 8 + 3, // 减小大小
                    color: '#FF4500',
                    alpha: 1,
                    life: 40, // 减少生命周期
                    velX: (Math.random() - 0.5) * 8,
                    velY: (Math.random() - 0.5) * 8
                });
            }
        }
        
        function updateParticles() {
            for (let i = particles.length - 1; i >= 0; i--) {
                const particle = particles[i];
                particle.x += particle.velX;
                particle.y += particle.velY;
                particle.alpha -= 0.04; // 加快消失
                particle.life--;
                
                if (particle.life <= 0 || particle.alpha <= 0) {
                    particles.splice(i, 1);
                }
            }
        }
        
        function updateCamera() {
            targetCameraOffset.x = player.x - CANVAS_WIDTH / 2;
            targetCameraOffset.y = player.y - CANVAS_HEIGHT / 2;
            
            cameraOffset.x += (targetCameraOffset.x - cameraOffset.x) * CAMERA_SMOOTHING;
            cameraOffset.y += (targetCameraOffset.y - cameraOffset.y) * CAMERA_SMOOTHING;
            
            cameraOffset.x = Math.max(0, Math.min(cameraOffset.x, levelGoal));
            cameraOffset.y = Math.max(0, Math.min(cameraOffset.y, CANVAS_HEIGHT - GROUND_HEIGHT));
        }
        
        function collectDiamonds() {
            diamonds.forEach(diamond => {
                if (!diamond.collected && checkCollision(player, diamond)) {
                    diamond.collected = true;
                    diamondsCollected++;
                    score += 100;
                    document.getElementById('score-display').textContent = score;
                    
                    for (let i = 0; i < 10; i++) {
                        particles.push({
                            x: diamond.x + diamond.w / 2,
                            y: diamond.y + diamond.h / 2,
                            size: Math.random() * 4 + 2,
                            color: '#00FFFF',
                            alpha: 1,
                            life: 30,
                            velX: (Math.random() - 0.5) * 3,
                            velY: (Math.random() - 0.5) * 3
                        });
                    }
                }
            });
        }
        
        function respawnAtStart() {
            resetKeys();
            
            player.x = 100;
            player.y = CANVAS_HEIGHT - GROUND_HEIGHT - player.height;
            player.velX = 0;
            player.velY = 0;
            player.isJumping = false;
            player.isCrouching = false;
            player.isForcedCrouching = false;
            player.height = player.originalHeight;
            player.speed = PLAYER_SPEED;
            player.platformVelX = 0;
            player.platformVelY = 0;
            
            cameraOffset = { x: 0, y: 0 };
            targetCameraOffset = { x: 0, y: 0 };
            
            document.getElementById('game-over-modal').style.display = 'none';
            gameStarted = true;
            gameOver = false;
            
            gameLoop();
        }
        
        // ==================== 渲染系统 ====================
        function draw() {
            ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
            
            ctx.fillStyle = '#87CEEB';
            ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT - GROUND_HEIGHT);
            
            drawClouds();
            drawTiles();
            drawObstacles();
            drawPlatforms();
            drawSprings();
            drawDiamonds();
            drawEndPoints();
            drawPlayer();
            drawJumpTrails();
            drawParticles();
        }
        
        function drawClouds() {
            ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
            
            ctx.beginPath();
            ctx.arc(200 - cameraOffset.x * 0.2, 80 - cameraOffset.y * 0.1, 20, 0, Math.PI * 2);
            ctx.arc(230 - cameraOffset.x * 0.2, 70 - cameraOffset.y * 0.1, 25, 0, Math.PI * 2);
            ctx.arc(260 - cameraOffset.x * 0.2, 80 - cameraOffset.y * 0.1, 20, 0, Math.PI * 2);
            ctx.fill();
            
            ctx.beginPath();
            ctx.arc(500 - cameraOffset.x * 0.2, 120 - cameraOffset.y * 0.1, 25, 0, Math.PI * 2);
            ctx.arc(540 - cameraOffset.x * 0.2, 110 - cameraOffset.y * 0.1, 30, 0, Math.PI * 2);
            ctx.arc(580 - cameraOffset.x * 0.2, 120 - cameraOffset.y * 0.1, 25, 0, Math.PI * 2);
            ctx.fill();
        }
        
        // ==================== 性能优化: 视锥体剔除 ====================
        function drawTiles() {
            tiles.forEach(item => {
                const x = item.x - cameraOffset.x;
                const y = item.y - cameraOffset.y;
                // 只在视口内绘制
                if (x > -TILE_SIZE * 2 && x < CANVAS_WIDTH + TILE_SIZE * 2 &&
                    y > -TILE_SIZE * 2 && y < CANVAS_HEIGHT + TILE_SIZE * 2) {
                    TEXTURES[item.type.texture].draw(ctx, x, y, item.w, item.h);
                }
            });
        }
        
        function drawObstacles() {
            obstacles.forEach(item => {
                const x = item.x - cameraOffset.x;
                const y = item.y - cameraOffset.y;
                if (x > -item.w - 50 && x < CANVAS_WIDTH + item.w + 50) {
                    if (item.type.texture) {
                        TEXTURES[item.type.texture].draw(ctx, x, y, item.w, item.h);
                    } else {
                        ctx.fillStyle = item.type.color;
                        ctx.fillRect(x, y, item.w, item.h);
                    }
                }
            });
        }
        
        function drawPlatforms() {
            platforms.forEach(platform => {
                const x = platform.x - cameraOffset.x;
                const y = platform.y - cameraOffset.y;
                if (x > -platform.w - 50 && x < CANVAS_WIDTH + platform.w + 50) {
                    if (platform.type.texture) {
                        TEXTURES[platform.type.texture].draw(ctx, x, y, platform.w, platform.h);
                    } else {
                        ctx.fillStyle = platform.type.color;
                        ctx.fillRect(x, y, platform.w, platform.h);
                    }
                }
            });
        }
        
        function drawSprings() {
            springs.forEach(spring => {
                const x = spring.x - cameraOffset.x;
                const y = spring.y - cameraOffset.y;
                if (x > -spring.w - 50 && x < CANVAS_WIDTH + spring.w + 50) {
                    if (spring.type.texture) {
                        TEXTURES[spring.type.texture].draw(ctx, x, y, spring.w, spring.h);
                    } else {
                        ctx.fillStyle = spring.type.color;
                        ctx.fillRect(x, y, spring.w, spring.h);
                    }
                }
            });
        }
        
        function drawDiamonds() {
            diamonds.forEach(diamond => {
                if (!diamond.collected) {
                    const x = diamond.x - cameraOffset.x;
                    const y = diamond.y - cameraOffset.y;
                    if (x > -diamond.w - 50 && x < CANVAS_WIDTH + diamond.w + 50) {
                        ctx.fillStyle = '#00FFFF';
                        ctx.beginPath();
                        ctx.moveTo(x + diamond.w/2, y);
                        ctx.lineTo(x + diamond.w, y + diamond.h/2);
                        ctx.lineTo(x + diamond.w/2, y + diamond.h);
                        ctx.lineTo(x, y + diamond.h/2);
                        ctx.closePath();
                        ctx.fill();
                        
                        ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
                        ctx.beginPath();
                        ctx.arc(x + diamond.w/2, y + diamond.h/2, 5, 0, Math.PI * 2);
                        ctx.fill();
                    }
                }
            });
        }
        
        function drawEndPoints() {
            endPoints.forEach(endPoint => {
                const x = endPoint.x - cameraOffset.x;
                const y = endPoint.y - cameraOffset.y;
                
                if (x > -60 - 50 && x < CANVAS_WIDTH + 60 + 50) {
                    ctx.fillStyle = '#FFD700';
                    ctx.fillRect(x, y + 60, 60, 20);
                    
                    ctx.strokeStyle = '#B8860B';
                    ctx.lineWidth = 2;
                    ctx.strokeRect(x, y + 60, 60, 20);
                    
                    ctx.fillStyle = '#000';
                    ctx.fillRect(x + 60, y, 5, 80);
                    
                    for (let i = 0; i < 6; i++) {
                        for (let j = 0; j < 4; j++) {
                            ctx.fillStyle = (i + j) % 2 === 0 ? '#000' : '#fff';
                            ctx.fillRect(x + 65 + j * 10, y + i * 10, 10, 10);
                        }
                    }
                    
                    ctx.fillStyle = '#000';
                    ctx.font = '14px Courier New';
                    ctx.fillText('终点', x + 10, y + 75);
                }
            });
        }
        
        // ==================== 游戏体验改进: 添加简单动画 ====================
        function drawPlayer() {
            const x = player.x - cameraOffset.x;
            const y = player.y - cameraOffset.y;
            
            // 添加跳跃动画
            let bobOffset = 0;
            if (player.isJumping) {
                bobOffset = Math.sin(Date.now() / 50) * 2;
            }
            
            ctx.fillStyle = '#3d85c6';
            ctx.fillRect(x + 4, y + 10 + bobOffset, player.width - 8, player.height - 10);
            
            // 头部旋转动画
            const headBob = Math.sin(Date.now() / 100) * 1;
            
            ctx.fillStyle = '#f1c27d';
            ctx.fillRect(x + 6, y + headBob, player.width - 12, 10);
            
            // 眼睛
            ctx.fillStyle = '#000';
            if (player.facingRight) {
                ctx.fillRect(x + player.width - 8, y + 3 + headBob, 2, 2);
            } else {
                ctx.fillRect(x + 6, y + 3 + headBob, 2, 2);
            }
        }
        
        function drawJumpTrails() {
            jumpTrails.forEach(trail => {
                const x = trail.x - cameraOffset.x;
                const y = trail.y - cameraOffset.y;
                
                ctx.fillStyle = `rgba(255, 255, 255, ${trail.alpha})`;
                ctx.beginPath();
                ctx.arc(x, y, trail.size, 0, Math.PI * 2);
                ctx.fill();
            });
        }
        
        function drawParticles() {
            particles.forEach(particle => {
                const x = particle.x - cameraOffset.x;
                const y = particle.y - cameraOffset.y;
                
                ctx.fillStyle = `${particle.color}${Math.floor(particle.alpha * 255).toString(16).padStart(2, '0')}`;
                ctx.beginPath();
                ctx.arc(x, y, particle.size, 0, Math.PI * 2);
                ctx.fill();
            });
        }
        
        // 游戏循环控制
        let gameLoopId = null;
        
        function gameLoop() {
            if (gameLoopId) {
                cancelAnimationFrame(gameLoopId);
            }
            
            if (!gameStarted || gameOver) return;
            update();
            draw();
            gameLoopId = requestAnimationFrame(gameLoop);
        }
        
        // ==================== 游戏流程控制 ====================
        function showHelp() {
            document.getElementById('help-modal').style.display = 'block';
        }
        
        function endGame(reason) {
            gameOver = true;
            gameStarted = false;
            
            if (gameLoopId) {
                cancelAnimationFrame(gameLoopId);
                gameLoopId = null;
            }
            
            function continueParticles() {
                if (particles.length > 0) {
                    updateParticles();
                    draw();
                    requestAnimationFrame(continueParticles);
                }
            }
            
            createDeathParticles();
            
            document.getElementById('game-over-title').textContent = "游戏结束";
            document.getElementById('game-over-reason').textContent = reason;
            
            document.getElementById('diamonds-collected').textContent = diamondsCollected;
            document.getElementById('final-score').textContent = score;
            
            document.getElementById('game-over-modal').style.display = 'block';
            
            continueParticles();
        }
        
        function winGame() {
            gameOver = true;
            gameStarted = false;
            
            if (gameLoopId) {
                cancelAnimationFrame(gameLoopId);
                gameLoopId = null;
            }
            
            document.getElementById('win-diamonds').textContent = diamondsCollected;
            document.getElementById('win-score').textContent = score;
            
            document.getElementById('win-modal').style.display = 'block';
        }
        
        // ==================== 修复Bug 4: 游戏重启时的状态问题 ====================
        function restartGame() {
            if (gameLoopId) {
                cancelAnimationFrame(gameLoopId);
                gameLoopId = null;
            }
            
            // 清理所有粒子效果
            particles = [];
            jumpTrails = [];
            
            document.getElementById('game-over-modal').style.display = 'none';
            document.getElementById('win-modal').style.display = 'none';
            
            currentSeed = generateRandomSeed();
            generateLevel(currentSeed);
            
            gameStarted = true;
            gameOver = false;
            score = 0;
            diamondsCollected = 0;
            document.getElementById('score-display').textContent = score;
            
            gameLoop();
        }
        
        function playAgain() {
            if (gameLoopId) {
                cancelAnimationFrame(gameLoopId);
                gameLoopId = null;
            }
            
            // 清理所有粒子效果
            particles = [];
            jumpTrails = [];
            
            document.getElementById('win-modal').style.display = 'none';
            
            generateLevel(currentSeed);
            
            gameStarted = true;
            gameOver = false;
            score = 0;
            diamondsCollected = 0;
            document.getElementById('score-display').textContent = score;
            
            gameLoop();
        }
        
        function newWorld() {
            if (gameLoopId) {
                cancelAnimationFrame(gameLoopId);
                gameLoopId = null;
            }
            
            // 清理所有粒子效果
            particles = [];
            jumpTrails = [];
            
            document.getElementById('win-modal').style.display = 'none';
            
            currentSeed = generateRandomSeed();
            generateLevel(currentSeed);
            
            gameStarted = true;
            gameOver = false;
            score = 0;
            diamondsCollected = 0;
            document.getElementById('score-display').textContent = score;
            
            gameLoop();
        }
        
        // 启动游戏
        init();
    </script>
</body>
</html>

可以直接在ourcraft.xin上游玩,这是我的网站谢谢

相关推荐
小徐不会敲代码~1 小时前
Vue3 学习
前端·javascript·vue.js·学习
大猩猩X1 小时前
vue vxe-gantt table 甘特图实现多个维度视图展示,支持切换年视图、月视图、周视图等
前端·javascript·甘特图·vxe-table·vxe-ui
m0_740043731 小时前
Element-UI 组件库的核心组件及其用法
前端·javascript·vue.js·ui·elementui·html
游九尘1 小时前
js:获取上一周,本周,下一周,上个月,本月,下个月的日期时间段
javascript
脾气有点小暴1 小时前
H5 跳转方式
前端·javascript
Doris8931 小时前
【JS】JS进阶--作用域、函数、解构赋值、数组方法
开发语言·前端·javascript
黑客思维者1 小时前
核弹级漏洞突袭React生态:RSC反序列化何以成为RCE通道?
前端·javascript·react.js·远程代码执行漏洞
野蛮人6号1 小时前
力扣热题100道之45跳跃游戏2
算法·leetcode·游戏
AndrewHZ2 小时前
【GIS数据处理】什么是Cesium?从零入门Web端三维地理可视化工具
javascript·gis·web开发·cesium·gis前端·三维地理可视化