前端案例:飞机大战( js+dom 操作,代码完整,附图片素材)

news2025/1/24 2:17:54

目录

一、案例效果

二、实现思路

三、完整代码+详细注释

四、涉及要点

五、案例素材


一、案例效果

二、实现思路

  • 创建游戏背景板;
  • 创建我方战机,鼠标进入游戏面板后其随鼠标轨迹运动; onmousemove
  • 创建子弹,让子弹周期性的在战机处发出并让其向 top 值减小的方向(向上)移动,top 小于 0 也就是子弹走出游戏面板时删除自身;
  • 创建敌机,让敌机周期性的在游戏背景板左侧的随机距离的位置产生,并让其向 top 增加的方向(向下)移动;
  • 定义函数,子弹和敌机相遇时消失。

条件:所有的元素都只在鼠标进入游戏背景区域时才触发运动。

三、完整代码+详细注释

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>飞机大战</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    /* 背景 */
    #background {
      width: 320px;
      height: 580px;
      background-image: url(./img/bg.jpg);
      margin: auto;
    }

    /* 我方飞机 */
    #my_fly {
      width: 30px;
      height: 30px;
      position: absolute;
      cursor: pointer;
    }
  </style>
</head>

<body>
  <!-- 游戏面板 -->
  <div id="background"></div>
