2025-07-20

<!DOCTYPE html>

<html lang="zh-CN">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>像素鸟游戏复刻版</title>

    <style>

        * {

            margin: 0;

            padding: 0;

            box-sizing: border-box;

            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

        }

       

        body {

            display: flex;

            justify-content: center;

            align-items: center;

            min-height: 100vh;

            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);

            overflow: hidden;

            padding: 20px;

        }

       

        .game-container {

            position: relative;

            width: 800px;

            max-width: 95%;

            display: flex;

            flex-direction: column;

            align-items: center;

            gap: 20px;

        }

       

        .game-header {

            display: flex;

            justify-content: space-between;

            align-items: center;

            width: 100%;

            background: rgba(0, 0, 0, 0.7);

            padding: 15px 25px;

            border-radius: 15px;

            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4);

        }

       

        .game-title {

            color: white;

            font-size: 2.2rem;

            letter-spacing: 2px;

            text-shadow: 0 0 10px #ff9900;

        }

       

        .game-stats {

            display: flex;

            gap: 25px;

        }

       

        .stat-box {

            background: rgba(255, 255, 255, 0.9);

            padding: 10px 20px;

            border-radius: 10px;

            text-align: center;

            min-width: 120px;

            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);

        }

       

        .stat-label {

            font-weight: bold;

            color: #333;

            font-size: 1rem;

        }

       

        .stat-value {

            font-weight: bold;

            color: #ff6600;

            font-size: 1.8rem;

        }

       

        .game-canvas-container {

            position: relative;

            width: 100%;

            background: #70c5ce;

            border-radius: 15px;

            overflow: hidden;

            box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);

        }

       

        canvas {

            display: block;

        }

       

        .theme-controls {

            display: flex;

            justify-content: center;

            gap: 30px;

            margin-top: 10px;

        }

       

        .btn {

            background: linear-gradient(45deg, #ff8a00, #ff2070);

            color: white;

            border: none;

            padding: 12px 25px;

            font-size: 1.1rem;

            border-radius: 50px;

            cursor: pointer;

            transition: all 0.3s ease;

            font-weight: bold;

            letter-spacing: 1px;

            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);

        }

       

        .btn:hover {

            transform: translateY(-3px);

            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);

        }

       

        .btn:active {

            transform: translateY(1px);

        }

       

        #themeToggleBtn {

            background: linear-gradient(45deg, #4776E6, #8E54E9);

        }

       

        #skinShopBtn {

            background: linear-gradient(45deg, #00c9ff, #92fe9d);

        }

       

        .modal {

            position: fixed;

            top: 0;

            left: 0;

            width: 100%;

            height: 100%;

            background: rgba(0, 0, 0, 0.8);

            display: flex;

            justify-content: center;

            align-items: center;

            opacity: 0;

            visibility: hidden;

            transition: all 0.4s;

            z-index: 100;

        }

       

        .modal.active {

            opacity: 1;

            visibility: visible;

        }

       

        .modal-content {

            background: linear-gradient(135deg, #2c3e50, #1a1a2e);

            width: 90%;

            max-width: 800px;

            padding: 30px;

            border-radius: 20px;

            position: relative;

            transform: translateY(-20px);

            transition: transform 0.4s;

            box-shadow: 0 15px 35px rgba(0, 0, 0, 0.7);

            max-height: 90vh;

            overflow-y: auto;

        }

       

        .modal.active .modal-content {

            transform: translateY(0);

        }

       

        .close-modal {

            position: absolute;

            top: 20px;

            right: 25px;

            font-size: 2rem;

            color: white;

            cursor: pointer;

            transition: transform 0.3s;

        }

       

        .close-modal:hover {

            transform: rotate(90deg);

            color: #ff5252;

        }

       

        .modal-title {

            color: white;

            text-align: center;

            margin-bottom: 25px;

            font-size: 2.2rem;

            text-shadow: 0 0 10px #00b4d8;

        }

       

        .skin-grid {

            display: grid;

            grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));

            gap: 20px;

            margin-bottom: 30px;

        }

       

        .skin-card {

            background: rgba(255, 255, 255, 0.1);

            border-radius: 12px;

            padding: 15px;

            text-align: center;

            cursor: pointer;

            transition: all 0.3s;

            border: 2px solid transparent;

        }

       

        .skin-card:hover {

            background: rgba(255, 255, 255, 0.15);

            transform: translateY(-5px);

        }

       

        .skin-card.selected {

            border-color: #00e5ff;

            box-shadow: 0 0 15px rgba(0, 229, 255, 0.7);

        }

       

        .skin-card.locked {

            filter: grayscale(80%);

            opacity: 0.7;

            cursor: not-allowed;

        }

       

        .skin-preview {

            width: 100%;

            height: 120px;

            border-radius: 8px;

            margin-bottom: 10px;

            background-size: contain;

            background-position: center;

            background-repeat: no-repeat;

        }

       

        .skin-name {

            color: white;

            font-weight: bold;

            margin: 8px 0;

        }

       

        .skin-price {

            color: #ffcc00;

            font-size: 1.1rem;

            font-weight: bold;

        }

       

        #buySkinBtn {

            display: block;

            margin: 20px auto 0;

            padding: 14px 45px;

            font-size: 1.2rem;

        }

       

        .notification {

            position: fixed;

            top: 20px;

            right: 20px;

            background: rgba(0, 0, 0, 0.8);

            color: white;

            padding: 15px 25px;

            border-radius: 10px;

            transform: translateX(200%);

            transition: transform 0.5s;

            z-index: 200;

        }

       

        .notification.show {

            transform: translateX(0);

        }

       

        @media (max-width: 600px) {

            .game-header {

                flex-direction: column;

                gap: 15px;

            }

           

            .game-title {

                font-size: 1.8rem;

            }

           

            .skin-grid {

                grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));

            }

           

            .theme-controls {

                flex-direction: column;

                gap: 15px;

            }

           

            .btn {

                width: 100%;

            }

        }

    </style>

