【js小游戏案例】纯前端实现飞机大战,附带源码

news2024/9/28 6:54:35

技能:

使用html js css实现飞机大战小游戏

需求:

我军飞机左右移动,并且按空格 可以发射炮弹,敌方飞机从上往下飞,接触到我方炮弹 飞机被歼灭,我军接触到敌军飞机也将会被歼灭,我方飞机吃到道具可以增加弹道

思路:

初始化:初始创建我方飞机,用定时器定时创建敌方飞机,敌方飞机位置由random()随机生成

移动:飞机样式使用position: absolute,然后监听键盘被按事件 用left位置来移动我方飞机,敌军飞机也有定时器 定时向下移动

发射炮弹:创建炮弹跟创建敌军类似,区别是炮弹的位置是根据我方飞机的位置进行初始化的,而敌军飞机位置是随机的

敌军歼灭:通过getBoundingClientRect()获取位置信息 来判断是否接触到;我军歼灭类似

能量小球:产生小球跟敌军类似,休改下样式就好了

效果图:

 全部代码:

<!DOCTYPE html>
<html>

<head>
    <title>飞机大战</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
        }

        /* 游戏边框 */
        .game-board {
            width: 400px;
            height: 600px;
            border: 1px solid black;
            position: relative;
            overflow: hidden;
        }

        /* 我方飞机 */
        .player {
            width: 50px;
            height: 50px;
            background-color: blue;
            position: absolute;
            bottom: 0;
        }

        /* 敌方飞机 */
        .enemy {
            width: 30px;
            height: 30px;
            background-color: red;
            position: absolute;
            top: 0;
        }

        /* 子弹 */
        .bullet {
            width: 2px;
            height: 10px;
            background-color: black;
            position: absolute;
        }

        /* 分数 */
        .score {
            font-size: 18px;
            position: absolute;
            top: 10px;
            right: 10px;
        }

        /* 能量小球 */
        .power-up {
            width: 20px;
            height: 20px;
            background-color: green;
            position: absolute;
        }
    </style>
</head>