</body>
<script>
  //创建我方战机
  var fly = document.createElement('div'); //创建一个div
  fly.id = 'my_fly'; //为div添加id名
  fly.innerHTML = '<img src ="./img/my_fly.png" width=30px height=30px>'; //在div中插入飞机的图片
  document.body.appendChild(fly); //将刚创建的div追加到body中

  //使飞机鼠标跟随
  document.onmousemove = function (e) { //onmousemove 当鼠标移动时触发事件
    var fly = document.getElementById('my_fly'); //获取我方战机
    var bg = document.getElementById('background'); //获取背景
    var fly_X = e.clientX - 20; //获取鼠标的坐标 -20是减去飞机宽高的一半,以达到飞机中心与鼠标对应
    var fly_Y = e.clientY - 20;
    //游戏背景的区域
    var bgX = fly_X > bg.offsetLeft && fly_X < bg.offsetLeft + bg.offsetWidth - 30;
    var bgY = fly_Y > bg.offsetTop && fly_Y < bg.offsetTop + bg.offsetHeight - 30;
    if (bgX && bgY) { //只有在游戏背景区域内飞机才跟随鼠标移动
      fly.style.top = fly_Y + 'px'; //将鼠标此时的坐标赋值给我方飞机
      fly.style.left = fly_X + 'px';
      //此时飞机跟随鼠标移动,我们为该行为定义一个属性
      fly.follow = true; //今后follow为true则代表飞机可跟随鼠标移动,false则相反
    }
  }

  //创建子弹
  var objB = { //子弹相关变量
    name: 'bullet', //名称
    num: 1, //数量
    arr: [], //子弹的属性['id|top|left']
    width: 5, //子弹宽
    height: 10, //子弹高
    path: './img/bullet.png'
  }
  creatBullet(objB);

  function creatBullet(obj) {
    setInterval(function () {
      var fly = document.getElementById('my_fly');
      if (fly.follow) { //当飞机可跟随鼠标移动时可以发射子弹
        var bull = document.createElement('div'); //创建div元素作为子弹
        bull.id = obj.name + obj.num; //子弹的id名随创建数量不断变化(因为id值唯一)
        var length = obj.arr.length;
        if (length < 40) {
          obj.arr[length] = bull.id + '|';
          obj.num++;
          bull.style.width = obj.width + 'px'; //子弹的相关属性
          bull.style.height = obj.height + 'px';
          bull.style.position = 'absolute';
          bull.style.background = 'url(' + obj.path + ')';

          bull.style.top = parseInt(fly.style.top) + 'px'; //子弹发出的位置
          obj.arr[length] = obj.arr[length] + bull.style.top + '|';
          bull.style.left = parseInt(fly.style.left) + 12 + 'px';
          obj.arr[length] = obj.arr[length] + bull.style.left;
        }
        document.body.appendChild(bull); //将子弹添加到body
      }
    }, 700)
  }

  //让子弹运动起来
  function moveBullet() {
    var fly = document.getElementById('my_fly');
    if (fly.follow) {
      for (var i = 0; i < objB.arr.length; i++) { //遍历子弹的对象
        var newArr = objB.arr[i].split('|'); //将数组arr中的元素切割出来放入新数组
        var eleB = document.getElementById(newArr[0]);
        //切割后第0项为id 第一项为top 第二项为left  
        newArr[1] = parseInt(newArr[1]) - 1; //数组第一项为top,不断减1则子弹便会向上运动
        eleB.style.top = newArr[1] + 'px';
        objB.arr[i] = newArr[0] + '|' + newArr[1] + '|' + newArr[2];
        if (newArr[1] < 0) { //第一项为top,当top小于0 也就是子弹走出游戏面板时删除该子弹
          objB.arr.splice(i, 1);
          var delEle = document.getElementById(newArr[0]); //获取走出面板的子弹
          delEle.parentNode.removeChild(delEle); //删除自身
        }
      }
    }
  }


  //创建敌机(与创建子弹类似)
  var objF = { //敌机相关变量
    name: 'foe', //名称
    num: 1, //数量
    arr: [], //敌机的属性['id|top|left']
    width: 34, //敌机宽
    height: 24, //敌机高
    path: './img/he_fly.png'
  }
  creatFoe(objF);

  function creatFoe(obj) {
    setInterval(function () {
      var fly = document.getElementById('my_fly');
      var bg = document.getElementById('background'); //获取背景
      if (fly.follow) { //当飞机可跟随鼠标移动时出现敌机
        var bull = document.createElement('div'); //创建div元素作为敌机
        bull.id = obj.name + obj.num; //子弹的id名随创建数量不断变化(因为id值唯一)
        var length = obj.arr.length;
        if (length < 40) {
          obj.arr[length] = bull.id + '|';
          obj.num++;
          bull.style.width = obj.width + 'px';
          bull.style.height = obj.height + 'px';
          bull.style.position = 'absolute';
          bull.style.background = 'url(' + obj.path + ')';

          bull.style.top = 0; //敌机的顶部初始位置为0
          obj.arr[length] = obj.arr[length] + bull.style.top + '|';
          bull.style.left = bg.offsetLeft + 290 * Math.random() + 'px'; //敌机的左侧初始位置为随机
          obj.arr[length] = obj.arr[length] + bull.style.left;
        }
        document.body.appendChild(bull); //将敌机添加到body
      }
    }, 1000)
  }

  //让敌机运动起来
  function moveFoe() {
    var fly = document.getElementById('my_fly');
    var bg = document.getElementById('background'); //获取背景
    if (fly.follow) {
      for (var i = 0; i < objF.arr.length; i++) { //遍历敌机的对象
        var newArr = objF.arr[i].split('|'); //将数组arr中的元素切割出来放入新数组
        var eleB = document.getElementById(newArr[0]);
        //切割后第0项为id 第一项为top 第二项为left  
        newArr[1] = parseInt(newArr[1]) + 1; //数组第一项为top,不断加1则飞机便会向下运动
        eleB.style.top = newArr[1] + 'px';
        objF.arr[i] = newArr[0] + '|' + newArr[1] + '|' + newArr[2];
        if (newArr[1] > bg.offsetLeft - 30) {
          objF.arr.splice(i, 1);
          var delEle = document.getElementById(newArr[0]);
          delEle.parentNode.removeChild(delEle);
        }
      }
    }
  }

  //调用运动函数
  setInterval(function () {
    moveBullet(); //子弹运动
    moveFoe(); //敌机运动

    //子弹和敌机相遇时消失
    for (var i = 0; i < objF.arr.length; i++) {
      var newArr = objF.arr[i].split('|');
      var eleF = document.getElementById(newArr[0]);
      var xFS = parseInt(newArr[2]);
      var xFE = parseInt(newArr[2]) + 34;
      var yFS = parseInt(newArr[1]);
      var yFE = parseInt(newArr[1]) + 24;
      for (var j = 0; j < objB.arr.length; j++) {
        var newArr1 = objB.arr[j].split('|');
        var eleB = document.getElementById(newArr1[0]);
        var xB = parseInt(newArr1[2]);
        var yB = parseInt(newArr1[1]);
        var xCheck = xB > xFS && xB < xFE;
        var yCheck = yB > yFS && yB < yFE;

        if (xCheck && yCheck) {
          objF.arr.splice(i, 1);
          eleF.parentNode.removeChild(eleF);
          objB.arr.splice(j, 1);
          eleB.parentNode.removeChild(eleB);
        }
      }
    }
  }, 10)