</head>

<body>

    <div class="game-container">

        <div class="game-header">

            <div class="game-title">像素鸟复刻版</div>

            <div class="game-stats">

                <div class="stat-box">

                    <div class="stat-label">分数</div>

                    <div id="score" class="stat-value">0</div>

                </div>

                <div class="stat-box">

                    <div class="stat-label">金币</div>

                    <div id="coins" class="stat-value">50</div>

                </div>

            </div>

        </div>

       

        <div class="game-canvas-container">

            <canvas id="gameCanvas" width="800" height="500"></canvas>

        </div>

       

        <div class="theme-controls">

            <button id="themeToggleBtn" class="btn">切换昼夜</button>

            <button id="skinShopBtn" class="btn">皮肤商店</button>

            <button id="startBtn" class="btn">开始游戏</button>

        </div>

    </div>

   

    <!-- 皮肤商店弹窗 -->

    <div id="skinShop" class="modal">

        <div class="modal-content">

            <span class="close-modal">×</span>

            <h2 class="modal-title">皮肤商店</h2>

            <div class="skin-grid" id="skinContainer">

                <!-- 皮肤将通过JavaScript动态添加 -->

            </div>

            <button id="buySkinBtn" class="btn">购买并应用</button>

        </div>

    </div>

   

    <div id="notification" class="notification">

        <p>购买成功!已应用新皮肤</p>

    </div>


    <script>

        // 游戏常量

        const GRAVITY = 0.5;

        const JUMP_FORCE = -10;

        const PIPE_WIDTH = 70;

        const PIPE_GAP = 180;

        const PIPE_SPACING = 250;

        const GROUND_HEIGHT = 100;

        const BIRD_WIDTH = 40;

        const BIRD_HEIGHT = 30;

       

        // DOM 元素

        const canvas = document.getElementById('gameCanvas');

        const ctx = canvas.getContext('2d');

        const scoreElement = document.getElementById('score');

        const coinsElement = document.getElementById('coins');

        const themeToggleBtn = document.getElementById('themeToggleBtn');

        const skinShopBtn = document.getElementById('skinShopBtn');

        const startBtn = document.getElementById('startBtn');

        const skinShop = document.getElementById('skinShop');

        const closeModal = document.querySelector('.close-modal');

        const skinContainer = document.getElementById('skinContainer');

        const buySkinBtn = document.getElementById('buySkinBtn');

        const notification = document.getElementById('notification');

       

        // 游戏状态

        let gameState = 'start'; // start, playing, gameover

        let score = 0;

        let coins = 50;

        let dayMode = true;

        let selectedSkin = 'green';

       

        // 皮肤数据

        const skins = [

            { id: 'green', name: '森林管道', price: 0, unlocked: true },

            { id: 'winter', name: '冬季管道', price: 20, unlocked: false },

            { id: 'desert', name: '沙漠管道', price: 30, unlocked: false },

            { id: 'candy', name: '糖果管道', price: 40, unlocked: false },

            { id: 'gold', name: '黄金管道', price: 50, unlocked: false },

            { id: 'diamond', name: '钻石管道', price: 100, unlocked: false }

        ];

       

        // 鸟对象

        const bird = {

            x: 100,

            y: canvas.height / 2 - 15,

            width: BIRD_WIDTH,

            height: BIRD_HEIGHT,

            velocity: 0,

           

            draw: function() {

                ctx.save();

               

                // 绘制鸟的身体

                ctx.fillStyle = dayMode ? '#FFD700' : '#FFA500';

                ctx.beginPath();

                ctx.arc(this.x + 15, this.y + 15, 15, 0, Math.PI * 2);

                ctx.fill();

               

                // 绘制鸟的眼睛

                ctx.fillStyle = 'black';

                ctx.beginPath();

                ctx.arc(this.x + 20, this.y + 12, 3, 0, Math.PI * 2);

                ctx.fill();

               

                // 绘制鸟的喙

                ctx.fillStyle = '#FF8C00';

                ctx.beginPath();

                ctx.moveTo(this.x + 25, this.y + 15);

                ctx.lineTo(this.x + 35, this.y + 15);

                ctx.lineTo(this.x + 25, this.y + 20);

                ctx.fill();

               

                // 绘制鸟的翅膀

                ctx.fillStyle = dayMode ? '#FF6347' : '#CD5C5C';

                ctx.beginPath();

                ctx.moveTo(this.x + 10, this.y + 15);

                ctx.quadraticCurveTo(this.x + 5, this.y + 25, this.x + 10, this.y + 25);

                ctx.quadraticCurveTo(this.x + 15, this.y + 20, this.x + 10, this.y + 15);

                ctx.fill();

               

                ctx.restore();

            },

           

            update: function() {

                // 应用重力

                this.velocity += GRAVITY;

                this.y += this.velocity;

               

                // 地面碰撞检测

                if (this.y + this.height > canvas.height - GROUND_HEIGHT) {

                    this.y = canvas.height - GROUND_HEIGHT - this.height;

                   

                    if (gameState === 'playing') {

                        gameOver();

                    }

                }

               

                // 天花板碰撞检测

                if (this.y < 0) {

                    this.y = 0;

                    this.velocity = 0;

                }

            },

           

            jump: function() {

                if (gameState === 'playing') {

                    this.velocity = JUMP_FORCE;

                } else if (gameState === 'start') {

                    startGame();

                }

            },

           

            reset: function() {

                this.y = canvas.height / 2 - 15;

                this.velocity = 0;

            }

        };

       

        // 管道数组

        const pipes = [];

       

        // 管道对象

        class Pipe {

            constructor() {

                this.x = canvas.width;

                this.width = PIPE_WIDTH;

                this.gapStart = Math.random() * (canvas.height - GROUND_HEIGHT - PIPE_GAP - 50) + 25;

                this.gapEnd = this.gapStart + PIPE_GAP;

                this.passed = false;

            }

           

            draw() {

                // 上管道

                ctx.fillStyle = this.getPipeColor();

                ctx.fillRect(this.x, 0, this.width, this.gapStart);

               

                // 下管道

                ctx.fillRect(this.x, this.gapEnd, this.width, canvas.height - this.gapEnd);

               

                // 管道帽

                ctx.fillStyle = this.getPipeCapColor();

                ctx.fillRect(this.x - 5, this.gapStart - 20, this.width + 10, 20);

                ctx.fillRect(this.x - 5, this.gapEnd, this.width + 10, 20);

            }

           

            update() {

                this.x -= 3;

               

                // 检查鸟是否通过管道

                if (!this.passed && this.x + this.width < bird.x) {

                    score++;

                    scoreElement.textContent = score;

                    this.passed = true;

                   

                    // 获得金币

                    coins++;

                    coinsElement.textContent = coins;

                }

               

                // 碰撞检测

                if (detectCollision(bird, this)) {

                    gameOver();

                }

            }

           

            isOffScreen() {

                return this.x + this.width < 0;

            }

           

            getPipeColor() {

                switch(selectedSkin) {

                    case 'winter': return '#A4DEF9';

                    case 'desert': return '#DEB887';

                    case 'candy': return '#FF9AA2';

                    case 'gold': return '#FFD700';

                    case 'diamond': return '#B9F2FF';

                    default: return '#4CAF50'; // green

                }

            }

           

            getPipeCapColor() {

                switch(selectedSkin) {

                    case 'winter': return '#70d6ff';

                    case 'desert': return '#E1C16E';

                    case 'candy': return '#FFB7C5';

                    case 'gold': return '#FFA500';

                    case 'diamond': return '#66FFFF';

                    default: return '#2E8B57'; // green

                }

            }

        }

       

        // 精确碰撞检测函数

        function detectCollision(bird, pipe) {

            // 鸟的边界

            const birdLeft = bird.x;

            const birdRight = bird.x + bird.width;

            const birdTop = bird.y;

            const birdBottom = bird.y + bird.height;

           

            // 下管道的边界

            const bottomPipeTop = pipe.gapEnd;

           

            // 检测与上管道的碰撞

            if (birdRight > pipe.x &&

                birdLeft < pipe.x + pipe.width &&

                birdTop < pipe.gapStart) {

                return true;

            }

           

            // 检测与下管道的碰撞

            if (birdRight > pipe.x &&

                birdLeft < pipe.x + pipe.width &&

                birdBottom > bottomPipeTop) {

                return true;

            }

           

            return false;

        }

       

        // 游戏函数

        function startGame() {

            gameState = 'playing';

            score = 0;

            scoreElement.textContent = score;

            pipes.length = 0;

            bird.reset();

        }

       

        function gameOver() {

            gameState = 'gameover';

           

            // 添加新的金币

            coins += Math.floor(score / 5);

            coinsElement.textContent = coins;

           

            // 短暂暂停后回到开始状态

            setTimeout(() => {

                gameState = 'start';

            }, 2000);

        }

       

        // 添加新管道

        function addPipe() {

            if (gameState === 'playing' &&

                (pipes.length === 0 ||

                canvas.width - pipes[pipes.length - 1].x > PIPE_SPACING)) {

                pipes.push(new Pipe());

            }

        }

       

        // 游戏循环

        function gameLoop() {

            // 绘制背景

            if (dayMode) {

                ctx.fillStyle = '#87CEEB';

            } else {

                ctx.fillStyle = '#1a1a2e';

            }

            ctx.fillRect(0, 0, canvas.width, canvas.height);

           

            // 绘制云朵(只在白天模式)

            if (dayMode) {

                ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';

                for(let i = 0; i < 5; i++) {

                    const x = (Date.now() / 40 + i * 100) % (canvas.width + 200) - 100;

                    ctx.beginPath();

                    ctx.arc(x, 70, 25, 0, Math.PI * 2);

                    ctx.arc(x + 20, 65, 20, 0, Math.PI * 2);

                    ctx.arc(x + 40, 70, 25, 0, Math.PI * 2);

                    ctx.fill();

                }

            }

           

            // 绘制星星(只在夜晚模式)

            if (!dayMode) {

                ctx.fillStyle = 'white';

                for(let i = 0; i < 50; i++) {

                    const x = i * 20 % canvas.width;

                    const y = (i * 7) % 200;

                    const size = Math.sin(Date.now() / 1000 + i) * 0.8 + 1.2;

                    ctx.beginPath();

                    ctx.arc(x, y, size, 0, Math.PI * 2);

                    ctx.fill();

                }

            }

           

            // 绘制地面

            ctx.fillStyle = dayMode ? '#8B4513' : '#654321';

            ctx.fillRect(0, canvas.height - GROUND_HEIGHT, canvas.width, GROUND_HEIGHT);

           

            // 绘制草地

            if (dayMode) {

                ctx.fillStyle = '#2E8B57';

            } else {

                ctx.fillStyle = '#1d5d2b';

            }

            ctx.fillRect(0, canvas.height - GROUND_HEIGHT, canvas.width, 20);

           

            // 绘制游戏元素

            bird.draw();

            bird.update();

           

            // 处理管道

            if (gameState === 'playing') {

                addPipe();

            }

           

            for (let i = 0; i < pipes.length; i++) {

                pipes[i].draw();

                if (gameState === 'playing') {

                    pipes[i].update();

                }

               

                // 移除屏幕外的管道

                if (pipes[i].isOffScreen()) {

                    pipes.splice(i, 1);

                    i--;

                }

            }

           

            // 游戏状态文本

            if (gameState === 'start') {

                ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';

                ctx.fillRect(0, 0, canvas.width, canvas.height);

               

                ctx.font = 'bold 48px Arial';

                ctx.fillStyle = 'white';

                ctx.textAlign = 'center';

                ctx.fillText('像素鸟复刻版', canvas.width / 2, canvas.height / 2 - 40);

               

                ctx.font = '20px Arial';

                ctx.fillText('点击屏幕或按空格键开始游戏', canvas.width / 2, canvas.height / 2 + 20);

               

                ctx.fillText('↑ 使用金币在商店购买新皮肤', canvas.width / 2, canvas.height / 2 + 60);

            }

           

            if (gameState === 'gameover') {

                ctx.font = 'bold 36px Arial';

                ctx.fillStyle = '#ff3333';

                ctx.textAlign = 'center';

                ctx.fillText('游戏结束!', canvas.width / 2, canvas.height / 2 - 20);

               

                ctx.font = 'bold 28px Arial';

                ctx.fillStyle = 'white';

                ctx.fillText(`最终分数: ${score}`, canvas.width / 2, canvas.height / 2 + 30);

            }

           

            requestAnimationFrame(gameLoop);

        }

       

        // 事件监听

        function initEventListeners() {

            // 点击或空格键跳跃

            canvas.addEventListener('click', () => {

                bird.jump();

            });

           

            document.addEventListener('keydown', (e) => {

                if (e.code === 'Space') {

                    bird.jump();

                }

            });

           

            // 切换昼夜主题

            themeToggleBtn.addEventListener('click', () => {

                dayMode = !dayMode;

                themeToggleBtn.textContent = dayMode ? '切换夜晚' : '切换白天';

            });

           

            // 打开皮肤商店

            skinShopBtn.addEventListener('click', () => {

                skinShop.classList.add('active');

                renderSkinShop();

            });

           

            // 关闭皮肤商店

            closeModal.addEventListener('click', () => {

                skinShop.classList.remove('active');

            });

           

            // 点击模态框外部关闭

            skinShop.addEventListener('click', (e) => {

                if (e.target === skinShop) {

                    skinShop.classList.remove('active');

                }

            });

           

            // 开始游戏按钮

            startBtn.addEventListener('click', startGame);

        }

       

        // 渲染皮肤商店

        function renderSkinShop() {

            skinContainer.innerHTML = '';

           

            skins.forEach(skin => {

                const skinCard = document.createElement('div');

                skinCard.className = `skin-card ${skin.id === selectedSkin ? 'selected' : ''} ${!skin.unlocked ? 'locked' : ''}`;

                skinCard.dataset.skin = skin.id;

               

                skinCard.innerHTML = `

                    <div class="skin-preview" style="background-color: ${skin.id === 'green' ? '#4CAF50' :

                                                    skin.id === 'winter' ? '#A4DEF9' :

                                                    skin.id === 'desert' ? '#DEB887' :

                                                    skin.id === 'candy' ? '#FF9AA2' :

                                                    skin.id === 'gold' ? '#FFD700' : '#B9F2FF'}"></div>

                    <div class="skin-name">${skin.name}</div>

                    ${!skin.unlocked ? `<div class="skin-price">${skin.price} 金币</div>` : ''}

                `;

               

                if (skin.unlocked || coins >= skin.price) {

                    skinCard.addEventListener('click', () => {

                        if (!skin.unlocked && coins < skin.price) return;

                       

                        document.querySelectorAll('.skin-card').forEach(card => {

                            card.classList.remove('selected');

                        });

                       

                        skinCard.classList.add('selected');

                        selectedSkin = skin.id;

                    });

                }

               

                skinContainer.appendChild(skinCard);

            });

        }

       

        // 购买皮肤按钮事件

        buySkinBtn.addEventListener('click', () => {

            const skin = skins.find(s => s.id === selectedSkin);

           

            // 如果皮肤已解锁,直接应用

            if (skin.unlocked) {

                skinShop.classList.remove('active');

                return;

            }

           

            // 如果金币足够

            if (coins >= skin.price) {

                coins -= skin.price;

                coinsElement.textContent = coins;

               

                skin.unlocked = true;

               

                renderSkinShop();

               

                // 显示通知

                notification.classList.add('show');

                setTimeout(() => {

                    notification.classList.remove('show');

                }, 2000);

            } else {

                alert('金币不足!');

            }

        });

       

        // 初始化

        function init() {

            initEventListeners();

            gameLoop();

        }

       

        // 启动游戏

        window.onload = init;

    </script>

</body>

</html>

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容