JavaScript打飞机小游戏

又到了每日分享时间了,今天分享的内容为:JavaScript打飞机小游戏
效果图:
js打飞机游戏
实现逻辑:
第一步:实现页面的排版、布局
1.1 准备打飞机游戏需要使用到的图片
1.2 开始游戏界面
1.3 进入游戏的界面
1.3.1 己方飞机
1.3.2 敌方飞机
1.3.3 己方飞机发射的子弹
第二步:开始游戏
2.1 点击开始游戏按钮,进入到游戏界面
2.2 摁下空格键,实现己方飞机跟随鼠标的移动==》游戏的开始
2.3 第二次摁下空格键时,实现己方飞机的暂停移动==》游戏的暂停
2.4 以此类推,实现开始和暂停的交换
第三步:开始游戏之后的发射子弹
3.1 定时创建子弹:
3.1.1 单位时间内创建子弹的数量
3.1.2 开始游戏和暂停游戏时:暂停游戏后,不能再创建子弹;再次开始游戏时,不能存在多个创建子弹的定时器==》把上一次创建子弹的定时器给清除或者不再开启定时器
3.2 制造子弹
3.2.1 制造子弹时,确定子弹的位置
3.2.2 根据当前己方飞机的位置
3.2.3 把子弹追加到文档中去
3.3 子弹的运动
3.3.1 子弹的top值是-子弹的高度时,删除子弹,清除定时器
3.4 子弹消失
3.4.1 子弹飞出游戏界面
3.4.2 清除子弹==》每一颗飞出到游戏界面之外的子弹,肯定是第一个创建的子弹(当前子弹所在父元素下的第一个子元素)
第四步:开始游戏之后的创建敌机
4.1 定时创建敌机
4.1.1 单位时间内创建敌机的数量
4.1.2 暂停之后不能重复性的开启创建敌机的定时器
4.1.3 敌机的概率出现:大、中、小三种敌机
===》小:75% 中:20% 大:5%
4.2 制造敌机
4.3 敌机的运动
4.4 敌机的消失
第五步:实现游戏的暂停
5.1 敌机运动速度的控制
5.2 实现游戏的暂停
5.2.1 清除己方飞机的移动
5.2.2 清除创建敌机
5.2.3 清除创建子弹
5.2.4 清除每颗子弹上的运动
5.2.5 清除每架敌机上的运动
第六步:实现开始游戏之后的背景图的运动
6.1 改变的是背景图的background-position-y的值
6.2 游戏界面的高度568,每运动568px是一个循环
第七步:检测子弹和敌机的碰撞
7.1 每一个敌机都是运动的,每一颗子弹也是运动的==》在每一架敌机运动时,检测和所有游戏界面内存在的子弹的碰撞
7.2 创建全局变量:把当前游戏界面内存在的所有的子弹放入到该变量里
7.3 敌机运动的过程中,检测和每一颗子弹的碰撞
7.4 子弹和敌机发生碰撞时,子弹消失
7.4.1 把该子弹元素删除掉
7.4.2 把该子弹元素从全局变量集合里删除
7.5 敌机和子弹发生碰撞时,敌机血量减少==》每一颗子弹消耗的血量100
7.6 敌机的血量为0时,删除敌机元素???
第八步:实现敌机的爆炸效果
8.1 替换爆炸图片
8.2 区分存活的敌机和死亡敌机(爆炸过程中的敌机)==》标记每一架敌机的存活状态
8.3 延时删除敌机元素==》显示爆炸效果
8.4 在创建敌机时,删除敌机集合中的死亡敌机
第九步:实现游戏的得分
第十步:检测己方飞机和敌机的碰撞
10.1 一对多的关系:敌机运动,己方飞机运动
10.2 在每一架敌机运动的过程中检测
10.3 碰撞的原理
第十一步:游戏结束
11.1 清除掉当前页面上的所有的定时器
11.2 清除掉所有子弹上的定时器以及删除所有的子弹元素
11.3 清除掉素有敌机上的定时器以及删除所有的敌机元素
11.4 清空子弹和敌机的集合
11.5 删除己方飞机上的移动事件
11.6 回到游戏开始界面
一、html代码
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>javascript 原生打飞机游戏</title>
	<link rel="stylesheet" href="style.css">
	<script src="plane.js"></script>
</head>
<body>
	<div id="game">
		<div id="gameStart">
			<span>开始游戏</span>
		</div>
		<div id="gameEnter">
			<div id="myPlane">
				<img src="image/my.gif" alt="">
			</div>
			<div id="bullets">
			</div>
			<div id="enemys"></div>
			<div id="scores">
				<p>得分:<span>0</span> 分</p>
			</div>
		</div>
	</div>