<body>
    <div class="game-board" id="game-board">
        <div class="score">分数: <span id="score">0</span></div>
    </div>

    <script>
        const gameBoard = document.getElementById('game-board');
        // 创建我方飞机
        const player = document.createElement('div');
        // 我军飞机初始位置
        let playerLeft = 175;
        player.style.left = `${playerLeft}px`;
        // 游戏是否结束
        let isGameOver = false;
        // 是否在发射子弹的状态
        let isShooting = false;
        // 初始化分数
        let score = 0;
        const scoreElement = document.getElementById('score');
        // 初始化我军飞机样式
        player.classList.add('player');
        gameBoard.appendChild(player);

        // 创造敌军飞机
        function createEnemy() {
            const enemy = document.createElement('div');
            // 随机位置
            let enemyLeft = Math.floor(Math.random() * 350);
            enemy.classList.add('enemy');
            enemy.style.left = `${enemyLeft}px`;
            gameBoard.appendChild(enemy);
            moveEnemy(enemy);
        }

        // 每30ms敌军就会向下移动五像素,如果到达边界就会取消移动 并且移除样式
        function moveEnemy(enemy) {
            let enemyTop = 0;
            let enemyInterval = setInterval(() => {
                if (enemyTop > 600 || isGameOver) {
                    clearInterval(enemyInterval);
                    // 出界 清除dom
                    gameBoard.removeChild(enemy);
                }

                enemy.style.top = `${enemyTop}px`;
                enemyTop += 5;

                // 如果两个接触到 就结束游戏
                if (checkCollision(player, enemy)) {
                    gameOver();
                }
            }, 30);
        }

        // 创建能量小球
        function createPowerUp() {
            const powerUp = document.createElement('div');
            // 随机水平位置
            let powerUpLeft = Math.floor(Math.random() * 350);
            powerUp.classList.add('power-up');
            powerUp.style.left = `${powerUpLeft}px`;
            gameBoard.appendChild(powerUp);

            movePowerUp(powerUp);
        }

        // 移动绿色小球
        // 每30ms绿色小球就会向下移动五像素,如果到达边界就会取消移动 并且移除样式
        function movePowerUp(powerUp) {
            let powerUpTop = 0;
            let powerUpInterval = setInterval(() => {
                if (powerUpTop > 600 || isGameOver) {
                    clearInterval(powerUpInterval);
                    // 出界 清除dom
                    gameBoard.removeChild(powerUp);
                }

                powerUp.style.top = `${powerUpTop}px`;
                powerUpTop += 5;

                // 我方飞机吃到绿色小球
                if (checkCollision(player, powerUp)) {
                    gameBoard.removeChild(powerUp);
                    powerUpEffect();
                }
            }, 30);
        }


        let isDoubleBullet = false;
        let numBullets = 1;

        // 新增函数,处理绿色小球效果
        function powerUpEffect() {
            isDoubleBullet = true;
            numBullets++;
        }

        // 创造子弹
        function createBullet(left, bottom) {
            // console.log(left, bottom)
            const bullet = document.createElement('div');
            bullet.classList.add('bullet');
            bullet.style.left = `${left + 25}px`;
            bullet.style.bottom = `50px`;
            gameBoard.appendChild(bullet);

            moveBullet(bullet);
        }
        // 子弹移动
        function moveBullet(bullet) {
            let bulletBottom = 50;
            let bulletInterval = setInterval(() => {
                if (bulletBottom > 600 || isGameOver) {
                    clearInterval(bulletInterval);
                    gameBoard.removeChild(bullet);
                }

                bullet.style.bottom = `${bulletBottom}px`;
                bulletBottom += 10;

                const enemies = document.querySelectorAll('.enemy');
                // 判断子弹是否接触到敌军飞机
                enemies.forEach(enemy => {
                    if (checkCollision(bullet, enemy)) {
                        clearInterval(bulletInterval);
                        gameBoard.removeChild(bullet);
                        gameBoard.removeChild(enemy);
                        increaseScore();
                    }
                });
            }, 30);
        }

        // 检测是否接触
        function checkCollision(a, b) {
            // getBoundingClientRect()是一个DOM元素对象的方法,用于获取该元素相对于视口(viewport)的位置和尺寸信息
            // 从而进行碰撞检测、位置计算等操作
            const aRect = a.getBoundingClientRect();
            const bRect = b.getBoundingClientRect();

            return !(
                // 我军飞机的top如果小于敌军的bottom 说明已经两机已经接触了
                aRect.top > bRect.bottom ||
                aRect.bottom < bRect.top ||
                aRect.right < bRect.left ||
                aRect.left > bRect.right
            );
        }

        // 游戏结束
        function gameOver() {
            isGameOver = true;
            // 移除gameBoard元素的所有子元素,即清空游戏面板
            while (gameBoard.firstChild) {
                gameBoard.removeChild(gameBoard.firstChild);
            }
            // 停止创造敌军飞机
            clearInterval(enemyInterval)
            gameBoard.innerHTML = '游戏结束!最终分数为: ' + score;
        }

        // 分数增加
        function increaseScore() {
            score++;
            scoreElement.textContent = score;

            if (score % 8 === 0) { // 每射杀十个敌方飞机,创建绿色小球
                createPowerUp();
            }
        }

        document.addEventListener('keydown', function (event) {
            // 空格键
            if (event.keyCode === 32 && !isGameOver) {
                // 发射与停止发射子弹
                if (!isShooting) {
                    isShooting = true;
                    shoot();
                }
            } else if (event.keyCode === 37) { // 左箭头键
                if (playerLeft > 0) playerLeft -= 10;
            } else if (event.keyCode === 39) { // 右箭头键
                if (playerLeft < 350) playerLeft += 10;
            }

            player.style.left = playerLeft + 'px';
        });

        // 控制发射子弹
        function shoot() {
            if (isShooting) {
                const plane = document.querySelector('.player');
                const planeLeft = parseInt(plane.style.left);
                const planeBottom = parseInt(plane.style.bottom);
                console.log(plane.style.left)

                // 增加子弹
                for (let i = 0; i < numBullets; i++) {
                    if (isDoubleBullet) {
                        createBullet(planeLeft - 5 + 10 * i , planeBottom);
                    } else {
                        createBullet(planeLeft, planeBottom);
                    }
                }
                // 设置发射子弹的频率,这里是每隔200毫秒发射一颗子弹
                setTimeout(shoot, 200);
            }
        }

        document.addEventListener('keyup', function (event) {
            if (event.keyCode === 32) { // 当松开空格键时,关闭发射状态
                isShooting = false;
            }
        });

        let enemyInterval = setInterval(createEnemy, 1000); // 每隔1秒创建一个敌方飞机
    </script>
