先看看效果图

github地址:https://github.com/dong432/plane

​​​​​​​1、首先准备好需要的素材,己方飞机、敌方飞机、爆炸效果(可以自行寻找素材,一下是该项目所用素材)

             

2、创建好父类-plane.js,(好像没啥用,就保存dom和一些属性)

class plane {constructor(options) {this.dom = options.dom;for (let key in options) {this[key] = options[key];}}
}

3、创建己方飞机类-mine.js

继承父类plane,给定己方飞机高度宽度和位置,然后给己方飞机绑定拖拽事件

class mine extends plane {constructor (options) {super({name: 'mine',left: 0,top: 0,...options,dom: document.createElement('div')})this.dom.className = 'mine'// 设置飞机在屏幕下方中间this.left = bodyWidth / 2 - this.width / 2;this.top = bodyHeight - 100;// 把飞机放到body里面document.body.appendChild(this.dom)// 绑定拖拽事件this.draggable()}// 让元素可拖拽draggable() {this.dom.onmousedown = (e) => {let left = e.clientX - this.dom.offsetLeft;let top = e.clientY - this.dom.offsetTop;document.onmousemove = ({ clientX, clientY }) => {this.left =clientX - left < 0 - this.width / 2? -this.width / 2: clientX - left > bodyWidth - this.width / 2? this.left: clientX - left;this.top =clientY - top < 0? 0: clientY - top > bodyHeight - this.height? this.top: clientY - top;render(this)};document.onmouseup = (e) => {document.onmousemove = null;this.dom.onmouseup = null;};};}
}

4、创建子弹类-bullet.js

子弹为敌人和英雄共用类,所以设置了子弹方向(direction),速度(speed),颜色(color),

给子弹实例一个定时器,让它不停向下或向上移动,当子弹超出屏幕时,删除子弹实例,移除dom元素

class bullet extends plane {constructor(options) {super({...options,name: 'enemy',dom: document.createElement('div')})this.dom.style.backgroundColor = options.color || "#000";this.dom.className = 'bullet';// 子弹显示停留做个透明度过渡衔接this.dom.style.opacity = 0;document.body.appendChild(this.dom);this.upgo()}upgo() {let clock = setInterval(() => {if (this.direction == 'up') this.top -= this.speed;else if (this.direction == 'down') this.top += this.speed;else {clearInterval(clock)console.warn('请设置子弹方向')}this.dom.style.opacity = 1;if (this.top <= -this.height && this.direction == 'up') {bulletObj[this.index] = null;delete bulletObj[this.index]clearInterval(clock)return this.dom.remove()} else if (this.top >= bodyHeight && this.direction == 'down') {enemyBulletObj[this.index] = null;delete enemyBulletObj[this.index]clearInterval(clock)return this.dom.remove()}}, 100);this.moveClock = clock}
}

5、创建敌机类-enemy.js

创建一个敌机,left 为屏幕宽度随机位置,top 为负的敌机高度,然后给敌机创建子弹,速度应快于敌机下降速度,当敌机超出屏幕,删除敌机实例,移除dom元素

class enemy extends plane {constructor(options) {super({...options,top: -options.height,left: Math.floor(Math.random() * bodyWidth),name: 'enemy',dom: document.createElement('div')})this.dom.className = "enemy"document.body.appendChild(this.dom)this.down()this.createBullet()}// 向下坠down() {let clock = setInterval(() => {this.top += this.speedif (this.top >= bodyHeight) {clearInterval(clock)clearInterval(this.enemyBulletClock)enemyObj[this.index] = nulldelete enemyObj[this.index]return this.dom.remove()}}, 100);this.moveClock = clock}// 创建子弹createBullet() {let enemyBulletClock = setInterval(() => {enemyBulletKey++;const width = 10, height = 20let enemyBullet = new bullet({speed: this.speed + 30,width,height,direction: 'down',left: this.left + this.width / 2 - width / 2,top: this.top + this.height,index: enemyBulletKey})enemyBulletObj[enemyBulletKey] = enemyBullet}, 500);this.enemyBulletClock = enemyBulletClock}
}

6、创建游戏结束类-gameover.js

游戏结束,创建一个弹窗在屏幕正中间,显示分数和评语,以及重新开始按钮

class gameover extends plane{constructor(options) {super({...options,dom: document.createElement('div')})this.draggable()this.dom.className = 'gameover'let title = document.createElement('div')title.className = 'title'title.innerText = '游戏结束'this.dom.appendChild(title)let scoreDom = document.createElement('div')scoreDom.className = 'score'scoreDom.innerText = '分数:' + scorethis.dom.appendChild(scoreDom)let time = document.createElement('div')time.className = 'time'time.innerText = score > 200 ? '超神' : score > 120 ? '666' : score > 50 ? '太棒啦' : '继续努力'this.dom.appendChild(time)let btn = document.createElement('button')btn.className = 'resetGame'btn.innerText = '重新开始'btn.onclick = () => {location.reload()}this.dom.appendChild(btn)document.body.appendChild(this.dom)}
}

7、创建html文件-index.html

创建维护己方子弹对象

创建维护敌机对象

创建维护敌方子弹对象

用于监听他们之间的碰撞情况,用一个自增key作为他们的属性

changeCoordinate-更新dom,并监听是否发生碰撞

render-执行各个元素位置更新

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>飞机大战</title><link rel="stylesheet" href="./index.css" /></head><body><div class="scores">得分:0</div><button class="begin">开始游戏</button><script>// 创建维护敌机的对象let enemyObj = {};// 创建维护子弹的对象let bulletObj = {};// 创建维护敌人子弹的对象let enemyBulletObj = {};// 创建敌人子弹自增keylet enemyBulletKey = 0;// 创建子弹自增keylet bulletKey = 0;// 创建敌机自增keylet enemyKey = 0;// 游戏是否结束let over = false;// 分数let score = 0;// 屏幕宽高let bodyWidth =document.compatMode == "BackCompat"? document.body.clientWidth: document.documentElement.clientWidth;let bodyHeight =document.compatMode == "BackCompat"? document.body.clientHeight: document.documentElement.clientHeight;// 更新dom,监听是否碰撞function changeCoordinate() {if (over) return;if (mineExample) {this.render(mineExample);}for (let key in bulletObj) {this.render(bulletObj[key]);}for (let key in enemyObj) {this.render(enemyObj[key]);}for (let key in enemyBulletObj) {this.render(enemyBulletObj[key]);}let l3 = mineExample.dom.offsetLeft;let t3 = mineExample.dom.offsetTop;let r3 = l3 + mineExample.dom.offsetWidth;let b3 = t3 + mineExample.dom.offsetHeight;for (let bulletKey in bulletObj) {const bulletDom = bulletObj[bulletKey].dom;for (let enemyKey in enemyObj) {const enemyDom = enemyObj[enemyKey].dom;let l1 = bulletDom.offsetLeft;let t1 = bulletDom.offsetTop;let r1 = l1 + bulletDom.offsetWidth;let b1 = t1 + bulletDom.offsetHeight;let l2 = enemyDom.offsetLeft;let t2 = enemyDom.offsetTop;let r2 = l2 + enemyDom.offsetWidth;let b2 = t2 + enemyDom.offsetHeight;if (r1 > l2 && l1 < r2 && b1 > t2 && t1 < b2 && !enemyDom.bao) {enemyDom.bao = true;enemyDom.style.backgroundImage = `url(./bao.gif?time=${Math.random()})`;bulletObj[bulletKey] = null;delete bulletObj[bulletKey];// 敌机毁灭,停止发射子弹clearInterval(enemyObj[enemyKey].enemyBulletClock);clearInterval(enemyObj[enemyKey].moveClock);bulletDom.remove();score++;scoreDom.innerHTML = "得分:" + score;setTimeout(() => {enemyObj[enemyKey] = null;delete enemyObj[enemyKey];enemyDom.remove();}, 800);}if (r2 > l3 && l2 < r3 && b2 > t3 && t2 < b3 && !enemyDom.bao) {return this.gameOver();}}}for (let key in enemyBulletObj) {const enemyBulletDom = enemyBulletObj[key].dom;let l2 = enemyBulletDom.offsetLeft;let t2 = enemyBulletDom.offsetTop;let r2 = l2 + enemyBulletDom.offsetWidth;let b2 = t2 + enemyBulletDom.offsetHeight;if (r2 > l3 && l2 < r3 && b2 > t3 && t2 < b3) {return this.gameOver();}}}function render(temp) {if (over) return;temp.dom.style.width = temp.width + "px";temp.dom.style.height = temp.height + "px";temp.dom.style.left = temp.left + "px";temp.dom.style.top = temp.top + "px";}// 游戏结束function gameOver() {over = true;const width = 400,height = 400;new gameover({width,height,left: bodyWidth / 2 - width / 2,top: bodyHeight / 2 - height / 2,});for (let key in enemyObj) {const item = enemyObj[key];clearInterval(item.enemyBulletClock);clearInterval(item.clock);clearInterval(item.moveClock);}for (let key in bulletObj) {const item = bulletObj[key];clearInterval(item.clock);clearInterval(item.moveClock);}for (let key in enemyBulletObj) {const item = enemyBulletObj[key];clearInterval(item.moveClock);}mineExample.dom.onmousedown = null;}const begin = document.querySelector(".begin");let scoreDom = null;let mineExample = null;// 子弹发射频率 - 100毫秒const launch = 100;begin.onclick = () => {begin.style.display = "none";// 获取分数dom对象scoreDom = document.querySelector(".scores");// 创建自己/*width: number - 自己宽度height: number - 自己高度*/mineExample = new mine({width: 52,height: 26,});// 循环创建自己的子弹let bulletClock = setInterval(() => {bulletKey++;/*speed: number - 子弹速度direction: up | down - 子弹方向left: number - 坐标xtop: number - 坐标ywidth: number - 子弹宽度height: number - 子弹高度color: string - 子弹颜色*/// 生成随机颜色const getRandomColor = () => {let color = "#";const str = "abcdef1234567890";const strL = str.length;for (let i = 0; i < 6; i++) {color += str[Math.floor(Math.random() * strL)];}return color;};const width = 4,height = 10;let biu = new bullet({speed: 60,direction: "up",left: mineExample.left + mineExample.width / 2 - width / 2,top: mineExample.top,width,height,color: getRandomColor(),index: bulletKey,clock: bulletClock,});bulletObj[bulletKey] = biu;}, launch);const createEnemyTime = 100;// 循环生成敌人let enemyClock = setInterval(() => {enemyKey++;/*speed: number - 敌机速度width: number - 敌机宽度height: number - 敌机高度*/let di = new enemy({width: 50,height: 50,speed: 20,index: enemyKey,clock: enemyClock,});enemyObj[enemyKey] = di;}, createEnemyTime);setInterval(() => {changeCoordinate();}, 20);};</script><script src="./plane.js"></script><script src="./gameover.js"></script><script src="./mine.js"></script><script src="./bullet.js"></script><script src="./enemy.js"></script></body>
</html>

8、最后加上样式-index.css

* { margin: 0; padding: 0; user-select: none; }
body {width: 100vw;height: 100vh;overflow: hidden;
}
.mine {cursor: pointer;position: absolute;background-color: transparent;background-image: url(./mine.png);background-repeat: no-repeat;background-size: cover;background-position: center center;border-radius: 3px;
}
.bullet {position: absolute;border-radius: 3px;transition: all .1s linear 0s;
}
.enemy {cursor: pointer;position: absolute;background-color: transparent;background-image: url(./enemy.png);background-repeat: no-repeat;background-size: cover;background-position: center center;border-radius: 3px;transition: all .1s linear 0s;
}
.gameover {position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);z-index: 1;width: 400px;height: 400px;background-color: #eee;border-radius: 20px;overflow: hidden;box-shadow: 0 0 5px 5px #999;text-align: center;
}
.gameover .title {background-color: brown;line-height: 50px;color: #fff;font-size: 20px;font-weight: bold;
}
.gameover .score {font-size: 60px;color: #0000ae;font-family: monospace;margin-top: 30px;
}
.gameover .time {margin-top: 40px;font-size: 30px;
}
.gameover .resetGame {width: 50%;height: 40px;margin-top: 80px;cursor: pointer;background-color: #ffa500;border: none;border-radius: 10px;font-size: 18px;color: #fff;box-shadow: 0 0 5px #787878;
}
.gameover .resetGame:active {background-color: #ffb938;
}
.scores {position: fixed;top: 20px;left: 50%;transform: translateX(-50%);font-size: 30px;font-weight: bold;color: #0000ae;
}
.begin {position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);background-color: #ffa500;color: #fff;border-radius: 10px;border: none;width: 200px;height: 40px;font-size: 20px;box-shadow: 0 0 5px #787878;
}
.begin:active {background-color: #ffb938;
}

