js版飞机大战

2023-11-14

 <!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>飞机大战</title>
	<style>
		div
		{
			margin: 0 auto;
			text-align: center;
		}
	</style>
</head>
<body>
	<div>
		<canvas id="myCanvas" width="480" height="650"></canvas>
	</div>

	<script>
		//获取画布的对象和工具
		var cav = document.getElementById("myCanvas");
	    var cxt = cav.getContext("2d");

		//初始化数据
		//定义游戏的状态
		var START = 0;    //加载
		var STARTING = 1; //加载中
		var RUNNING = 2;  //游戏开始
		var PAUSE = 3;    //暂停
		var GAMEOVER = 4; //结束

		//开始加载状态
		var start = START;
		//设置宽高
		var WIDTH = 480;
		var HEIGHT = 650;
		//设置得分
		var score = 0;
		//设置玩家生命值
		var life = 3;

		//设置背景
		var bg = new Image();//创建背景对象
		bg.src = "img/background.png";
		//定义背景对象数据
		var Bg = {
			imgs: bg,
			width: 480,
			height: 850
		}

		//定义函数绘制背景
		//创建两张图片形成切换效果
		function BG(temp)
		{
			this.imgs = temp.imgs;
			this.width = temp.width;
			this.height = temp.height;
			//第一张图片位置
			this.x1 = 0;
			this.y1 = 0;
			//第二张图片位置
			this.x2 = 0;
			this.y2 = -this.height;
			//定义paint函数绘制背景图片
			this.paint = function()
			{
				cxt.drawImage(this.imgs,this.x1,this.y1);
				cxt.drawImage(this.imgs,this.x2,this.y2);
			}
			//定义step函数移动背景图片
			this.step = function()
			{
				this.y1++;
				this.y2++;
				//当第一张图片运动到最底下时,
				if (this.y1==this.height)
					//然后把第一张图片放在第二张图片的上面
					this.y1 = -this.height;
					//当第二张图片运动到最底下时,
				if (this.y2==this.height)
					//然后把第二张图片放在第一张图片的上面
					this.y2 = -this.height;
			}
		}

		//创建背景对象
		var sky = new BG(Bg);
		//绘制外层logo
		var logo = new Image();
		logo.src = "img/start.png";

		//游戏加载状态
		var loadings = [];//定义加载状态图片数组
		loadings[0] = new Image();
		loadings[0].src = "img/game_loading1.png";
		loadings[1] = new Image();
		loadings[1].src = "img/game_loading2.png";
		loadings[2] = new Image();
		loadings[2].src = "img/game_loading3.png";
		loadings[3] = new Image();
		loadings[3].src = "img/game_loading4.png";
		//定义对象存储图片数据
		var Loading = {
			img: loadings,
			length: loadings.length,
			width: 186,
			height: 38
		}
		//定义函数绘制加载状态的动画
		//当loading的索引长度达到最大时游戏开始
		function Load(temp)
		{
			this.img = temp.img;
			this.length = temp.length;
			this.width = temp.width;
			this.height = temp.height;
			this.index = 0; //定义数组索引
			//x,y为图片的位置
			this.x = 110;
			this.y = 400;
			//定义绘制图片的函数paint
			this.paint = function()
			{
				cxt.drawImage(this.img[this.index],this.x,this.y);
			}
			//定义图片移动函数
			this.cnt = 0;
			this.step = function()
			{
				//当程序运行3次时图片换一个
				this.cnt++;
				if (this.cnt%3==0)
					this.index++;
				if (this.index == this.length)
					start = RUNNING;//游戏开始标志
			}
		}

		//创建载入图片对象
		var loadImg = new Load(Loading);
		//给canvas绑定鼠标点击事件
		//点击画布时进入START状态
		cav.onclick = function()
		{
			if (start==START)
				start = STARTING;
		}

		//定义玩家对象状态数组
		var myPlane = [];
		//玩家飞机正常的状态
		//用两张图片使飞机呈现动态效果
		myPlane[0] = new Image;
		myPlane[0].src = "img/hero1.png";
		myPlane[1] = new Image;
		myPlane[1].src = "img/hero2.png";
		//飞机生命值为0时的状态
		myPlane[2] = new Image;
		myPlane[2].src = "img/hero_blowup_n1.png";
		myPlane[3] = new Image;
		myPlane[3].src = "img/hero_blowup_n2.png";
		myPlane[4] = new Image;
		myPlane[4].src = "img/hero_blowup_n3.png";
		myPlane[5] = new Image;
		myPlane[5].src = "img/hero_blowup_n4.png";

		//定义玩家飞机的数据对象
		var plane = {
			img: myPlane,
			length: myPlane.length,
			width: 99,
			height: 124,
			collider: 2 //玩家是否碰撞的状态
		}

		//创建玩家飞机函数
		function PLANE(my)
		{
			this.img = my.img;
			this.length = my.length;
			this.width = my.width;
			this.height = my.height;
			this.collider = my.collider;
			this.index = 0; //数组索引
			//飞机(图片)位置
			this.x = (WIDTH - this.width) / 2;
			this.y = HEIGHT - 150;
			this.dash = false; //飞机未碰撞
			//撞击函数
			this.bang = function()
			{
				this.dash = true;//飞机碰撞了
			}
			//paint绘制飞机
			this.paint = function()
			{
				cxt.drawImage(this.img[this.index],this.x,this.y);
			}
			//玩家飞机运动函数
			this.step = function()
			{
				//飞机未碰撞时在两张图片中来
				//回切换,形成动态效果
				if (this.dash==false)
				{
					this.index++;
					this.index = this.index % 2;
				}
				else
				{
					//飞机碰撞后加载碰撞后的图片
					this.index++;
					if (this.index==this.length)
					{
						//碰撞一次生命值减一
						life--;
						//s生命值为0时结束游戏
						if (life <= 0)
						{
							start = GAMEOVER;
							this.index = this.length - 1;
						}
						//生命值不为0重建玩家飞机对象
						else
						{
							player = new PLANE(plane);
						}
					}
				}
			}
			//定义自动射击的时间间隔
			this.cnt = 0;
			//玩家飞机射击控制函数
			this.shoot = function()
			{
				this.cnt++;
				if (this.cnt % 3==0)
				{
					//射出的子弹存在数组里
					bullett.push(new bulls(bull));
				}
			}
		}

		//设置玩家对象
		var player = new PLANE(plane);

		//设置飞机在画布上跟随鼠标移动
		cav.onmousemove = function(evevt)
		{
			var event = event || window.event;
			if (start==RUNNING)
			{
				//获取鼠标的位置
				var x = event.offsetX;
				var y = event.offsetY;
				//使玩家飞机中心跟随鼠标
				player.x = x - player.width / 2;
				player.y = y - player.height / 2;
			}
		}

		//绘制子弹

		var bu = new Image();
		bu.src = "img/bullet1.png";
		//初始化子弹数据
		var bull = {
			img: bu,
			width: 9,
			height: 21
		}

		//绘制子弹函数
		function bulls(zd)
		{
			this.img = zd.img;
			this.width = zd.width;
			this.height = zd.height;
			//子弹坐标
			this.x = player.x + player.width / 2 - this.width / 2;
			this.y = player.y - this.height - 10;
			//碰撞标志位
			this.candel = false;
			//绘制子弹
			this.paint = function()
			{
				cxt.drawImage(this.img,this.x,this.y);
			}
			//子弹移动函数
			this.step = function()
			{
				this.y -= 10;
			}
			//碰撞状态改变函数
			this.bang = function()
			{
				this.candel = true;
			}
		}

		//创建储存子弹对象的数组
		var bullett = [];
		//创建绘制所有子弹的函数
		function bullet_paint()
		{
			for (var i=0;i<bullett.length;i++)
			{
				bullett[i].paint();
			}
		}
		//创建子弹运动的函数
		function bullet_step()
		{
			for (var i=0;i<bullett.length;i++)
			{
				bullett[i].step();
			}
		}
		//清楚无用的子弹(碰撞和出界的)
		function bullet_vanish()
		{
			for (var i=0;i<bullett.length;i++)
			{
				//子弹的碰撞动画播放完,以及出界的清除掉
				if (bullett[i].candel==true || bullett[i].y<-bullett[i].height)
				{
					//splice删除i位置的若干元素
					bullett.splice(i,1);
				}
			}
		}

		//创建敌机
		var enermys = [];//低机图片数组
		enermys[0] = new Image();
		enermys[0].src = "img/enemy1.png";
		enermys[1] = new Image();
		enermys[1].src = "img/enemy1_down1.png";
		enermys[2] = new Image();
		enermys[2].src = "img/enemy1_down2.png";
		enermys[3] = new Image();
		enermys[3].src = "img/enemy1_down3.png";
		enermys[4] = new Image();
		enermys[4].src = "img/enemy1_down4.png";

		//敌机初始化数据
		var enermy = {
			img: enermys,
			length: enermys.length,
			width: 57,
			height: 51,
			life: 1,
			score: 1
		}

		function Enermy(dj)
		{
			this.img = dj.img;
			this.length = dj.length;
			this.width = dj.width;
			this.height = dj.height;
			this.life = dj.life;
			this.score = dj.score;
			//用随机数产生敌机出现的坐标
			this.x = Math.random() * (WIDTH - this.width);
			this.y = -this.height;
			this.dash = false;//撞击标志位
			this.cancel = false;//确定动画是否播放完
			this.index = 0;//敌机索引
			//绘制敌机
			this.paint = function()
			{
				cxt.drawImage(this.img[this.index],this.x,this.y);
			}

			//敌机运动函数
			this.step = function()
			{
				if (!this.dash)
				{
					//没碰撞时敌机状态不变一直是第一张图片
					this.index = 0;
					this.y += 10;
					if (this.y+this.height>HEIGHT)
					{
						//当敌机到达画布底部还没被击败,则游戏结束
						start = GAMEOVER;
					}
				}
				else
				{
					//加载碰撞后的动画
					this.index++;
					if (this.index == this.length)
					{
						this.cancel = true;//表示动画播放完
						this.index = this.length - 1;
					}
				}
			}
			//敌机撞击函数
			this.bang = function()
			{
				//碰撞后生命值减少
				this.life--;
				if (this.life<=0)
				{
					this.dash = true;
					score += this.score;
				}
			}
			//判断碰撞函数
			this.check_hit = function(obj)
			{
				return this.x<obj.x+obj.width && this.x+this.width>obj.x && this.y<obj.y+obj.height && this.y+this.height>obj.y
			}
		}

		//定义数组存储敌机
		var enermies = [];
		function enermy_create()
		{
			//使用随机数控制敌机产生数量
			var ran = Math.floor(Math.random()*100);
			if (ran<=7)
			{
				enermies.push(new Enermy(enermy));
			}
		}
		//绘制敌机
		function enermy_paint()
		{
			for (var i=0;i<enermies.length;i++)
			{
				enermies[i].paint();
			}
		}
		//敌机运动
		function enermy_step()
		{
			for (var i=0;i<enermies.length;i++)
			{
				enermies[i].step();
			}
		}
		//敌机毁灭并清除掉
		function enermy_dash()
		{
			for (var i=0;i<enermies.length;i++)
			{
				if (enermies[i].cancel || enermies[i].y>HEIGHT)
					enermies.splice(i,1);
			}
		}
		//碰撞处理函数
		function checkHit()
		{
			for (var i=0;i<enermies.length;i++)
			{
				//情况一:玩家飞机与敌机碰撞
				if (enermies[i].check_hit(player))
				{
					enermies[i].bang();
					player.bang();
				}
				//情况二:子弹与敌机相撞
				for (var j=0;j<bullett.length;j++)
				{
					if (enermies[i].check_hit(bullett[j]))
					{
						enermies[i].bang();
						bullett[j].bang();
					}
				}
			}
		}

		//定义暂停图片
		var pause = new Image();
		pause.src = "img/game_pause_nor.png";

		//鼠标离开画布时暂停
		cav.onmouseout = function()
		{
			if (start ==RUNNING)
				start = PAUSE;
		}

		//鼠标回到画布时继续
		cav.onmouseover = function()
		{
			if (start == PAUSE)
				start = RUNNING;
		}

		//在画布的左上角打印得分
		//在画布右上角打印玩家生命值
		function pain_information()
		{
			cxt.font = 'bold 24px 微软雅黑';
			cxt.fillText("SCORE:"+score,20,30);
			cxt.fillText("LIFE:"+life,380,30);
		}

		//游戏结束时打印gameover
		function paint_end_game()
		{
			cxt.font = "bold 36px 微软雅黑";
			cxt.fillText("GAMEOVER",150,300);
		}
		//定时器循环调用
		function main()
		{
			sky.paint();//绘制背景图
			sky.step();//背景图滚动
			//当游戏是开始状态时
			if (start == START)
			{
				cxt.drawImage(logo,40,0);//添加飞机大战字样的图片
			}
			//当游戏是载入状态时
			else if (start == STARTING)
			{
				loadImg.paint();//绘制加载图片
				loadImg.step();//加载图片运动
			}
			else if (start == RUNNING)
			{
				//玩家飞机状态
				player.paint();//绘制玩家飞机
				player.step();//玩家飞机运动
				player.shoot();//玩家飞机射击
				//射击子弹状态
				bullet_paint();//绘制子弹
				bullet_step();//子弹运动
				bullet_vanish();//子弹消失
				//敌人状态
				enermy_create();//敌机产生
				enermy_paint();//敌机绘制
				enermy_step();//敌机运动
				enermy_dash();//敌机毁灭
				checkHit();//判断敌机碰撞
				//打印玩家得分与生命值
				pain_information();
			}
			//暂停游戏时也要保存当前游戏的状态画面
			else if (start == PAUSE)
			{
				player.paint();
				bullet_paint();
				enermy_paint();
				cxt.drawImage(pause,200,300);
				pain_information();
			}
			//游戏结束状态
			else if (start == GAMEOVER)
			{
				pain_information();
				paint_end_game();
			}
		}
	    setInterval(main,60);
	</script>
