暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

通过CodeBuddy制作一个飞机大战游戏

168

点击标题下「蓝色微信名」可快速关注

《腾讯云代码助手CodeBuddy初体验》通过CodeBuddy进行了代码开发的过程体验,为做到学以致用,碰巧孩子暑假了,给孩子做了个飞机大战的游戏,只能算个不成熟的初稿,还能继续优化。

游戏的使用说明,

游戏使用说明:

1. 开始游戏:按任意键开始

2. 移动控制:方向键↑↓←→移动飞机

3. 射击:空格键发射子弹

4. 游戏规则:

击落敌机获得分数

被敌机击中会损失生命值

被击中后有短暂无敌时间(飞机会闪烁)

生命值归零游戏结束

5. 重新开始:游戏结束后按R键重新开始

游戏说明

相关的code如下,

    <!DOCTYPE html>
    <html>
    <head>
        <title>星空飞机大战</title>
        <style>
            body { 
                margin: 0; 
                overflow: hidden; 
                background: #000;
                display: flex;
                justify-content: center;
                align-items: center;
                height: 100vh;
            }
            canvas { 
                display: block; 
                background: #000;
                box-shadow: 0 0 20px #0066ff;
            }
            #score, #weapon, #lives {
                position: absolute;
                left: 20px;
                color: white;
                font-family: Arial, sans-serif;
                font-size: 24px;
                text-shadow: 0 0 5px #00a2ff;
            }
            #score {
                top: 20px;
            }
            #weapon {
                top: 60px;
                font-size: 18px;
            }
            #lives {
                top: 90px;
            }
        </style>
    </head>
    <body>
                <div id="score">分数: 0</div>
                <div id="weapon">当前武器: 普通子弹 (1-普通 2-散弹 3-激光)</div>
                <div id="lives">生命: ❤️❤️❤️</div>
                <canvas id="gameCanvas"></canvas>
        <script>
            // 游戏初始化
            const canvas = document.getElementById('gameCanvas');
            const ctx = canvas.getContext('2d');
            const scoreElement = document.getElementById('score');
            
            // 设置画布大小为窗口大小
            canvas.width = 800;
            canvas.height = 600;
            // 武器类型
            const WEAPON_TYPES = {
                NORMAL: {
                    name: "普通子弹",
                    color: "#00a2ff",
                    damage: 1,
                    delay: 100,
                    width: 4,
                    height: 20,
                    speed: 10
                },
                SPREAD: {
                    name: "散弹",
                    color: "#ff9900",
                    damage: 1,
                    delay: 300,
                    width: 3,
                    height: 15,
                    speed: 8,
                    count: 5
                },
                LASER: {
                    name: "激光",
                    color: "#ff00aa",
                    damage: 3,
                    delay: 500,
                    width: 10,
                    height: 30,
                    speed: 15
                }
            };
            // 敌机类型
            const ENEMY_TYPES = {
                NORMAL: {
                    width: 40,
                    height: 40,
                    speed: 1 + Math.random() * 2,
                    health: 1,
                    score: 100,
                    color: "#ff3300"
                },
                LARGE: {
                    width: 60,
                    height: 60,
                    speed: 0.5 + Math.random() * 1.5,
                    health: 2,
                    score: 200,
                    color: "#ff6600"
                },
                BOSS: {
                    width: 120,
                    height: 120,
                    speed: 0.3,
                    health: 20,
                    score: 1000,
                    color: "#ff0000",
                    attackPattern: "circle",
                    attackDelay: 2000
                }
            };
            // 游戏状态
            const game = {
                player: {
                    x: canvas.width / 2,
                    y: canvas.height - 100,
                    width: 50,
                    height: 40,
                    speed: 10,
                    isShooting: false,
                    lastShot: 0,
                    currentWeapon: WEAPON_TYPES.NORMAL,
                    particles: [],
                    lives: 3,  // 玩家生命值
                    invincible: false,  // 无敌状态
                    invincibleTimer: 0,   // 无敌时间
                    visible: true
                },
                bullets: [],
                enemies: [],
                stars: [],
                explosions: [],
                score: 0,
                lastEnemyTime: 0,
                enemySpawnRate: 2000,  // 敌机生成间隔从1秒增加到2秒
                gameOver: false,
                started: false
            };
            // 创建星空背景
            function createStars() {
                for (let i = 0; i < 200; i++) {
                    game.stars.push({
                        x: Math.random() * canvas.width,
                        y: Math.random() * canvas.height,
                        size: Math.random() * 3,
                        speed: 0.5 + Math.random() * 2,
                        alpha: Math.random()
                    });
                }
            }
            // 绘制星空
            function drawStars() {
                ctx.save();
                game.stars.forEach(star => {
                    star.y += star.speed;
                    if (star.y > canvas.height) {
                        star.y = 0;
                        star.x = Math.random() * canvas.width;
                    }
                    
                    const alpha = 0.5 + Math.sin(Date.now()  1000 + star.x) * 0.5;
                    ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
                    ctx.beginPath();
                    ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);
                    ctx.fill();
                });
                ctx.restore();
            }
            // 玩家飞机
            function drawPlayer() {
                // 无敌状态时不绘制
                if (game.player.invincible && !game.player.visible) {
                    return;
                }
                ctx.save();
                ctx.translate(game.player.x, game.player.y);
                
                // 机身
                ctx.fillStyle = '#0066ff';
                ctx.beginPath();
                ctx.moveTo(25, 0);
                ctx.lineTo(0, 40);
                ctx.lineTo(50, 40);
                ctx.closePath();
                ctx.fill();
                ctx.strokeStyle = '#00a2ff';
                ctx.lineWidth = 2;
                ctx.stroke();
                
                // 引擎火焰
                const flameSize = 5 + Math.sin(Date.now()  100) * 3;
                ctx.fillStyle = '#ff6600';
                ctx.fillRect(20, 40, 10, flameSize);
                
                // 驾驶舱
                ctx.fillStyle = '#00ccff';
                ctx.beginPath();
                ctx.arc(25, 15, 8, 0, Math.PI * 2);
                ctx.fill();
                
                ctx.restore();
                
                // 更新粒子
                updateParticles();
            }
            // 粒子系统
            function updateParticles() {
                // 添加新粒子
                if (Math.random() < 0.3) {
                    game.player.particles.push({
                        x: game.player.x + Math.random() * 50 - 25,
                        y: game.player.y + 40,
                        size: 3 + Math.random() * 4,
                        speedX: Math.random() * 2 - 1,
                        speedY: 1 + Math.random() * 2,
                        alpha: 1,
                        color: `hsl(${Math.random() * 30 + 20}, 100%, 50%)`
                    });
                }
                
                // 更新粒子
                ctx.save();
                game.player.particles.forEach((p, i) => {
                    p.x += p.speedX;
                    p.y += p.speedY;
                    p.alpha -= 0.02;
                    p.size *= 0.98;
                    
                    if (p.alpha <= 0) {
                        game.player.particles.splice(i, 1);
                    } else {
                        ctx.globalAlpha = p.alpha;
                        ctx.fillStyle = p.color;
                        ctx.beginPath();
                        ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
                        ctx.fill();
                    }
                });
                ctx.restore();
            }
            // 子弹
            function drawBullets() {
                ctx.save();
                game.bullets.forEach((bullet, i) => {
                    // 更新子弹位置
                    bullet.y -= bullet.type === 'LASER' ? 15 : 10;
                    
                    // 移除屏幕外的子弹
                    if (bullet.y < 0) {
                        game.bullets.splice(i, 1);
                    } else {
                        // 根据子弹类型绘制不同效果
                        if (bullet.type === 'NORMAL') {
                            const gradient = ctx.createLinearGradient(bullet.x, bullet.y, bullet.x, bullet.y + 20);
                            gradient.addColorStop(0, '#ffffff');
                            gradient.addColorStop(1, '#0066ff');
                            ctx.fillStyle = gradient;
                            ctx.fillRect(bullet.x - 2, bullet.y, 4, 20);
                            
                            // 子弹尾迹
                            ctx.fillStyle = 'rgba(0, 200, 255, 0.3)';
                            ctx.fillRect(bullet.x - 3, bullet.y + 10, 6, 30);
                        }
                        else if (bullet.type === 'SPREAD') {
                            ctx.fillStyle = '#ff9900';
                            ctx.beginPath();
                            ctx.arc(bullet.x, bullet.y, 3, 0, Math.PI * 2);
                            ctx.fill();
                            
                            // 散弹尾迹
                            ctx.fillStyle = 'rgba(255, 150, 0, 0.3)';
                            ctx.beginPath();
                            ctx.arc(bullet.x, bullet.y + 10, 5, 0, Math.PI * 2);
                            ctx.fill();
                        }
                        else if (bullet.type === 'LASER') {
                            // 激光光束
                            const gradient = ctx.createLinearGradient(bullet.x, bullet.y, bullet.x, bullet.y + 30);
                            gradient.addColorStop(0, '#ff00aa');
                            gradient.addColorStop(1, '#ffffff');
                            ctx.fillStyle = gradient;
                            ctx.fillRect(bullet.x - 5, bullet.y, 10, 30);
                            
                            // 激光光晕
                            ctx.fillStyle = 'rgba(255, 0, 170, 0.2)';
                            ctx.fillRect(bullet.x - 10, bullet.y, 20, 40);
                        }
                    }
                });
                ctx.restore();
            }
            // 敌机
            function drawEnemies() {
                const now = Date.now();
                if (now - game.lastEnemyTime > game.enemySpawnRate) {
                    game.lastEnemyTime = now;
                    
                    // 每5000分出现Boss
                    if (game.score > 0 && game.score % 5000 === 0) {
                        game.enemies.push({
                            ...ENEMY_TYPES.BOSS,
                            x: canvas.width / 2 - ENEMY_TYPES.BOSS.width / 2,
                            y: -ENEMY_TYPES.BOSS.height,
                            lastAttack: now
                        });
                    } else {
                        // 普通敌机
                        const type = Math.random() > 0.3 ? ENEMY_TYPES.NORMAL : ENEMY_TYPES.LARGE;
                        game.enemies.push({
                            ...type,
                            x: Math.random() * (canvas.width - type.width),
                            y: -type.height
                        });
                    }
                }
                
                ctx.save();
                game.enemies.forEach((enemy, i) => {
                    enemy.y += enemy.speed;
                    
                    // 移除屏幕外的敌机
                    if (enemy.y > canvas.height) {
                        game.enemies.splice(i, 1);
                    } else {
                        // 绘制敌机
                        ctx.fillStyle = enemy.color || '#ff3300';
                        
                        if (enemy.width === ENEMY_TYPES.BOSS.width) {
                            // Boss特殊绘制
                            ctx.beginPath();
                            ctx.arc(enemy.x + enemy.width/2, enemy.y + enemy.height/2, 
                                    enemy.width/2, 0, Math.PI * 2);
                            ctx.fill();
                            
                            // Boss光环效果
                            ctx.strokeStyle = 'rgba(255, 255, 0, 0.7)';
                            ctx.lineWidth = 3;
                            ctx.beginPath();
                            ctx.arc(enemy.x + enemy.width/2, enemy.y + enemy.height/2, 
                                    enemy.width/2 + 5 + Math.sin(now/200)*5, 0, Math.PI * 2);
                            ctx.stroke();
                        } else {
                            // 普通敌机绘制
                            ctx.beginPath();
                            ctx.moveTo(enemy.x + enemy.width/2, enemy.y);
                            ctx.lineTo(enemy.x, enemy.y + enemy.height);
                            ctx.lineTo(enemy.x + enemy.width, enemy.y + enemy.height);
                            ctx.closePath();
                            ctx.fill();
                        }
                        
                        // 敌机引擎效果
                        ctx.fillStyle = '#ff9900';
                        ctx.fillRect(enemy.x + enemy.width/2 - 5, enemy.y + enemy.height, 
                                    10, 5 + Math.sin(now  100) * 3);
                    }
                });
                ctx.restore();
            }
            // 爆炸效果
            function drawExplosions() {
                ctx.save();
                game.explosions.forEach((exp, i) => {
                    exp.particles.forEach(p => {
                        p.x += p.speedX;
                        p.y += p.speedY;
                        p.size *= 0.95;
                        p.alpha -= 0.02;
                        
                        if (p.alpha > 0) {
                            ctx.globalAlpha = p.alpha;
                            ctx.fillStyle = p.color;
                            ctx.beginPath();
                            ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
                            ctx.fill();
                        }
                    });
                    
                    // 移除消失的爆炸
                    if (exp.particles.every(p => p.alpha <= 0)) {
                        game.explosions.splice(i, 1);
                    }
                });
                ctx.restore();
            }
            // 创建爆炸
            function createExplosion(x, y) {
                const particles = [];
                for (let i = 0; i < 30; i++) {
                    const angle = Math.random() * Math.PI * 2;
                    const speed = 1 + Math.random() * 3;
                    particles.push({
                        x: x,
                        y: y,
                        speedX: Math.cos(angle) * speed,
                        speedY: Math.sin(angle) * speed,
                        size: 3 + Math.random() * 5,
                        alpha: 1,
                        color: `hsl(${Math.random() * 30 + 20}, 100%, 50%)`
                    });
                }
                game.explosions.push({ particles });
            }
            // 碰撞检测
            function checkCollisions() {
                const now = Date.now();
                // 子弹与敌机
                game.bullets.forEach((bullet, bIndex) => {
                    game.enemies.forEach((enemy, eIndex) => {
                        if (bullet.x > enemy.x && 
                            bullet.x < enemy.x + enemy.width &&
                            bullet.y > enemy.y && 
                            bullet.y < enemy.y + enemy.height) {
                            
                            enemy.health--;
                            game.bullets.splice(bIndex, 1);
                            
                            if (enemy.health <= 0) {
                                createExplosion(enemy.x + enemy.width/2, enemy.y + enemy.height/2);
                                game.enemies.splice(eIndex, 1);
                                game.score += enemy.score || 100;
                                scoreElement.textContent = `分数: ${game.score}`;
                            }
                            return;
                        }
                    });
                });
                
                // 玩家与敌机碰撞
                if (!game.player.invincible) {
                    game.enemies.forEach((enemy, eIndex) => {
                        if (game.player.x < enemy.x + enemy.width &&
                            game.player.x + game.player.width > enemy.x &&
                            game.player.y < enemy.y + enemy.height &&
                            game.player.y + game.player.height > enemy.y) {
                            
                            createExplosion(enemy.x + enemy.width/2, enemy.y + enemy.height/2);
                            game.enemies.splice(eIndex, 1);
                            hitPlayer();
                        }
                    });
                }
            }
            // 玩家被击中
            function hitPlayer() {
                const now = Date.now();
                
                // 只在非无敌状态下减少生命值
                if (!game.player.invincible) {
                    game.player.lives--;
                    updateLivesDisplay();
                    
                    if (game.player.lives <= 0) {
                        createExplosion(game.player.x + game.player.width/2, game.player.y + game.player.height/2);
                        game.gameOver = true;
                        game.started = false;
                        return;
                    }
                    
                    // 设置无敌状态
                    game.player.invincible = true;
                    game.player.invincibleTimer = now + 2000; // 2秒无敌时间
                    
                    // 闪烁效果
                    const blinkInterval = setInterval(() => {
                        game.player.visible = !game.player.visible;
                        if (Date.now() > game.player.invincibleTimer) {
                            clearInterval(blinkInterval);
                            game.player.invincible = false;
                            game.player.visible = true;
                        }
                    }, 100);
                }
            }
            // 更新生命值显示
            function updateLivesDisplay() {
                const livesElement = document.getElementById('lives');
                livesElement.textContent = '生命: ' + '❤️'.repeat(game.player.lives);
            }
            // 游戏结束画面
            function drawGameOver() {
                ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
                ctx.fillRect(0, 0, canvas.width, canvas.height);
                
                ctx.fillStyle = '#ff3300';
                ctx.font = '48px Arial';
                ctx.textAlign = 'center';
                ctx.fillText('游戏结束', canvas.width/2, canvas.height/2 - 40);
                
                ctx.fillStyle = '#ffffff';
                ctx.font = '36px Arial';
                ctx.fillText(`最终分数: ${game.score}`, canvas.width/2, canvas.height/2 + 20);
                
                ctx.fillStyle = '#00a2ff';
                ctx.font = '24px Arial';
                ctx.fillText('按R键重新开始', canvas.width/2, canvas.height/2 + 80);
            }
            // 重置游戏
            function resetGame() {
                game.player.x = canvas.width / 2;
                game.player.y = canvas.height - 100;
                game.player.lives = 3;
                game.player.invincible = false;
                game.player.invincibleTimer = 0;
                game.bullets = [];
                game.enemies = [];
                game.explosions = [];
                game.score = 0;
                game.lastEnemyTime = 0;
                game.gameOver = false;
                game.started = true;
                scoreElement.textContent = `分数: ${game.score}`;
                updateLivesDisplay();
                
                console.log('Game reset, starting loop...');
                if (!animationId) {
                    animationId = requestAnimationFrame(gameLoop);
                }
            }
            // 键盘控制
            const keys = {};
            window.addEventListener('keydown', e => {
                console.log('Key pressed:', e.key); // 调试输出
                
                // 开始游戏逻辑
                if (!game.started && !game.gameOver) {
                    console.log('Starting game...');
                    game.started = true;
                    resetGame();
                    return;
                }
                
                keys[e.key] = true;
                
                // 武器切换
                if (e.key === '1') game.player.currentWeapon = WEAPON_TYPES.NORMAL;
                if (e.key === '2') game.player.currentWeapon = WEAPON_TYPES.SPREAD;
                if (e.key === '3') game.player.currentWeapon = WEAPON_TYPES.LASER;
                
                // 射击
                if (e.key === ' ' && !game.player.isShooting && !game.gameOver) {
                    const now = Date.now();
                    if (now - game.player.lastShot > game.player.currentWeapon.delay) {
                        game.player.lastShot = now;
                        
                        const weapon = game.player.currentWeapon;
                        if (weapon === WEAPON_TYPES.NORMAL) {
                            game.bullets.push({
                                x: game.player.x + game.player.width/2 - weapon.width/2,
                                y: game.player.y,
                                type: 'NORMAL',
                                damage: weapon.damage
                            });
                        }
                        else if (weapon === WEAPON_TYPES.SPREAD) {
                            // 散弹发射5颗子弹
                            for (let i = 0; i < weapon.count; i++) {
                                game.bullets.push({
                                    x: game.player.x + game.player.width/2 - weapon.width/2 + (i-2)*10,
                                    y: game.player.y,
                                    type: 'SPREAD',
                                    damage: weapon.damage
                                });
                            }
                        }
                        else if (weapon === WEAPON_TYPES.LASER) {
                            game.bullets.push({
                                x: game.player.x + game.player.width/2 - weapon.width/2,
                                y: game.player.y,
                                type: 'LASER',
                                damage: weapon.damage
                            });
                        }
                    }
                }
                
                // 重新开始
                if (e.key === 'r' && game.gameOver) {
                    resetGame();
                }
            });
            window.addEventListener('keyup', e => {
                keys[e.key] = false;
            });
            // 创建初始星空
            createStars();
            // 游戏开始画面
            function drawStartScreen() {
                ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
                ctx.fillRect(0, 0, canvas.width, canvas.height);
                
                ctx.fillStyle = '#00a2ff';
                ctx.font = '48px Arial';
                ctx.textAlign = 'center';
                ctx.fillText('星空飞机大战', canvas.width/2, canvas.height/2 - 60);
                
                ctx.fillStyle = '#ffffff';
                ctx.font = '24px Arial';
                ctx.fillText('使用方向键移动,空格键射击', canvas.width/2, canvas.height/2);
                
                ctx.fillStyle = '#ff9900';
                ctx.font = '24px Arial';
                ctx.fillText('1-普通子弹 2-散弹 3-激光', canvas.width/2, canvas.height/2 + 40);
                
                ctx.fillStyle = '#00ffaa';
                ctx.font = '24px Arial';
                ctx.fillText('按任意键开始游戏', canvas.width/2, canvas.height/2 + 100);
            }
            // 游戏主循环
            let animationId;
            function gameLoop() {
                if (!game.started) {
                    drawStartScreen();
                    animationId = requestAnimationFrame(gameLoop);
                    return;
                }
                
                if (!game.gameOver) {
                    // 清屏
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    
                    // 绘制星空
                    drawStars();
                    
                    // 更新游戏状态
                    if (keys['ArrowLeft'] && game.player.x > 0) {
                        game.player.x -= game.player.speed;
                    }
                    if (keys['ArrowRight'] && game.player.x < canvas.width - game.player.width) {
                        game.player.x += game.player.speed;
                    }
                    if (keys['ArrowUp'] && game.player.y > 0) {
                        game.player.y -= game.player.speed;
                    }
                    if (keys['ArrowDown'] && game.player.y < canvas.height - game.player.height) {
                        game.player.y += game.player.speed;
                    }
                    
                    // 绘制游戏元素
                    drawPlayer();
                    drawBullets();
                    drawEnemies();
                    drawExplosions();
                    
                    // 碰撞检测
                    checkCollisions();
                    
                    // 更新武器状态显示
                    document.getElementById('weapon').textContent = 
                        `当前武器: ${game.player.currentWeapon.name} (1-普通 2-散弹 3-激光)`;
                } else {
                    drawGameOver();
                }
                
                requestAnimationFrame(gameLoop);
            }
            // 启动游戏
            gameLoop();
        </script>
    </body>
    </html>


    如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发朋友圈,

    可以到各大平台找我,
    • 微信公众号:@bisal的个人杂货铺
    • 腾讯云开发者社区:@bisal的个人杂货铺
    • 头条号:@bisal的个人杂货铺
    • CSDN:@bisal
    • ITPub:@bisal
    • 墨天轮:@bisal
    • 51CTO:@bisal
    • 小红书:@bisal
    • 抖音:@bisal
    近期更新的文章:
    《推荐北京21条骑行路线》
    《关于数据库索引的一些常识》
    《平均故障间隔时间(MTBF)的含义是什么?》
    《看个中国足球的管理规定》
    《世俱杯参赛名额的分配规则》
    热文鉴赏:
    《揭开"仿宋"和"仿宋_GB2312"的神秘面纱》
    《Linux的"aarch"是多了个"a"?》
    《中国队“自己的”世界杯》
    《你不知道的C罗-Siu庆祝动作》
    《大阪环球影城避坑指南和功略》
    《推荐一篇Oracle RAC Cache Fusion的经典论文》
    《"红警"游戏开源代码带给我们的震撼》
    文章分类和索引:
    《公众号1700篇文章分类和索引》

    文章转载自bisal的个人杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论