</script>

</html>

四、涉及要点

鼠标进入游戏界面时触发元素运动

dom 事件 onmousemove 当指针在元素上方移动时,发生此事件。

创建战机、子弹

document.createElement(element)

创建 HTML 元素,可以 element.id、element.style、element.innerHTML 等为其设置相关属性;

//创建我方战机
var fly = document.createElement('div'); //创建一个div
fly.id = 'my_fly'; //为div添加id名

删除战机、子弹

document.removeChild(element)

删除 HTML 元素,可以结合父元素 parentNode 使用,如我们删除走出游戏面板的子弹,先找到子弹,再删除该子弹自身,其实就是删除该元素的父元素的子元素;

var delEle = document.getElementById(newArr[0]); //获取走出面板的子弹
delEle.parentNode.removeChild(delEle); //删除自身

将创建的 dom 元素追加到页面

document.appendChild(element)

添加 HTML 元素, 每一个创建完的 dom 元素都需要添加后才能显示,如我们将创建的我方战机添加到 body 中;

document.body.appendChild(fly); //将刚创建的div追加到body中

五、案例素材

背景 bg.jpg

己方飞机 my_fly.png

敌方飞机 he_fly.png

子弹 bullet.png

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

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

相关文章

Grafana alert预警+钉钉通知

1 Grafana alert预警 如下图所示&#xff0c;主要是前3步&#xff0c;设置alert rules、contact points 、notification policies。alert rules主要设置触发警告的规则&#xff1b;contact points设置通过什么发送预警&#xff0c;如钉钉&#xff1b;notification policies 将…

鼠标事件、键盘事件,你听过嘛?

&#x1f4dc;个人简介 ⭐️个人主页&#xff1a;微风洋洋&#x1f64b;‍♂️ &#x1f351;博客领域&#xff1a;编程基础,后端 &#x1f345;写作风格&#xff1a;干货,干货,还是tmd的干货 &#x1f338;精选专栏&#xff1a;【JavaScript】 &#x1f680;支持洋锅&#xff…

Chrome-谷歌浏览器多开教程

Chrome谷歌浏览器多开教程在我们的日常生活中&#xff0c;我们常常在某一时刻需要在进行多个账号的查看&#xff0c;例如在跨境电商时&#xff0c;我们常常需要开多各店铺页面&#xff0c;又或者&#xff0c;我们在玩游戏时&#xff0c;需要开多个账号同时进行运作&#xff0c;…

一文通透从输入URL到页面渲染的全过程----高频面试

一文通透从输入URL到页面渲染的全过程----高频面试 喜欢大海 喜欢夕阳 写下便是永恒 文章目录一文通透从输入URL到页面渲染的全过程----高频面试重温进程与线程什么是进程什么是线程进程和线程的区别多进程和多线程JS为什么是单线程浏览器相关浏览器是多进程的浏览器包含哪些进…

jeecg-boot首页加载速度优化全过程

优化结果 前端和后端部署在轻量服务器: 以下结果都是三次强刷得到的 优化前: 优化后: 优化方案 开启Nginx压缩 方案来自于:jeecg官方文档 作用:通过nginx内置的压缩策略来压缩静态资源&#xff0c;提升资源请求速度 在nginx.conf 的 http 中加入以下片断: # gzip …

【微信小程序 | 实战开发】常用的视图容器类组件介绍和使用(1)

个人名片: 🐼作者简介:一名大二在校生,喜欢编程🎋 🐻‍❄️个人主页🥇:小新爱学习. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️ 零基础学Java——小白入门必备重识C语言——复习回顾

component lists rendered with v-for should have explicit keys

component lists rendered with v-for should have explicit keys 发现问题 关键报错 (Emitted value instead of an instance of Error) : component lists rendered with v-for should have explicit keys. See https://vuejs.org/guide/list.html#key for more info. 具体…

VUE之Element-ui文件上传详解

引言 对于文件上传&#xff0c;在开发主要涉及到以下两个方面&#xff1a; 单个文件上传和表单一起实现上传&#xff08;这种情况一般都是文件上传之后&#xff0c;后端返回保存在服务器的文件名&#xff0c;最后和我们的表单一起上传&#xff09; 单文件上传 element-ui中…

Cesium加载离线地图和离线地形