js版本飞机大战(完整代码)相关推荐

  1. python制作飞机大战代码_python实现飞机大战完整代码,可运行

    我发现很多python代码飞机大战在互联网上,但几乎没有一个是完整的.所以我做了一个完整的人.python代码分为两个文件,工具类和主类.python版本,pygame模块需要安装.完整的代码如下.1 ...

  2. 雷霆战机9.5全新上线,Python+Pygame开发飞机大战完整游戏项目(附源码)

    项目名称:太空大战 开发环境:Python3.6.4 第三方库:Pygame1.9.6 代码编辑器:Sublime Text 先来看一下游戏画面吧!  游戏画面动态且丰富哦!   需求分析 利用Pyt ...

  3. Python3飞机大战全代码(亲测OJBK)

    以下是亲测Python飞机大战全部代码,在保证有pygame环境支持并且有Python3解释器的话完全没问题! 如果大家喜欢的话麻烦点个赞! 当然没有图片的可以给小编评论留下自己的qq号并且点个赞,晚 ...

  4. Java版本飞机大战

    1.关于这个飞机大战 学Java有一段时间了,然后通过Java开发了一些简易安卓APP.最近很想实现以前自己很想写的飞机大战,也练练手.代码和界面参考(抄袭 )了许多,毕竟天下码农一家亲. 游戏大概长 ...

  5. python飞机大战游戏代码_python实现飞机大战游戏

    飞机大战(Python)代码分为两个python文件,工具类和主类,需要安装pygame模块,能完美运行(网上好多不完整的,调试得心累.实现出来,成就感还是满满的),如图所示: 完整代码如下: 1.工 ...

  6. Html+Css+Js五星好评(完整代码+详解)

    一,问题描述 当鼠标滑过空白的五颗星星时,有预览的颜色填充,当点击鼠标后,颜色填充确定,确定的颜色是绿色,当鼠标预览时,依然有预览色,没有点击鼠标确定时,颜色依然是,上一次的记录,点击了则是当次的好评 ...

  7. Python pycharm环境 飞机大战游戏代码 以及打包成exe教程

    创建项目文件plane war,在项目文件里放入写游戏脚本需要用到的图片文件images以及新建一个新的文件plane放入py文件(main.py和sprites.py) images文件压缩包链接: ...

  8. js实现飞机大战小游戏

    用JavaScript来实现一个鼠标指针控制的飞机大战小程序,效果图如下. 1.进入页面阶段 2.第二载入阶段效果图 3.第三核心阶段 4.第四暂停阶段 5.第五结束阶段 实现这个项目的HTML代码只 ...

  9. 飞机大战java代码_[源码和文档分享]Java飞机大战游戏设计与实现

    1 概述 1.1 项目简介 本次Java课程设计是做一个飞机大战的游戏,应用Swing编程,完成一个界面简洁流畅.游戏方式简单,玩起来易于上手的桌面游戏.该飞机大战项目运用的主要技术即是Swing编程 ...

  10. JS实现京东倒计时(完整代码)

    JS实现京东秒杀倒计时(完整代码) 一.获取图片 二.css实现外观 这里比较简单,就不细说了 三.JS实现倒计时 基本思路: 1.首先使用Date()对象获取当前时间(时间戳) 2.传递参数获取活动 ...

