飛機大戰

效果圖


lufy原版

http://www.hui12.com/nbin/game/plane/index.html

https://nbin2008.github.io/demo/plane/index.html

div版

http://www.hui12.com/nbin/game/plane/index2.html

https://nbin2008.github.io/demo/plane/index2.html

div版dom動畫過多會有卡頓現象,以學習思路爲主。


div版代碼

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>飛機大戰 div版</title>
		<link rel="stylesheet" type="text/css" href="css/index2.css"/>
		<script src="js/jquery-2.1.0.js"></script>
		<script src="js/Plain.js"></script>
		<script src="js/Bullet.js"></script>
		<script src="js/BulletCtrl.js"></script>
		<script src="js/nb-main.js"></script>
	</head>
	<body>
		<div class="container">
			<div class="plainLayer"></div>
			<div class="bulletLayer"></div>
			<div class="ammoLayer"></div>
			<div class="txtLayer"></div>
			<div class="gameover">遊戲結束</div>
		</div>
	</body>
</html>


/*
 * 飛機大戰
 */

*{ margin: 0; padding: 0; }
body, html{ font-size: 12px; font-family: "微軟雅黑"; }

.container{
	width: 800px; height: 400px; background: #000000; position: absolute; left: 10px; top: 10px; color: #fff; overflow: hidden;
}
.container div{
	position: absolute;
}

/* 文字層 */
.txtLayer{
	left: 5px; top: 2px;
}
/* 飛機層 */
.plainLayer .self{
	width: 50px; height: 47px; background: url(../images/player.png);
}
.plainLayer .enemy01{
	width: 50px; height: 40px; background: url(../images/enemy1.png);
}
.plainLayer .enemy02{
	width: 38px; height: 50px; background: url(../images/enemy2.png);
}
.plainLayer .enemy03{
	width: 150px; height: 132px; background: url(../images/enemy3.png);
}
/* 子彈層 */
.bulletLayer .self{
	width: 10px; height: 10px; background: url(../images/bullet01.png); border-radius: 50%;
}
.bulletLayer .enemy{
	width: 10px; height: 10px; background: url(../images/bullet02.png); border-radius: 50%;
}
.bulletLayer .die{
	width: 49px; height: 44px; background: url(../images/remove.png); margin-left: -20px; margin-top: -18px;
}
/* 彈藥層 */
.ammoLayer .ammo01{
	width: 30px; height: 30px; background: url(../images/item01.png); border-radius: 50%;
}
.ammoLayer .ammo02{
	width: 30px; height: 30px; background: url(../images/item02.png); border-radius: 50%;
}
/* gameOver */
.container .gameover{
	width:200px; height: 100px; left: calc(50% - 100px); top: calc(50% - 50px); text-align: center; line-height: 100px; border: 2px solid #FF0000; background-color: #ccc; font-size: 20px; display: none;
}


/*
 * 灰機大戰
 */