文章目录 前言一、Cesium加载离线地图 1.1 下载数据2.2 数据处理2.3 地图发布2.4下载速度改进 二、Cesium加载离线地形 2.1 下载数据2.2 数据处理2.3 地形发布2.4 遇到的问题 前言 直接把地图数据切片&#xff0c;然后通过nginx以静态服务方式发布。 使用工具&#xff1a;…

this.$emit使用方法【前端技术】

this.$emit()主要用于子组件向父组件传值。 下面就给大家举一个实际开发中使用到的案例。 需求&#xff1a; 点击关联项目&#xff0c;弹出关联项目数据进行选择一条数据&#xff0c;点击确定&#xff0c;项目编号会回显到关联项目中。 1新增页面 2 新增页面中点击关联项目弹出…

vue3全局自定义指令实现按钮权限控制

1. 文档介绍的全局自定义指令 在Vue的模板语法中我们除了使用&#xff1a;v-show、v-for、v-model等&#xff0c;Vue其实 也允许我们来自定义自己的指令。 1&#xff09;注意&#xff0c;在 Vue 中&#xff0c;代码复用和抽象的主要形式是组件。 2&#xff09;然而&#xff0c…

HTML+CSS实现搜索框

HTMLCSS实现搜索框&#xff1a; 需求分析&#xff1a; 1、输入框焦点事件 onfocus:成为焦点, 点击输入框的时候&#xff0c;出现闪烁光标&#xff0c;此时可以输入内容。 onblur :失去焦点, 点击页面空白区域&#xff0c;光标消失。此时不可以输入内容。 2、获取元素 3、…

vite配置@别名,以及如何让vscode智能提示路经

vite配置别名 vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue// 配置别名import { resolve } from "path"; // https://vitejs.dev/config/ export default defineConfig({plugins: [vue()],// ↓解析配置resolve: {// ↓路…

HTML基础之form表单

目录 一&#xff1a;表单属性 1 name 属性 2 action属性 3 method属性 4 target属性 5 enctype属性 二&#xff1a;表单对象 1 input标签 2 多行文本textarea 3 下拉列表select 4 表单控件&#xff08;元素&#xff09;button 5 表单控件&#xff08;元素&#xff…

Vuex持久化插件(vuex-persistedstate)

为什么使用持久化 目的: 让在vuex中管理的状态数据同时储存在本地。可免去自己储存的环节。 在开发的过程中&#xff0c;像用户信息&#xff08;名字&#xff0c;头像&#xff0c;token&#xff09;需要vuex中储存且需要本地储存再例如&#xff0c;购物车如果需要未登录状态下…

Router-view

我们都知道&#xff0c;路由指的是组件和路径的一种映射关系。Router-view也被称为路由的出口,今天我们就探讨下如何去使用路由出口。 也就是: 路径--------------------------------------------------------------->页面 可以把router-view理解成一类代码存放的位置。 …

vue3项目中使用three.js

vue3项目中使用three.js前言一、three.js是什么&#xff1f;二、vue3中下载与安装three.js三、操作步骤1.创建场景2.创建物体3.添加光源4.添加相机5.开始渲染四、myThree.vue源代码五、效果图1.单个模型2.多个模型总结前言 在vue3项目中&#xff0c;通过three.js使用了一段短小…

java 课程设计——银行管理系统

银行管理系统&#xff08;java&#xff09; 环境&#xff1a; idea2020 jdk1.8 能实现的功能&#xff1a; 1.注册账户 2.登录 3.查询账户信息 4.存款 5.取款 6.向另一个账户转账 7.修改账户密码 8.注销账户 项目结构 项目演示 1.主页面&#xff1a; 2.注册账号&#xff1a;…

多行文本溢出显示省略号

文本溢出显示省略号分两种情况&#xff0c;单行文本溢出显示省略号&#xff08;参考上篇文章https://blog.csdn.net/qq_43687594/article/details/123511873&#xff09;&#xff0c;另外一种就是多行文本溢出显示省略号。 多行文本显示省略号有两种办法 第一种&#xff1a; …

解决Vue刷新后页面数据丢失的问题(sessionStorage和localStorage的用法)

一、为什么刷新后数据会丢失 vuex存储的数据只是在页面中&#xff0c;相当于全局变量&#xff0c;页面刷新的时候vuex里的数据会重新初始化&#xff0c;导致数据丢失。因为vuex里的数据是保存在运行内存中的&#xff0c;当页面刷新时&#xff0c;页面会重新加载vue实例&#xf…