最新文章

  1. 比尔.盖茨11点忠告
  2. 架构师之路 — 分布式系统 — gRPC 谷歌远程过程调用
  3. 在VS2005中 GridView导入Excel的两点小技巧-附源码
  4. DUILib 中的通知事件
  5. mysql为什么使用B+树
  6. 重物码垛搬运机器人_搬运码垛机器人的特点及应用
  7. Tempter of the Bone(HDU1010)
  8. java判断实例_java判断类和实例的关系
  9. PWN-PRACTICE-BUUCTF-23
  10. 2021年中国电竞运动行业发展报告
  11. matlab求逆矩阵_MPU6050姿态解算2-欧拉角amp;旋转矩阵
  12. 创建了一个表之后怎么再次在表中添加字段和字段显示位置_筛选数据透视表中的数据...
  13. winform调用websocket_C#基于websocket的前台及后台实时推送
  14. 报告一个IE很奇葩的滚动条问题——百分比计算宽度为浮点数时的滚动条显示异常
  15. 通过maven安装spire.pdf
  16. 工序能力指数Cp判定标准(附免费CPK计算工具)
  17. Win10蓝牙耳机连接成功但耳机没声音解决方案
  18. linux mbr gpt 区别,MBR、GPT的结构和区别
  19. 在网页右下角添加一个卡通动漫人物
  20. 触摸按键(电容式按键)

热门文章

  1. O2O新猜想:如果商家这样做,还需要团购平台吗
  2. Java和C专项练习
  3. 华为服务器管理口在哪个位置,华为服务器默认管理口地址吗
  4. 【UVM基础】3、核心基类和机制
  5. 论文笔记:Auto-Encoding Scene Graphs for Image Captioning
  6. java图书商城项目_JavaWeb网上图书商城完整项目--23.注册页面之html实现
  7. GOlang中对flag.Prase()的疑问
  8. PCB 板弯了怎么办?pcb板弯翘原因分析及改善方法
  9. 今日恐慌与贪婪指数为15 恐慌程度较昨日持续下降
  10. 九种常见的数据分析模型