//全局變量
var env = {};
function callParent(obj,name,args){
	var tmp = {
		s1: "obj.constructor.prototype",
		s2: "obj.constructor.prototype[name]"
	};
	var back = null;
	while( !eval(tmp.s2) ){
		tmp.s1 += ".constructor.prototype";
		tmp.s2 = tmp.s1 + "[name]";
		if( eval(tmp.s1) == back ){
			return;
		}
		back = eval(tmp.s1);
	};
	var str = tmp.s2 + ".apply(obj,args)";
	eval(str);
};
//碰撞檢測
function crashTest(a,b){
	var aWidth = a.w,
		aHeight = a.h,
		aLeft = a.x,
		aTop = a.y;
	var bWidth = b.w,
		bHeight = b.h,
		bLeft = b.x,
		bTop = b.y;
	if( aLeft+aWidth<bLeft || aLeft>bLeft+bWidth || aTop+aHeight<bTop || aTop>bTop+bHeight ){
		return false
	}else{
		return true;
	};
};
//敵機
var ctrlList=[
//	{"frames":10,"bullet":3,"move":[-1,0],cName:"enemy03",x:800,y:180,hp:100,isboss:true}
	{"frames":10,"bullet":4,"move":[-1,1,-1,-1],cName:"enemy01",x:800,y:0,hp:3,isboss:false},
	{"frames":15,"bullet":4,"move":[-1,1,-1,-1],cName:"enemy01",x:800,y:0,hp:3,isboss:false},
	{"frames":20,"bullet":4,"move":[-1,1,-1,-1],cName:"enemy01",x:800,y:0,hp:3,isboss:false},
	{"frames":25,"bullet":4,"move":[-1,1,-1,-1],cName:"enemy01",x:800,y:0,hp:3,isboss:false},
	{"frames":30,"bullet":4,"move":[-1,1,-1,-1],cName:"enemy01",x:800,y:0,hp:3,isboss:false},
	{"frames":50,"bullet":5,"move":[0,-1,-1,1],cName:"enemy02",x:600,y:400,hp:5,isboss:false},
	{"frames":55,"bullet":5,"move":[0,-1,-1,1],cName:"enemy02",x:600,y:400,hp:5,isboss:false},
	{"frames":60,"bullet":5,"move":[0,-1,-1,1],cName:"enemy02",x:600,y:400,hp:5,isboss:false},
	{"frames":65,"bullet":5,"move":[0,-1,-1,1],cName:"enemy02",x:600,y:400,hp:5,isboss:false},
	{"frames":70,"bullet":5,"move":[0,-1,-1,1],cName:"enemy02",x:600,y:400,hp:5,isboss:false},
	{"frames":90,"bullet":4,"move":[-1,-1,-1,1],cName:"enemy01",x:800,y:400,hp:3,isboss:false},
	{"frames":95,"bullet":4,"move":[-1,-1,-1,1],cName:"enemy01",x:800,y:400,hp:3,isboss:false},
	{"frames":100,"bullet":4,"move":[-1,-1,-1,1],cName:"enemy01",x:800,y:400,hp:3,isboss:false},
	{"frames":105,"bullet":4,"move":[-1,-1,-1,1],cName:"enemy01",x:800,y:400,hp:3,isboss:false},
	{"frames":110,"bullet":4,"move":[-1,-1,-1,1],cName:"enemy01",x:800,y:400,hp:3,isboss:false},
	{"frames":130,"bullet":5,"move":[0,1,-1,-1],cName:"enemy02",x:600,y:0,hp:5,isboss:false},
	{"frames":135,"bullet":5,"move":[0,1,-1,-1],cName:"enemy02",x:600,y:0,hp:5,isboss:false},
	{"frames":140,"bullet":5,"move":[0,1,-1,-1],cName:"enemy02",x:600,y:0,hp:5,isboss:false},
	{"frames":145,"bullet":5,"move":[0,1,-1,-1],cName:"enemy02",x:600,y:0,hp:5,isboss:false},
	{"frames":150,"bullet":5,"move":[0,1,-1,-1],cName:"enemy02",x:600,y:0,hp:5,isboss:false},
	{"frames":180,"bullet":3,"move":[-1,0],cName:"enemy03",x:800,y:180,hp:100,isboss:true},
	{"frames":200,"bullet":4,"move":[-1,1,-1,-1],cName:"enemy01",x:800,y:0,hp:3,isboss:false},
	{"frames":220,"bullet":5,"move":[0,1,-1,-1],cName:"enemy02",x:600,y:0,hp:5,isboss:false},
	{"frames":230,"bullet":4,"move":[-1,1,-1,-1],cName:"enemy01",x:800,y:0,hp:3,isboss:false},
	{"frames":250,"bullet":4,"move":[-1,1,-1,-1],cName:"enemy01",x:800,y:0,hp:3,isboss:false}
];
//子彈
var bulletList = [
	{startAngle:0,angle:20,step:10,speed:4,count:1},//1發
	{startAngle:-20,angle:20,step:10,speed:4,count:3},//3發
	{startAngle:-40,angle:20,step:10,speed:4,count:5},//5發
	{startAngle:0,angle:20,step:10,speed:4,count:18},//環發
	{startAngle:180,angle:20,step:50,speed:4,count:1},//1發
	{startAngle:160,angle:20,step:50,speed:4,count:3},//3發
	{startAngle:140,angle:20,step:50,speed:4,count:5}//5發
];
//全局變量
var env = {};