</body>
</html>

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

js版飞机大战 的相关文章

随机推荐

  • Executors类中创建线程池的几种方法的分析

    Executors类中创建线程池的几种方法的分析 要配置一个线程池是比较复杂的 尤其是对于线程池的原理不是很清楚的情况下 很有可能配置的线程池不是较优的 因此在Executors类里面提供了一些静态工厂 生成一些常用的线程池 1 newFi
  • 2023备战金三银四,Python自动化软件测试面试宝典合集(五)

    接上篇 八 抓包与网络协议 8 1 抓包工具怎么用 我原来的公司对于抓包这块 在 App 的测试用得比较多 我们会使用 fiddler 抓取数据检查结果 定 位问题 测试安全 制造弱网环境 如 抓取数据通过查看请求数据 请求行 请求报头 请
  • HTML——label标签

    label标签 是什么 label标签是HTML中的一个标签 用于为表单元素 如文本框 复选框等 提供标签或说明文本 通常与input标签配合使用 label标签可以通过for属性与相应的表单元素建立联系 这样当用户点击标签时 相应的表单元
  • 三、Python基础(高级变量类型篇)

    三 Python基础 高级变量类型篇 目录 三 Python基础 高级变量类型篇 一 列表 list 1 列表的定义 2 列表的常用方法和操作 对象 方法名 参数 3 for in对列表迭代遍历 4 利用 for in 的输出技巧 5 se
  • CPU占用100%的一般原因及解决办法

    转自 微点阅读 https www weidianyuedu com content 2517683835639 html 电脑关机故障速解 经常出现cPU占用100 的情况 主要问题可能发生在下面的某些方面 cPU占用率高的九种可能 1
  • 有奖调研

    历经五载 FISCO BCOS开源联盟链生态圈已汇聚超过3000家机构与企业 7万多名个人成员 大家秉持共建共享的开源精神 一同建设出FISCO BCOS在技术 应用和生态上的累累硕果 在这片天地里 我们与志同道合的伙伴交流技术 也发现了区
  • 关于类,你真的掌握了吗?(详细代码解读以及详细图解)

    目录 一 类和对象 二 类和类的实例化 三 类的成员 四 封装 五 构造方法 六 代码块 今日良言 既然选择了远方 便只顾风雨兼程 一 类和对象 1 类 具有相同特性 属性 和行为的对象的抽象 类是一个模板 2 对象 对象是人们要进行研究的
  • 多元线性回归方差分析表理解

    1 单因素一元方差分析的方法和案例 例子 案例的代码 X 533 580 525 600 570 650 500 因数I A F 实验组 CK标准 565 600 500 615 575 661 510 525 575 510 590 56
  • 四个视角,讲透额温枪应用设计中的运放问题

    3 月 12 号 世界卫生组织宣布新冠肺炎为全球性流行病 抗疫正从中国的 人民战争 变成一场 世界大战 很多事情正在微妙和快速的变化 额温枪和口罩一样 成为抗疫以及复产复工必不可少的日常用品 额温枪成了市场上炙手可热的产品 很多厂家开始步入
  • Top n 开源物理仿真引擎

    物理仿真引擎可以做为强化学习用 也可以做游戏等 列举主要几个开源的 pybullet Webots 开源早的 用户也多 比如 pybullet提供Python API 学习曲线较平缓 Nvidia的isaac 新开源不久 GPU支持好 Mu
  • 微信能上但浏览器无法上网

    微信能上但浏览器无法上网 问题描述 微信能聊天传文件 但是浏览器一直显示 未链接到互联网 问题描述 网络诊断提示 远程计算机或设备将不接受链接 出现这类问题 一般都是电脑打开了SSR代理服务 关闭了代理服务基本上就可以恢复正常上网了 解决方
  • Unity的C#编程教程_47_函数和方法

    C Functions and Methods Overview 1 Functions vs Methods 函数和方法其实就是一个东西 在 C 中通常称之为方法 方法 就是一块打包的代码 比如我们最常见的 就是在 Unity 中初始化
  • Mac git 命令自动提示

    1 首先安装配置Homebrew 注 如果已经安装过就跳过 在终端输入如下命令 usr bin ruby e curl fsSL https raw githubusercontent com Homebrew install master
  • 【GitLab】docker部署个人代码私服(开源gitlab)

    文章目录 前期准备 安装部署 拉取Gitlab镜像文件 创建容器挂在卷轴目录 运行镜像 修改配置文件 重启容器 使用说明 初次登陆 更改语言模式 创建新用户 邮件转发服务 总结 前期准备 准备一台CentOS7 8 以上版本的服务器 标配2
  • 编程题目:求二叉树的叶子结点个数(涉及前中序遍历,建树,叶子节点个数)

    以二叉链表作为二叉树的存储结构 求二叉树的叶子结点个数 输入格式 输入二叉树的先序序列 提示 一棵二叉树的先序序列是一个字符串 若字符是 表示该二叉树是空树 否则该字符是相应结点的数据元素 输出格式 输出有两行 第一行是二叉树的中序遍历序列
  • 关注深度学习代码

  • 【DA 03】Exploring Categorical Regularization for Domain Adaptive Object Detection (CVPR 2020)

    摘要 解决目标检测的域自适应问题 其中主要是source和target域之间的巨大差异 前人的工作主要在对齐image level和Instance level shifts Bias 07 DA Faster RCNN 然而 他们忽略去了
  • NO.55——Face Swapping with Python,dlib,openCV(换脸)

    摘要 早前看过国外博主的一篇用200行代码实现图像换脸操作的文章 主要通过仿射变换和调色的方法 原理呢 晦涩难懂 具体效果呢 其实也并不是很理想 至少要比直接调用Face 的人脸融合接口要差很多 用于学习图像处理相关的知识还是不错的 下一篇
  • IoT Studio场景最佳实践——实践类

    1 使用IoT Studio快速构建可视化应用 在物联网业务场景中设备数据可视化应用是最普遍的需求 阿里云物联网应用开发 IoT Studio 提供了Web可视化开发 移动可视化开发 业务逻辑开发与物联网数据分析等一系列便捷的物联网开发工具
  • js版飞机大战

    div div