游戏 保卫萝卜

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>bwlb</title>
<meta name="author" content="Administrator" />
<script src="jquery-1.11.1.js"></script>
<!-- Date: 2015-04-20 -->
<style>
#div1{ margin:20px auto; position:relative;}
.box1{ 50px; height:50px; background:black; float:left;}
.box2{ 50px; height:50px; background:white; float:left;}
.box3{ 50px; height:50px; background:yellow; float:left; text-align:center; line-height:50px;}
.box4{ 50px; height:50px; background:blue; float:left; text-align:center; line-height:50px;}
.gw1{ 50px; height:50px; background:url(gw1.jpg) no-repeat; position:absolute;}
.active{ background:red;}
.pt1{ 50px; height:50px; background:url(pt1.jpg) no-repeat; float:left;}
.bullet1{ 5px; height:5px; background:blue; position:absolute;}
</style>
<script>
	$(function(){
		var Game={
			arrMap : [   //地图  表现的路线跟地图一样 1代表黑色方块,3代表起始方块,2代表白色方块,4代表结束方块
				1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
				1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
				1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,
				1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,
				1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,
				1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,
				1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,
				1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,1,1,
				1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
				1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1
			],
			arrRoute : [  //方向  0代表不能走的区域 B T L R 代表方向 数字代表行走先后顺序
				0,0,'1B',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
				0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
				0,0,'2R',0,0,0,0,0,0,'3B',0,0,0,0,0,0,0,0,0,0,
				0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
				0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
				0,0,0,0,0,0,0,0,0,'4R',0,0,0,0,0,0,'5B',0,0,0,
				0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
				0,0,0,0,0,0,'7B',0,0,0,0,0,0,0,0,0,'6L',0,0,0,
				0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
				0,0,0,0,0,0,'8B',0,0,0,0,0,0,0,0,0,0,0,0,0
			],
			
			bBtn : true,
			
			//参考走口字  三个数组初始化为空   需要根据路线来找 各数组的内容
			rootDir:[],//运动的方向的数组
			rootSpeed:[],//运动的速度的数组
			rootTarget:[],//运动的目标点的数组
			
			colNum:20,  //每行的网格个数  因为数组是一个整体 不会换行
			gridWidth:50,  //网格的宽度
			gwStyle:'gw1',//敌人的样式 小怪物
			gwSpeed:5,//敌人运动的速度
			gwBlood:100,
			gwMoney:10,
			ptStyle:'pt1',//炮塔样式
			ptMoney:50,//炮塔价格
			bulletRange:100,//子弹的攻击范围
			bulletPower:10, //子弹攻击力
			bulletSpeed:10,//子弹速度
			bulletStyle:'bullet1',//子弹样式
			
			$startElement:null,//起始元素
			$endElement:null,//结束元素
			
			init:function(){  //初始化游戏
				this.elements();
				this.createMap();
				this.bindEvent();
				this.listens();
			},
			elements:function(){  //收集所有的元素  降低内存
				this.$parent = $('#div1');
				this.$startBtn = $('#start1');
				this.$money = $('#money1')
			},
			createMap:function(){ //创建地图
				var This=this;
				This.$parent.css('width',this.colNum*this.gridWidth); //设置div的宽 限制范围
				$.each(this.arrMap ,function(i,value){
					 var $div = $('<div class="box'+value+'"></div>');  //value指的就是数组中的每一项
					 
					 //添加 起始 结束 文字
					 if( value == 3 ){
					 	$div.html('起始');
					 	This.$startElement = $div; //起始元素
					 }else if( value==4 ){
					 	$div.html('结束');
					 	This.$endElement = $div;//结束元素
					 }
					 
					 This.$parent.append($div)
				})
				
				 this.rootes()
			},
			bindEvent:function(){  //事件操作的集合
				var This = this;
				//点击开始按钮
				this.$startBtn.on('click', function(){
					
					if( This.bBtn ){
						This.bBtn = false;
						This.createGWList();  //点击开始按钮创建小怪物  不管起始位置在哪里 小怪物在起始位置动态生成
					}	 
				})
				
				this.$parent.delegate('.box1','mouseover',function(){
					$(this).addClass('active')
				})
				
				this.$parent.delegate('.box1','mouseout',function(){
					$(this).removeClass('active')
				})
				
				//点击黑色部分 .box1  创建炮塔
				this.$parent.delegate('.box1','click',function(){
					 This.createPt(this)
				})
			},
			
			createGWList:function(){
				var num=10;//创建10个小怪物
				var This=this;
				var timer=setInterval(function(){
					if( num==0 ){
						clearInterval(timer)
					}else{
						This.createGW();
						num--
					}						
				},500)
			},
			//创建小怪物
			createGW:function(){
				var $gw = $('<div class="'+this.gwStyle+'"></div>');
				var x = this.$startElement.position().left; //position().left 相对有定位的父级
				var y = this.$startElement.position().top;
				$gw.css({'left':x,'top':y});
				//给怪物挂载血量 和 金币
				$gw.get(0).blood = this.gwBlood;
				$gw.get(0).money = this.gwMoney;
				this.$parent.append($gw);
				this.runGW($gw);//创建完怪物后让怪物运动起来
			},
			
			runGW:function($gw){ //敌人的运动
				 var iNow=0;
				 var nowVal=0;
				 var This=this;
				 $gw.get(0).timer=setInterval(function(){
				 	//根据三个数组来计算  rootDir  rootSpeed rootTarget
				 	nowVal = $gw.position()[This.rootDir[iNow]] + This.rootSpeed[iNow];
				 	$gw.css( This.rootDir[iNow], nowVal );
				 	
				 	if( Math.abs(nowVal - This.rootTarget[iNow] )<=1){
				 		if( iNow==This.rootTarget.length-1 ){
				 			 alert('游戏结束');
				 			 $gw.remove()
				 		}else{
				 			iNow++
				 		} 
				 	}
				 	
				 },30)
			},
			
			rootes:function(){  //收集路线
				var arr=[];
				var This = this;
				var $aDiv = this.$parent.find('div');
				$.each( this.arrRoute ,function(i,value){
					if( this!=0 ){//将方向和位置存起来  还有坐标i
						arr.push({ dir:value, xy:i })
					}
				})

				//调整顺序 按照数字排序
				arr.sort(function(dir1,dir2){
					//要比较前面的数字
					return dir1.dir.substring(0,dir1.dir.length-1) - dir2.dir.substring(0,dir2.dir.length-1)
				})
				
				//console.dir(arr) 
				//[{dir:1B,xy:2},{dir:2R,xy:42},{dir:3B,xy:49},{dir:4R,xy:109},{dir:5B,xy:116},{dir:6L,xy:156}...  ]
				$.each(arr,function(i,value){
					var dir = value.dir.substring(value.dir.length-1);//截取字母  决定方向的 B T L R
					if( i==arr.length-1 ){
						return false
					}
					
					switch(dir){
						case 'B':
						This.rootDir.push('top');
						This.rootSpeed.push(This.gwSpeed);
						This.rootTarget.push( $aDiv.eq( arr[i+1].xy ).position().top  )  //arr[i+1].xy是下一个目标点的坐标  目标点   是下一个坐标xy的开始的 元素
						break
						
						case 'T':
						This.rootDir.push('top');
						This.rootSpeed.push(-This.gwSpeed);
						This.rootTarget.push( $aDiv.eq( arr[i+1].xy ).position().top  );//xy 是坐标
						break
						
						case 'L':
						This.rootDir.push('left');
						This.rootSpeed.push(-This.gwSpeed);
						This.rootTarget.push( $aDiv.eq( arr[i+1].xy ).position().left  )
						break
						
						case 'R':
						This.rootDir.push('left');
						This.rootSpeed.push(This.gwSpeed);
						This.rootTarget.push( $aDiv.eq( arr[i+1].xy ).position().left  )
						break
					}
					
				})
			},
			createPt:function(elem){ //创建炮塔
				//把当前点击区域的样式改成炮塔的样式   每个炮塔金额50  因为不能无限生成炮塔 限制创建炮塔的个数 用金额来限制   当当前的金额>=50的时候可以创建炮塔
				if( parseInt( this.$money.val() )>= this.ptMoney ){
					$(elem).attr('class',this.ptStyle);  //当前点击处的样式切换 改个class 创建炮塔样式
					this.changeMoney(-this.ptMoney)  //创建一个炮塔 减去50元
				}
				
			},
			changeMoney:function(num){
				//num 就是炮塔所需要的金额
				var val = parseInt( this.$money.val() ) + num +"¥";
				this.$money.val(val)
				
			},
			disRange:function( $elem1, $elem2 ){  //攻击范围
				
				//炮塔与怪物的距离
				var a=$elem1.offset().left - $elem2.offset().left;
				var b=$elem1.offset().top - $elem2.offset().top;
			    var c= Math.sqrt(a*a + b*b)
				
				return c
			},
			//监听怪物是否进入攻击范围  点击开始按钮之后就可以监听
			listens:function(){
				var This = this;
				
				//找到所有炮塔
				var $aPt = this.$parent.find('.'+this.ptStyle);

				//对所有炮塔进行遍历
				$aPt.each(function(){
					This.listensGW(this)  //监听每一个敌人gw 并把每个炮塔传进去
				})
				setTimeout(function(){
					This.listens()  //每隔100ms  自调用  就会一直去监听  不用setInterval是因为setTimeout性能好些
				},100)
				
			},
			
			//每个炮塔跟所有怪物的检测 
			listensGW:function(pt){
				var This = this;
				
				//找到所有怪物
				var $aGw = this.$parent.find('.'+this.gwStyle);
				
				//需要将进入攻击范围的怪物存进数组中  数组是针对每一个炮塔的
				pt.arr=[];
				
				$aGw.each(function(i,elem){
					 
					//将进入攻击范围的怪物存到一个数组中 pt相当于一个变量,需要使用 $(pt) 来调用  因为传进来的是jquery的元素对象
					if(This.disRange($(pt),$(elem)) <= This.bulletRange){ 
						pt.arr.push(elem)
					}
				})	 
				
				//什么时候攻击? 当数组里有值的时候攻击
				if(pt.arr.length){
					 this.createBullet(pt)  //子弹是炮塔发出的
				}	
				
			},
			createBullet:function(pt){
				//创建子弹
				var $bu = $('<span class="'+this.bulletStyle+'"></span>');
				//子弹的初始位置位于炮塔的中心点
				$bu.css({
						 'left': $(pt).position().left + $(pt).width()/2 , 
						 'top': $(pt).position().top + $(pt).height()/2 
					    })
			    $(pt).append($bu);
				this.runBullet(pt,$bu)
			},
			runBullet:function(pt,$bu){
				var This = this;
				$bu.get(0).timer=setInterval(function(){
					   if( !pt.arr.length ){
							clearInterval($bu.get(0).timer);
							pt.innerHTML = '';
							return false;
						}

						//跟踪算法  运动的是子弹 相对静止的是敌人  从最后一个怪物开始攻击  怪物存在数组中
						var curGw =pt.arr[pt.arr.length-1];//当前怪物  从最后一个计算
						
						var a = $(curGw).offset().left + $(curGw).width()/2 -$bu.offset().left;
						var b = $(curGw).offset().top + $(curGw).height()/2 -$bu.offset().top;
						var c = Math.sqrt( a*a + b*b ); //怪物与 子弹的距离
						
						// This.bulletSpeed斜边的速度 求 X轴速度 和 Y轴速度
						var speedX = This.bulletSpeed * a/c;
						var speedY = This.bulletSpeed * b/c;
						
						$bu.css({
								'left':$bu.position().left + speedX,
								'top':$bu.position().top + speedY,
						})
						
						 
						//如果子弹击中了怪物
						if( This.pz( $bu , $(curGw) ) ){
							$bu.remove();
							
							curGw.blood = curGw.blood - This.bulletPower;
							if( !curGw.blood  ){
								clearInterval( $bu.get(0).timer ); //敌人消灭后 关掉子弹的定时器
								clearInterval( curGw.timer );//敌人消灭后 关掉敌人的定时器
							    $(curGw).remove();
								This.changeMoney(curGw.money) //打死一个敌人 增加敌人的金币
							} 
						} 
				},30)
				
			},
			pz : function($obj1,$obj2){  //碰撞检测
					var T1 = $obj1.offset().top;
					var B1 = $obj1.offset().top + $obj1.height();
					var L1 = $obj1.offset().left;
					var R1 = $obj1.offset().left + $obj1.width();
					var T2 = $obj2.offset().top;
					var B2 = $obj2.offset().top + $obj2.height();
					var L2 = $obj2.offset().left;
					var R2 = $obj2.offset().left + $obj2.width();
					if(T1>B2 || B1<T2 || L1>R2 || R1<L2){
						return false;
					}
					else{
						return true;
					}
			}
		}
		
		Game.init();
	})
</script>
</head>
<body>
<input type="button" id="start1" value="开始">
<input type="button" value="200¥" id="money1" />
<div id="div1"></div>
</body>
</html>

  

原文地址:https://www.cnblogs.com/webskill/p/4540673.html