$(document).ready(function(){
	env = {
		width: $(".container").width(),
		height: $(".container").height(),
		bulletCache: [],
		enemyCache: [],
		bulletCtrlCache: [],
		$container: $(".container"),
		$plainLayer: $(".plainLayer"),
		$bulletLayer: $(".bulletLayer"),
		$ammoLayer: $(".ammoLayer"),
		$txtLayer: $(".txtLayer"),
		gameOver: function(){
			clearInterval(env.timer);
			$(".gameover").show();
			$(".gameover").on("click", function(){
				window.location.href = window.location.href
			});
		}
	};
	var $contaniner = env.$container,
		$plainLayer = env.$plainLayer,
		$bulletLayer = env.$bulletLayer,
		$ammoLayer = env.$ammoLayer,
		$txtLayer = env.$txtLayer;
	
	function Game(){
		this.init();
	};
	var proto = {
		init: function(){
			this.before();
			this.createSelfPlain();
			this.mouseEvent();
			this.start();
		},
		before: function(){
			var nb = this.nb = {};
				nb.MOVE_STEP = 5;
		},
		createSelfPlain: function(){
			var This = this,
				nb = this.nb;
			nb.player = new Player();
			env.player = nb.player;
			nb.player.create(100,150,50,25,$plainLayer,"self",30);
			nb.player.setBullet(0);
		},
		mouseEvent: function(){
			var This = this;
				nb = this.nb;
				player = nb.player;
			$contaniner.on("mousedown", function(event){
				player.canShoot = true;
				setCoordinate(event.pageX,event.pageY);
			});
			$contaniner.on("mousemove", function(e){
				if( !player.canShoot ) return;
				nb.mouseNowX = e.pageX;
				nb.mouseNowY = e.pageY;
			});
			$contaniner.on("mouseup", function(){
				player.canShoot = false;
			});
			function setCoordinate(x,y){
				nb.mouseStartX = nb.mouseNowX = x;
				nb.mouseStartY = nb.mouseNowY = y;
				player.downX = player.x;
				player.downY = player.y;
			};
		},
		start: function(){
			var This = this,
				nb = this.nb,
				player = nb.player;
				MOVE_STEP = nb.MOVE_STEP,
				ctrlIndex = 0,
				frame = 0,
				frames = 0;
			env.timer = nb.timer = setInterval(function(){
				start();
			},20);
			function start(){
				//已機
				player.onframe();
				//敵機
				for( var i=env.enemyCache.length-1; i>=0; i-- ){
					if( env.enemyCache[i].onframe() ){
						env.enemyCache.splice(i,1);
					};
				};
				//子彈
				for( var i=env.bulletCache.length-1; i>=0; i-- ){
					if( env.bulletCache[i].onframe() ){
						env.bulletCache.splice(i,1);
					};
				};
				//彈藥
				for( var i=env.bulletCtrlCache.length-1; i>=0; i-- ){
					if( env.bulletCtrlCache[i].onframe() ){
						env.bulletCtrlCache.splice(i,1);
					};
				};
				//設置敵機
				setObject();
				//顯示血量
				showText();
				//己機移動
				if( !player.canShoot ) return;
				if(player.x - player.downX > nb.mouseNowX - nb.mouseStartX){
					player.x -= MOVE_STEP;
					if(player.x - player.downX < nb.mouseNowX - nb.mouseStartX){
						player.x = nb.mouseNowX - nb.mouseStartX + player.downX;
					}
				}else if(player.x - player.downX < nb.mouseNowX - nb.mouseStartX){
					player.x += MOVE_STEP;
					if(player.x - player.downX > nb.mouseNowX - nb.mouseStartX){
						player.x = nb.mouseNowX - nb.mouseStartX + player.downX;
					}
				}
				if(player.y - player.downY > nb.mouseNowY - nb.mouseStartY){
					player.y -= MOVE_STEP;
					if(player.y - player.downY < nb.mouseNowY - nb.mouseStartY){
						player.y = nb.mouseNowY - nb.mouseStartY + player.downY;
					}
				}else if(player.y - player.downY < nb.mouseNowY - nb.mouseStartY){
					player.y += MOVE_STEP;
					if(player.y - player.downY > nb.mouseNowY - nb.mouseStartY){
						player.y = nb.mouseNowY - nb.mouseStartY + player.downY;
					}
				}
				if(player.x < 0){
					player.x = 0;
					nb.mouseStartX = nb.mouseNowX;
					nb.mouseStartY = nb.mouseNowY;
					player.downX = player.x;
					player.downY = player.y;
				}
			};
			//顯示血量
			function showText(){
				$txtLayer.text("");
				var str = "";
				for( var i=0; i<player.hp; i++ ){
					str += "■";
				};
				$txtLayer.text(str);
			};
			//設置敵機
			function setObject(){
				if(frame++ < 10)return;
				frame = 0;
				frames++;
				//彈藥包
				if(frames % 50 == 0){
					var bulletIndex = Math.random()>0.5?1:2;
					var attr = {
						x: 790,
						y: 100+Math.random()*200,
						xspeed: -1,
						yspeed: 0,
						bulletIndex: bulletIndex,
						cName: "ammo0" + bulletIndex,
					};
					var ammo = new BulletCtrl(attr);
					env.bulletCtrlCache.push(ammo);
				};
				//敵機
				var ctrlObject = ctrlList[ctrlIndex];
				if( !ctrlObject ) return;
				if(ctrlObject["frames"] == frames){
					ctrlIndex++;
					
					var cName = ctrlObject["cName"];
					var enemy;
					if(ctrlObject.isboss){
						enemy = new Boss();
						enemy.create(ctrlObject.x,ctrlObject.y,0,66,$plainLayer,cName,ctrlObject["hp"]);
					}else{
						enemy = new Enemy();
						enemy.create(ctrlObject.x,ctrlObject.y,0,22,$plainLayer,cName,ctrlObject["hp"]);
					}
					env.enemyCache.push(enemy);
					enemy.setBullet(ctrlObject.bullet);
					enemy.move = ctrlObject.move;
					enemy.canShoot=true;
				}
			}
		}
	};
	Game.prototype = proto;
	var g = new Game();
});