</body>
</html>
二、css代码
*{
	margin: 0;
	padding: 0;
}
#game{
	width: 320px;
	height: 568px;
	margin: auto;
	overflow: hidden;
}
#gameStart{
	width: 100%;
	height: 100%;
	background: url(image/ks.png);
	position: relative;
	/*display: none;*/
}
#gameStart span{
	width: 160px;
	height: 40px;
	display: block;
	background: rgba(196,201,202);
	border: 4px solid #666;
	box-sizing: border-box;
	text-align: center;
	line-height: 32px;
	font-size: 24px;
	font-weight: bolder;
	position: absolute;
	left: 80px;
	bottom: 200px;
	cursor: pointer;
}
#gameStart span:hover{
	color: #fff;
}
#gameEnter{
	width: 100%;
	height: 100%;
	background: url(image/background_1.png);
	position: relative;
	display: none;
}
#myPlane{
	width: 66px;
	height: 80px;
	position: absolute;
	left: 127px;
	bottom: 0;
	cursor: pointer;
}
#myPlane{
	width: 66px;
	height: 80px;
}
#myPlane img{
	cursor: move;
}
#bullets,#enemys{
	width: 100%;
	height: 100%;
	position: absolute;
	left: 0;
	top: 0;
}
.b{
	width: 6px;
	height: 14px;
	position: absolute;
}
.e{
	position: absolute;
}
#scores{
	width: 100%;
	height: 40px;
	line-height: 40px;
	font-size: 24px;
	font-weight: bolder;
	padding: 0 20px;
}
#scores p{
	text-align: right;
	width: 80%;
}
三、js代码
;window.onload = function(){
	// 获取标签元素的方法
	function $(idName){
		return document.getElementById(idName);
	}
	// 获取样式使用最终值的函数
	function getStyle(ele,attr){
		var res = null;
		if(ele.currentStyle){
			res = ele.currentStyle[attr];
		}else{
			res = window.getComputedStyle(ele,null)[attr];
		}
		return parseFloat(res);
	}
	// 获取需要使用到的标签元素
	var game = $("game")
	// 游戏开始的界面
	,	gameStart = $("gameStart")
	// 进入游戏的界面
	,	gameEnter = $("gameEnter")
	,	myPlane = $("myPlane")
	,	bulletsP = $("bullets")
	,	enemysP = $("enemys")
	,	s = $("scores").firstElementChild.firstElementChild;
	// 获取需要使用到的元素样式
	// 1、获取游戏界面的宽高
	var gameW = getStyle(game,"width")
	,	gameH = getStyle(game,"height");
	// 2、游戏界面的左上外边距
	var gameML = getStyle(game,"marginLeft")
	,	gameMT = getStyle(game,"marginTop");
	// 3、获取己方飞机的宽高
	var myPlaneW = getStyle(myPlane,"width")
	,	myPlaneH = getStyle(myPlane,"height");
	// 4、子弹的宽高
	var bulletW = 6
	,	bulletH = 14;

	// 声明需要使用到的全局变量
	var gameStatus = false // 当前的游戏状态
	,	a = null // 创建子弹的定时器
	,	b = null // 创建敌机的定时器
	,	c = null // 背景图运动的定时器
	,	backgroundPY = 0 // 背景图y轴的值
	,	bullets = [] // 所有子弹元素的集合
	,	enemys = [] // 所有敌机元素的集合
	,	scores = 0 // 得分
	;


	// 开始游戏
	gameStart.firstElementChild.onclick = function(){
		gameStart.style.display = "none";
		gameEnter.style.display = "block";
		// 给当前的文档添加键盘事件
		document.onkeyup = function(evt){
			var e = evt || window.event;
			// 获取到键盘的键值
			var keyVal = e.keyCode;
			if(keyVal == 32){
				if(!gameStatus){
					// 初始化得分
					scores = 0;
					// 开始游戏
					this.onmousemove = myPlaneMove;
					// 实现开始游戏之后背景图的运动
					bgMove();
					// 实现射击
					shot();
					// 出现敌机
					appearEnemy();
					// 暂停游戏之后的开始游戏
					// 子弹的继续运动
					if(bullets.length != 0) reStart(bullets,1);
					// 敌机的继续运动
					if(enemys.length != 0) reStart(enemys);
				}else{
					// 暂停游戏
					this.onmousemove = null;
					// 清除创建敌机和创建子弹的定时器
					clearInterval(a);
					clearInterval(b);
					clearInterval(c);
					a = null;
					b = null;
					c = null;
					// 清除所有子弹和所有敌机上的运动定时器
					clear(bullets);
					clear(enemys);
				}
				gameStatus = !gameStatus;
			}
		}
	}
	// 己方飞机的移动
	function myPlaneMove(evt){
		var e = evt || window.event;
		// 获取鼠标移动时的位置
		var mouse_x = e.x || e.pageX
		,	mouse_y = e.y || e.pageY;

		// 计算得到鼠标移动时己方飞机的左上边距
		var last_myPlane_left = mouse_x - gameML - myPlaneW/2
		,	last_myPlane_top = mouse_y - gameMT - myPlaneH/2;
		// 控制飞机不能脱离当前的游戏界面
		if(last_myPlane_left <= 0){
			last_myPlane_left = 0;
		}else if(last_myPlane_left >= gameW - myPlaneW){
			last_myPlane_left = gameW - myPlaneW;
		}
		if(last_myPlane_top <= 0){
			last_myPlane_top = 0;
		}else if(last_myPlane_top >= gameH - myPlaneH){
			last_myPlane_top = gameH - myPlaneH;
		}
		myPlane.style.left = last_myPlane_left + "px";
		myPlane.style.top = last_myPlane_top + "px";
	}
	// 单位时间内创建子弹
	function shot(){
		if(a) return ;
		a = setInterval(function(){
			// 创建子弹
			createBullet();
		},100);
	}
	// 制造子弹
	function createBullet(){
		var bullet = new Image();
		bullet.src = "image/bullet1.png";
		bullet.className = "b";
		// 创建每一颗子弹都需要确定己方飞机的位置:
		var myPlaneL = getStyle(myPlane,"left")
		,	myPlaneT = getStyle(myPlane,"top");
		// 确定创建子弹的位置
		var bulletL = myPlaneL + myPlaneW/2 - bulletW/2
		,	bulletT = myPlaneT - bulletH;

		bullet.style.left = bulletL + "px";
		bullet.style.top = bulletT + "px";
		bulletsP.appendChild(bullet);
		bullets.push(bullet);
		move(bullet,"top");
	}
	// 子弹的运动:运动函数(匀速运动)
	function move(ele,attr){
		var speed = -8;
		ele.timer = setInterval(function(){
			var moveVal = getStyle(ele,attr);
			// 子弹运动出游戏界面:清除子弹的定时器,删除子弹元素
			if(moveVal <= -bulletH){
				clearInterval(ele.timer);
				ele.parentNode.removeChild(ele);
				bullets.splice(0,1);
			}else{
				ele.style[attr] = moveVal + speed + "px";
			}
		},10);
	}
	// 创建敌机数据对象
	var enemysObj = {
		enemy1: {
			width: 34,
			height: 24,
			score: 100,
			hp: 100
		},
		enemy2: {
			width: 46,
			height: 60,
			score: 500,
			hp: 800
		},
		enemy3: {
			width: 110,
			height: 164,
			score: 1000,
			hp: 2000
		}
	}
	// 创建敌机的定时器
	function appearEnemy(){
		if(b) return ;
		b = setInterval(function(){
			// 制造敌机
			createEnemy();
			// 删除死亡敌机
			delEnemy();
		},1000);
	}
	// 制造敌机的函数
	function createEnemy(){
		// 敌机出现概率的数据
		var percentData = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,3];
		// 敌机的类型
		var enemyType = percentData[Math.floor(Math.random()*percentData.length)];
		// 得到当前随机敌机的数据
		var enemyData = enemysObj["enemy" + enemyType];
		// 创建敌机所在的元素
		var enemy = new Image(enemyData.width,enemyData.height);
		enemy.src = "image/enemy" + enemyType + ".png";
		enemy.t = enemyType;
		enemy.score = enemyData.score;
		enemy.hp = enemyData.hp;
		enemy.className = "e";
		enemy.dead = false; // 敌机存活
		// 确定当前敌机出现时的位置
		var enemyL = Math.floor(Math.random()*(gameW - enemyData.width + 1))
		,	enemyT = -enemyData.height;
		enemy.style.left = enemyL + "px";
		enemy.style.top = enemyT + "px";
		enemysP.appendChild(enemy);
		enemys.push(enemy);
		enemyMove(enemy,"top");
	}
	// 敌机的运动
	function enemyMove(ele,attr){
		var speed = null;
		if(ele.t == 1){
			speed = 1.5;
		}else if(ele.t == 2){
			speed = 1;
		}else if(ele.t == 3){
			speed = 0.5;
		}
		ele.timer = setInterval(function(){
			var moveVal = getStyle(ele,attr);
			if(moveVal >= gameH){
				clearInterval(ele.timer);
				enemysP.removeChild(ele);
				enemys.splice(0,1);
			}else{
				ele.style[attr] = moveVal + speed + "px";
				// 每一架敌机运动时,检测和每一颗子弹的碰撞
				danger(ele);
				// 检测碰撞
				gameOver();
			}
		},10);
	}
	// 清除所有敌机和所有子弹上的运动定时器
	function clear(childs){
		for(var i=0;i<childs.length;i++){
			clearInterval(childs[i].timer);
		}
	}
	// 暂停游戏之后的开始游戏
	function reStart(childs,type){
		for(var i=0;i<childs.length;i++){
			type == 1 ? move(childs[i],"top") : enemyMove(childs[i],"top");
		}
	}
	// 开始游戏之后的背景图的运动
	function bgMove(){
		c = setInterval(function(){
			backgroundPY += 0.5;
			if(backgroundPY >= gameH){
				backgroundPY = 0;
			}
			gameEnter.style.backgroundPositionY = backgroundPY + "px";
		},10);
	}
	// 检测子弹和敌机的碰撞
	function danger(enemy){
		for(var i=0;i<bullets.length;i++){
			// 得到子弹的左上边距
			var bulletL = getStyle(bullets[i],"left")
			,	bulletT = getStyle(bullets[i],"top");
			// 得到敌机的左上边距
			var enemyL = getStyle(enemy,"left")
			,	enemyT = getStyle(enemy,"top");
			// 得到敌机的宽高
			var enemyW = getStyle(enemy,"width")
			,	enemyH = getStyle(enemy,"height");
			var condition = bulletL + bulletW >= enemyL && bulletL <= enemyL + enemyW && bulletT <= enemyT + enemyH && bulletT + bulletH >= enemyT;
			if(condition){
				//子弹和敌机的碰撞:删除子弹
				// 1、先清除碰撞子弹的定时器
				clearInterval(bullets[i].timer);
				// 2、删除元素
				bulletsP.removeChild(bullets[i]);
				// 3、从集合中删除子弹
				bullets.splice(i,1);
				// 4、子弹和敌机发生碰撞后,敌机血量减少,血量为0时,删除敌机
				enemy.hp -= 100;
				if(enemy.hp == 0){
					// 删除敌机
					clearInterval(enemy.timer);
					// 替换爆炸图片 
					enemy.src = "image/bz" + enemy.t + ".gif";
					// 标记死亡敌机
					enemy.dead = true;
					// 计算得分
					scores += enemy.score;
					s.innerHTML = scores;
				}
			}
		}
	}
	// 在创建敌机时,延时删除掉集合和文档中的死亡敌机
	function delEnemy(){
		for(var i=enemys.length - 1;i>=0;i--){
			if(enemys[i].dead){
				(function(index){
					// 从文档中删除死亡敌机元素
					enemysP.removeChild(enemys[index]);
					// 从集合中删除死亡敌机元素
					enemys.splice(index,1);
				})(i)
			}
		}
	}
	// 飞机碰撞,游戏结束
	function gameOver(){
		for(var i=0;i<enemys.length;i++){
			if(!enemys[i].dead){ // 游戏机界面内存活的敌机
				// 检测碰撞
				// 1、获取敌机的左上边距
				var enemyL = getStyle(enemys[i],"left")
				,	enemyT = getStyle(enemys[i],"top");;
				// 2、获取敌机的宽高
				var enemyW = getStyle(enemys[i],"width")
				,	enemyH = getStyle(enemys[i],"height");
				// 3、获取己方飞机的左上边距
				var myPlaneL = getStyle(myPlane,"left")
				,	myPlaneT = getStyle(myPlane,"top");
				var condition = myPlaneL + myPlaneW >= enemyL && myPlaneL <= enemyL + enemyW && myPlaneT <= enemyT + enemyH && myPlaneT + myPlaneH >= enemyT;
				if(condition){ // 己方飞机和敌机的碰撞
					// console.log("碰撞了...");
					// 清除定时器:创建子弹的定时器、创建飞机的定时器、游戏背景图的定时器
					clearInterval(a);
					clearInterval(b);
					clearInterval(c);
					a = null;
					b = null;
					c = null;
					// 删除子弹和敌机元素
					remove(bullets);
					remove(enemys);
					// 集合清空
					bullets = [];
					enemys = [];
					// 清除己方飞机的移动事件
					document.onmousemove = null;
					// 提示得分:
					alert("Game over: " + scores + "分");
					// 回到游戏开始界面
					gameStart.style.display = "block";
					gameEnter.style.display = "none";
					myPlane.style.left = "127px";
					myPlane.style.top = gameH - myPlaneH + "px";
				}
			}
		}
	}
	// 删除元素
	function remove(childs){
		for(var i = childs.length - 1;i>=0;i--){
			clearInterval(childs[i].timer);
			childs[i].parentNode.removeChild(childs[i]);
		}
	}
}
老规矩,附带教学视频:https://www.3mooc.com/front/couinfo/214

猜你喜欢

转载自www.cnblogs.com/ganjiang/p/11640130.html