</body>

</html>

有其他问题 欢迎大家评论留言

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/789714.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】vector类的模拟实现(增删查改,拷贝构造,赋值运算,深浅拷贝)

文章目录 前言一、 整体1.命名空间:2构造函数&#xff1a;1普通构造2迭代器构造3初始化字符构造4拷贝构造&#xff1a; 3析构函数 二、成员函数实现1.大小1当前大小(size())2总体容量(capacity()) 2.返回头尾迭代器1begin&#xff08;&#xff09;2end&#xff08;&#xff09;…

改进的北方苍鹰算法优化BP神经网络---回归+分类两种案例

今天采用前作者自行改进的一个算法---融合正余弦和折射反向学习的北方苍鹰(SCNGO)优化算法优化BP神经网络。 文章一次性讲解两种案例&#xff0c;回归与分类。回归案例中&#xff0c;作者选用了一个经典的股票数据。分类案例中&#xff0c;选用的是公用的UCI数据集。 BP神经网络…

达芬奇密码

《达芬奇密码》是一款由德国人发明的桌游&#xff0c;游戏由2-4个人组成。每个玩家执有一定的数字牌&#xff0c;玩家需隐藏你的数字密码&#xff0c;猜透对手的密码&#xff0c;推测可能的答案&#xff0c;打败对手。 24 块塑料立牌&#xff0c;12 个黑色和12个白色。每块上数…

7-25作业