/*
 * 灰機構造函數
 */
function Plain(){};
Plain.prototype.create = function(x,y,sx,sy,$parent,cName,hp){
	this.x = x;
	this.y = y;
	this.sx = sx;
	this.sy = sy;
	this.$parent = $parent;
	this.cName = cName;
	this.canShoot = false;
	this.move = [0,0];
	this.speed = 1;
	this.hp = hp;
	this.isdie = false;
	this.shoopIndex = 0;
	this.obj = $("<div class='"+ this.cName +"'></div>");
	this.obj.css("transform","translate3d("+ this.x +"px,"+ this.y +"px,0px)")
	this.$parent.append(this.obj);
};
Plain.prototype.onframe = function(){
	this.x += this.move[0]*this.speed;
	this.y += this.move[1]*this.speed;
	this.obj.css("transform","translate3d("+ this.x +"px,"+ this.y +"px,0px)")
	if( this.canShoot ) this.shoot();
};
Plain.prototype.shoot = function(){
	var self = this;
	var bullet = bulletList[self.bullet];
	if(self.shoopIndex++ < bullet.step)return;
	self.shoopIndex=0;
	//開始發射
	for(var i=0;i<bullet.count;i++){
		//發射角度
		var angle = i*bullet.angle + bullet.startAngle;
		//子彈xy軸速度
		xspeed = bullet.speed*Math.cos(angle * Math.PI / 180);
		yspeed = bullet.speed*Math.sin(angle * Math.PI / 180);
		var params = {
			bulletName: self.bulletName,
			x:self.x+self.sx,
			y:self.y+self.sy,
			xspeed:xspeed,
			yspeed:yspeed,
			belong:self.belong
		};
		//子彈實例化
		obj = new Bullet(params);
		//顯示
		env.bulletCache.push(obj);
	}
};
Plain.prototype.setBullet = function(bulletIndex){
	this.bullet = bulletIndex;
};

/*
 * 己方飛機
 */
function Player(){
	this.belong = "self";
	this.downX = this.downY = 0;
	this.bulletName = "self";
};
Player.prototype = new Plain();
Player.prototype.create = function(x,y,sx,sy,$parent,cName,hp){
	callParent(this,"create",arguments);
};
Player.prototype.onframe = function(){
	callParent(this,"onframe",arguments);
	if( this.hp<0 ){
		env.gameOver();
	};
};

/*
 * 敵機類
 */
function Enemy(){};
Enemy.prototype = new Plain();
Enemy.prototype.create = function(x,y,sx,sy,$parent,cName,hp){
	this.belong = "enemy";
	this.bulletName = "enemy"
	callParent(this,"create",arguments);
};
Enemy.prototype.onframe = function(){
	var self = this;
	callParent(self,"onframe",arguments);
	var isOut = false;
	if(self.x < -self.obj.width() || self.x > env.width || self.y < -self.obj.height() || self.y > env.height){
		isOut = true;
	}
	if(isOut)self.whenOut();
	if(self.isdie || self.hp <= 0){
		self.obj.remove();
		return true;
	}
};
Enemy.prototype.whenOut = function (){
	var self = this;
	if(self.move.length > 0)self.move.splice(0,2);
	if(self.move.length == 0)self.isdie = true;
};

/*
 * boss
 */
function Boss(){};
Boss.prototype = new Plain();
Boss.prototype.create = function(){
	this.belong = "enemy";
	this.bulletName = "enemy"
	this.shootIndex = 0;
	callParent(this,"create",arguments);
};
Boss.prototype.onframe = function(){
	var self = this;
	callParent(self,"onframe",arguments);
	var isOut = false;
	if(self.x < -self.obj.width() || self.x > env.width || self.y < -self.obj.height() || self.y > env.height){
		isOut = true;
	};
	if(isOut)self.whenOut();
	if(self.isdie || self.hp <= 0){
		self.obj.remove();
		env.gameOver();
		return true;
	};
};
Boss.prototype.whenOut = function (){
	var self = this;
	if(self.x < 400){
		self.move[0]=1;
		self.move[1]=Math.random()>0.5?1:-1;
	}else{
		self.move[0]=-1;
		self.move[1]=Math.random()>0.5?1:-1;
	}
};
Boss.prototype.shoot = function (){
	var self = this;
	self.shootIndex++;
	if(self.shootIndex>100 && self.shootIndex < 150){
		return;
	}else if(self.shootIndex >= 150){
		self.shootIndex = 0;
	}
	callParent(self,"shoot",arguments);
};


/**
 * 子彈類 
 * */
function Bullet(params){
	var self = this;
	//出現位置
	self.x = params.x;
	self.y = params.y;
	//xy軸速度
	self.xspeed = params.xspeed;
	self.yspeed = params.yspeed;
	self.belong = params.belong;
	self.isdie = false;
	//子彈圖片
	self.obj = $("<div class='"+ params.bulletName +"'></div>")
	env.$bulletLayer.append(self.obj);
	self.obj.css("transform","translate3d("+ self.x +"px,"+ self.y +"px,0px)")
}

/**
 * 循環
 * */
Bullet.prototype.onframe = function (){
	var self = this;
	if(self.isdie){
		self.removeRun();
		return true;
	};
	
	//子彈移動
	self.x += self.xspeed;
	self.y += self.yspeed;
	self.obj.css("transform","translate3d("+ self.x +"px,"+ self.y +"px,0px)")
	//子彈位置檢測
	if(self.x < 0 || self.x > env.width || self.y < 0 || self.y > env.height){
		//從屏幕移除
		self.obj.remove();
		return true;
	};
	var key,plain,
		player = env.player;
		var a = {
			w: self.obj.width(),
			h: self.obj.height(),
			x: self.x,
			y: self.y
		};
	if(self.belong == player.belong){
		for( var i=0; i<env.enemyCache.length; i++ ){
			var enemy = env.enemyCache[i];
			var b = {
				w: enemy.obj.width,
				h: enemy.obj.height,
				x: enemy.x,
				y: enemy.y
			};
			if( crashTest(a,b) ){
				enemy.hp--;
				self.isdie = true;
				self.obj.addClass("die");
			};
		};
	}else{
		var b = {
			w: player.obj.width(),
			h: player.obj.height(),
			x: player.x,
			y: player.y
		};
		if( crashTest(a,b)){
			player.hp--;
			self.isdie=true;
			self.obj.addClass("die");
		}
	};
};
Bullet.prototype.removeRun = function (){
	var self = this;
	self.obj.addClass("die");
	self.obj.animate({"opacity":0},500,"linear");
};

/**
 * 彈藥類 
 * */
function BulletCtrl(params){
	var self = this;
	//出現位置
	self.x = params.x;
	self.y = params.y;
	//xy軸速度
	self.xspeed = params.xspeed;
	self.yspeed = params.yspeed;
	self.bulletIndex = params.bulletIndex;
	self.obj = $("<div class='"+ params.cName +"'></div>");
	env.$ammoLayer.append(self.obj);
	self.obj.css("transform","translate3d("+ self.x +"px,"+ self.y +"px,0px)");
}

/**
 * 循環
 * */
BulletCtrl.prototype.onframe = function (){
	var self = this;
	//移動
	self.x += self.xspeed;
	self.y += self.yspeed;
	self.obj.css("transform","translate3d("+ self.x +"px,"+ self.y +"px,0px)")
	//位置檢測
	if(self.x < 0 || self.x > env.width || self.y < 0 || self.y > env.height){
		//從屏幕移除
		self.obj.remove();
		return true;
	};
	var a={
		w: self.obj.width(),
		h: self.obj.height(),
		x: self.x,
		y: self.y
	};
	var player = env.player;
	var b={
		w: player.obj.width(),
		h: player.obj.height(),
		x: player.x,
		y: player.y
	};
	if( crashTest(a,b)){
		player.setBullet(self.bulletIndex);
		self.obj.remove();
		return true;
	}
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章