思维导图 QT窗口代码 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {qDebug()<< this->size();this->resize(1000,800);//设置宽高this->setFixedSize(1000,800);//固定宽高//窗口标题this->setWindowTitle("跟党走…

全志F1C200S嵌入式驱动开发(lcd屏幕驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 lcd RGB屏幕作为比较经济、实用的显示工具,在实际场景中使用较多。它的信号来说,一般也比较简单,除了常规的数据信号,剩下来就是行同步、场同步、数据使能和时钟信号了。数据信…

LED芯片 VAS1260IB05E 带内部开关LED驱动器 汽车硬灯带灯条解决方案

VAS1260IB05E深力科LED芯片是一种连续模式电感降压转换器&#xff0c;设计用于从高于LED电压的电压源高效驱动单个或多个串联连接的LED。该设备在5V至60V之间的输入电源下工作&#xff0c;并提供高达1.2A的外部可调输出电流。包括输出开关和高侧输出电流感测电路&#xff0c;该…

【Linux】进程通信 — 管道

文章目录 &#x1f4d6; 前言1. 通信背景1.1 进程通信的目的&#xff1a;1.2 管道的引入&#xff1a; 2. 匿名管道2.1 匿名管道的原理&#xff1a;2.2 匿名管道的创建&#xff1a;2.3 父子进程通信&#xff1a;2.3.1 read()阻塞等待 2.4 父进程给子进程派发任务&#xff1a;2.5…

使用 OpenCV 进行图像模糊度检测(拉普拉斯方差方法)

写在前面 工作中遇到&#xff0c;简单整理人脸识别中&#xff0c;对于模糊程度较高的图像数据&#xff0c;识别率低&#xff0c;错误率高。虽然使用 AdaFace 模型&#xff0c;对低质量人脸表现尤为突出。但是还是需要对 模糊程度高的图像进行丢弃处理当前通过阈值分类&#xff…

8.python设计模式【组合模式】

内容&#xff1a;将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。角色&#xff1a; 抽象组建&#xff08;component&#xff09;叶子组建(Leaf)复合组建(Composite)客户端 (Client) UML 图 举个例子 需求&#xf…

Mysql-MHA高可用

MHA高可用配置及故障切换 一.MySQL MHA 1.什么是MHA &#xff08;&#xff11;&#xff09;MHA (Master High Availability) 是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 &#xff08;&#xff12;&#xff09;MHA的出现就是解决MySQL 单点的问题。 &#xff…

elementui el-table折叠表格,点击主表数据展开从表明细

用element-ui 的el-table实现&#xff1a;主表table可实现展开行显示关联的明细表table的列表数据&#xff0c;效果图如下 <el-tableref"tableData"v-loading"listLoading":data"tableData"row-key"id"borderstripehighlight-curr…

idea中设置maven本地仓库和自动下载依赖jar包

1.下载maven 地址&#xff1a;maven3.6.3 解压缩在D:\apache-maven-3.6.3-bin\apache-maven-3.6.3\目录下新建文件夹repository打开apache-maven-3.6.3-bin\apache-maven-3.6.3\conf文件中的settings.xml编辑&#xff1a;新增本地仓库路径 <localRepository>D:\apache-…

十二、数据结构——二叉树基本概念及特点

数据结构中的二叉树 目录 一、二叉树的基本概念 二、二叉树的特点 三、二叉树的分类 四、二叉树的存储结构 (一)、顺序存储 (二)、链式存储 一、二叉树的基本概念 二叉树是一种重要的数据结构&#xff0c;它是每个节点最多有两个子节点的树结构。在二叉树中&#xff0c;每个…

【源码解析】SpringBoot循环依赖源码解析II

前言 前面已经写过循环以来的分析&#xff0c;对循环依赖有一些了解&#xff0c;【源码解析】Spring循环依赖和三级缓存。简单回顾一下&#xff1a; Spring可以解决Autowired注入的循环依赖 Spring解决不了构造器注入的循环依赖 使用Aysnc注解会导致循环依赖。提前暴露的Bea…

Vue基础 --- 路由

1. 前端路由的概念与原理 1.1 什么是路由 路由&#xff08;英文&#xff1a;router&#xff09;就是对应关系。 1.2 SPA 与前端路由 SPA 指的是一个 web 网站只有唯一的一个 HTML 页面&#xff0c;所有组件的展示与切换都在这唯一的一个页面内完成。 此时&#xff0c;不同…

K8s卷存储详解(二)

K8s卷存储详解&#xff08;二&#xff09; 持久卷持久卷&#xff08;PV&#xff09;持久卷申领&#xff08;PVC&#xff09;存储类&#xff08;StorageClass&#xff09;存储制备器&#xff08;Provisioner&#xff09;PV和PVC的生命周期持久卷的类型CSI 卷快照CSI 卷克隆 投射…

《合成孔径雷达成像算法与实现》Figure2.14

%% 插值核 clc close all clear allN 40; x1 -4:1/N:4-1/N; hx sin(pi*x1)./(pi*x1); if x1 0hx 1; end figure plot(x1,hx,k) axis([-4 4,-0.4 1.2]) grid on arrow([-4,0],[4,0],Color,k,Linewidth,1); arrow([0,-0.4],[0,1.2],Color,k,Linewidth,1); %% 初始样本 x2 1…

第一章 函数的连续与间断与 无穷小量

文章目录 前言一、连续二、间断考点 识别间断点解题思路 三、无穷小量无穷小量的加减运算与比较无穷小的题型与解答 四、曲线的渐近线1、概念2、分类3、例题 前言 一、连续 二、间断 考点 识别间断点 解题思路 三、无穷小量 无穷小量的加减运算与比较 无穷小的题型与解答 四、曲…

高效协作处理缓存清理需求:生产者-消费者模式助力多模块缓存管理

在现代应用系统中&#xff0c;缓存是提高性能和减少数据库负载的重要手段之一。然而&#xff0c;缓存的数据在某些情况下可能会过期或者变得无效&#xff0c;因此需要及时进行清理。在复杂的应用系统中&#xff0c;可能有多个系统、多个模块产生缓存清理需求&#xff0c;而这些…

从实践彻底掌握MySQL的主从复制

目录 一、本次所用结构如图---一主多从级联&#xff1a; 二、IP。 三、配置M1&#xff1a; 四、从库M1S1&#xff1a; 五、从库M2配置&#xff1a; 六、 从库M2S1&#xff1a; 一、本次所用结构如图--- 一主多从级联&#xff1a; 二、IP。这里M1S1和M1S2一样的&#xff0…