本文主要是介绍原生JS经典射击游戏-小蜜蜂,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
经典射击游戏-小蜜蜂做之前的大概思路看下面这个图,这个游戏我打算用单例模式来写也就是平常我们说的单体模式。
源码链接
在线玩经典射击游戏-小蜜蜂
单体是一个用来划分命名空间并将一批相关的属性和方法组织在一起的对象,如果他可以被实例化,那么他只能被实例化一次。 单体模式是javascript里面最基本但是也是最有用的也是最常用的模式之一。
单体模式的特点:
- 可以用来划分命名空间,从而清除全局变量所带来的危险,也就是该类只有一个实例
- 该类自行创建该实例,即在该类内部创建自身的实例对象,向整个系统公开这个实例接口。
- 利用分支技术来封装浏览器直接的差异
- 可以把代码组织的更为一体,便于阅读和维护。
单体模式的思路是: 一个类能返回一个对象的引用(并且永远是同一个)和一个获得该实例的方法(静态方法,通常使用getInstance名称)。那么当我们调用这个方法时,如果类持有的引用不为空就返回该引用,否者就创建该类的实例,并且将实例引用赋值给该类保持的那个引用再返回。同时将该类的构造函数定义为私有方法,避免其他函数使用该构造函数来实例化对象,只通过该类的静态方法来得到该类的唯一实例。 用一句话来说,单例模式的核心是确保只有一个实例,并提供全局访问。
布局代码
<!doctype html>
<html lang="en"><head><meta charset="UTF-8"><title>经典射击游戏-小蜜蜂</title><link rel="stylesheet" href="css/index.css" /><script type="text/javascript" src="js/index.js" charset="UTF-8"></script></head><body><div id="containt"><div id="goBtn">游戏开始</div></div></body>
</html>
CSS
body,ul,li,span{margin:0;padding:0;
}
html,body {width:100%;height:100%;overflow:hidden;
}
body {background:#f1f1f1;
}
li{list-style:none;
}
.score {color:white;
}
#containt{width:900px;height:600px;overflow:hidden;background:black;margin:10px auto;position:relative;
}
#goBtn{ color:white;font-size:20px;cursor:pointer;border:1px #FFFFFF solid;width:100px;height:40px;line-height:40px;text-align:center;position:absolute;top:50%;left:50%;margin-top:-20px;margin-left:-50px;
}
.enemy1 {/* 一级怪的样式 */width:25px;height:25px;background:url(../images/aliensheet.png);background-position:left bottom;overflow:hidden;float:left;
}
.enemy2 {/* 二级怪的样式 */width:25px;height:25px;background:url(../images/aliensheet.png);background-position:left 50px;overflow:hidden;float:left;
}
.enemy3 {/* 三级怪的样式 */width:25px;height:25px;background:url(../images/aliensheet.png);background-position:left 72px;overflow:hidden;float:left;
}
.enemy4 {/* 四级怪的样式 */width:25px;height:25px;background:url(../images/aliensheet.png);background-position:left top;overflow:hidden;float:left;
}
.air { /* 飞机的样式 */width:32px;height:25px;background:url(../images/playersheet.png);background-position:left 0px;overflow:hidden;position:absolute;left:0px;top:0px;
}
.bullet { /* 子弹的样式 */width:4px;height:16px;background:url(../images/lasers.gif);background-position:left 0px;overflow:hidden;position:absolute;
}
#list {position:relative;
}
#list:after {content:'';display:block;clear:both;
}
javascript
window.onload = function() {var oBtn = document.getElementById("goBtn");oBtn.onclick = function() {this.style.display = "none";Game.init("containt");}
}
var Game = {//敌人数据oEnemy : {/*** style 敌人样式* blood 敌人的血量* speed 敌人的移动速度* score 敌人的积分*/oEnemy1 : {style:"enemy1",blood:1,speed:2,score:1},oEnemy2 : {style:"enemy2",blood:2,speed:3,score:2},oEnemy3 : {style:"enemy3",blood:3,speed:4,score:3},oEnemy4 : {style:"enemy4",blood:4,speed:5,score:4}},gk : [//第一关{aMap : ['oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1'],cloNum : 10,iSpeedX : 3,iSpeedY : 2,timer : 2000,},//第二关{aMap : ['oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1'],cloNum : 10,iSpeedX : 4,iSpeedY : 2,timer : 3000,},//第三关{aMap : ['oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy2','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1'],cloNum : 13,iSpeedX : 5,iSpeedY : 2,timer : 3000,},//第四关{aMap : ['oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1'],cloNum : 13,iSpeedX : 5,iSpeedY : 2,timer : 3000,},//第五关{aMap : ['oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1'],cloNum : 13,iSpeedX : 5,iSpeedY : 2,timer : 3000,},//第六关{aMap : ['oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy4','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy3','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1','oEnemy1',],cloNum : 18,iSpeedX : 5,iSpeedY : 2,timer : 3000,}], //通关数gs : {gs : 0,},air : {style : "air", //飞机样式bulletStyle : "bullet" //子弹样式},//初始化init : function(id) {this.oParent = document.getElementById(id);this.createScore();this.createEemey(this.gs.gs);this.createAir()},//创建积分createScore : function() {var oSco = document.createElement("div");oSco.className = "score";oSco.innerHTML = "积分:<span>0</span>分";this.oParent.appendChild(oSco);this.oNum = oSco.getElementsByTagName("span")[0];},//创建敌人createEemey : function(iNow) {//如果敌人整体的ul还存在就把它删掉if(this.list) {clearInterval(this.list.timer); // 如果敌人整体的ul还存在就应该删掉前把定时器关掉this.oParent.removeChild(this.list); //删除敌人}var oGk = this.gk[iNow]; //获取关卡数据//创建ul并且加到containt里面去var oUl = document.createElement("ul");oUl.id="list";oUl.style.width = oGk.cloNum*25 + "px"; //给ul宽度,也就是控制每一行显示的个数this.list = oUl;this.oParent.appendChild(oUl); // 追加oUl.style.left = (this.oParent.offsetWidth - oUl.offsetWidth)/2 + "px"; //默认让敌人在中间出发document.title = "经典射击游戏-小蜜蜂第" + (this.gs.gs + 1) +"关";//创建lifor(var i = 0; i < oGk.aMap.length; i++) {var oLi = document.createElement("li");//给敌人上装备比如:样式,血量,积分。把敌人的装备转成他们自身自定义属性oLi.className = this.oEnemy[oGk.aMap[i]].style;oLi.blood = this.oEnemy[oGk.aMap[i]].blood;oLi.speed = this.oEnemy[oGk.aMap[i]].speed;oLi.score = this.oEnemy[oGk.aMap[i]].score;oLi.zIndex1 = 1;oUl.appendChild(oLi);//追加}this.aLi = oUl.getElementsByTagName("li");// 向整个系统公开这个实例接口。//布局转换var arr = [];for(var i = 0; i < this.aLi.length; i++) {arr.push({l : this.aLi[i].offsetLeft,t : this.aLi[i].offsetTop}); //把宽高存到json里面,方便提取}// 加定位前把left和top值先加上去for(var i = 0; i < this.aLi.length; i++) {this.aLi[i].style.left = arr[i].l + "px";this.aLi[i].style.top = arr[i].t + "px";}//加定位for(var i = 0; i < this.aLi.length; i++) {this.aLi[i].style.position = "absolute";}this.runEemey(oGk); //敌人开始移动},//敌人移动runEemey : function(oGk) {var This = this; //转this指向,这没什么好说的var l = 0;var R = this.oParent.offsetWidth - this.list.offsetWidth; // 敌人右移动最大的leftthis.list.timer = setInterval(function(){if(This.list.offsetLeft < l) {oGk.iSpeedX*=-1; //转方向移动This.list.style.top = This.list.offsetTop + oGk.iSpeedY + "px"; //敌人向y轴移动一点点}else if(This.list.offsetLeft>R){oGk.iSpeedX*=-1;//转方向移动This.list.style.top = This.list.offsetTop + oGk.iSpeedY + "px";//敌人向y轴移动一点点}This.list.style.left = This.list.offsetLeft + oGk.iSpeedX + "px"; //敌人向水平方向移动},200);//在这开始单兵做战setInterval(function(){This.oneMove();},oGk.timer)},//单兵做战 敌人追随oneMove : function() {var This = this;var nowLi = this.aLi[Math.floor(Math.random()*this.aLi.length-1)]; // 随机选一个敌人出来作战,厉害了我的哥nowLi.style.zIndex = nowLi.zIndex1++; // 敌人每次出来都是正前方出来nowLi.timer = setInterval(function(){//蜜蜂和飞机中心点的水平距离var x = (This.oAir.offsetLeft + This.oAir.offsetWidth/2) - (nowLi.offsetLeft + This.list.offsetLeft + nowLi.offsetWidth/2); //X轴的距离var y = (This.oAir.offsetTop + This.oAir.offsetHeight/2) - (nowLi.offsetTop + This.list.offsetTop + nowLi.offsetHeight/2); //Y的距离var z = Math.sqrt(x*x+y*y); //勾股定理,我就不多说了var oIsX=nowLi.speed*x/z; var oIsY=nowLi.speed*y/z;nowLi.style.left = nowLi.offsetLeft + oIsX + "px"; //X轴追起来了,哈哈nowLi.style.top = nowLi.offsetTop + oIsY + "px"; //Y轴追起来了,哈哈//检测敌人是否碰到飞机,碰到就结束游戏if(This.pz(This.oAir,nowLi)){alert('游戏结束');window.location.reload(); //从新加载}},30);},// 创建飞机createAir : function() {var oAir = document.createElement("div");oAir.className = this.air.style;this.oAir = oAir;this.oParent.appendChild(oAir); // 追加//把飞机初始化位置调到中间oAir.style.left = (this.oParent.offsetWidth - oAir.offsetWidth)/2 + "px";oAir.style.top = (this.oParent.offsetHeight - oAir.offsetHeight-10) + "px";this.bindAir();},//操作飞机bindAir : function() {var timer = null;var iNum = 0;var This = this;document.onkeydown = function() {document.onkeydown = function(ev) {var ev = ev || event;if(!timer) {timer = setInterval(run,30);}if(ev.keyCode == 37 ) { //按左方向的时候干的事iNum = 1;} else if (ev.keyCode == 39) { //按右方向的时候干的事iNum = 2;} else if( ev.keyCode == 38) {//按上方向的时候干的事iNum = 3;} else if( ev.keyCode == 40) {//按下方向的时候干的事iNum = 4;}}document.onkeyup = function(ev) {var ev = ev || event;clearInterval(timer);timer = null;iNum = 0;if(ev.keyCode == 32) {This.createBullet();}}function run() {if(iNum == 1) {//禁止飞机从左边出去if(This.oAir.offsetLeft<=0) {This.oAir.style.left=0 + "px";}This.oAir.style.left = This.oAir.offsetLeft - 6 + "px";} else if (iNum == 2) {//禁止飞机从右边出去if(This.oParent.offsetWidth - This.oAir.offsetWidth <= This.oAir.offsetLeft) {This.oAir.style.left = This.oParent.offsetWidth - This.oAir.offsetWidth + "px";}This.oAir.style.left = This.oAir.offsetLeft + 6 + "px";} else if (iNum == 3) {//禁止飞机从上边出去if(This.oAir.offsetTop <= 0 ) {This.oAir.style.top = 10+"px";}This.oAir.style.top = This.oAir.offsetTop - 6 + "px";} else if (iNum == 4) {//禁止飞机从下边出去if(This.oAir.offsetTop >= This.oParent.offsetHeight - This.oAir.offsetHeight-10 ) {This.oAir.style.top = This.oParent.offsetHeight - This.oAir.offsetHeight-10+"px";}This.oAir.style.top = This.oAir.offsetTop + 6 + "px";}}}},// 创建子弹createBullet : function() {//创建divvar oBullet = document.createElement("div");oBullet.className = this.air.bulletStyle;this.oParent.appendChild(oBullet);//把子弹定位到飞机的正前方oBullet.style.left = this.oAir.offsetLeft + this.oAir.offsetWidth/2 + "px";oBullet.style.top = this.oAir.offsetTop - oBullet.offsetHeight + "px";//创建后就开始运动this.runBullet(oBullet);},//子弹运动runBullet : function(obj) {var This = this;obj.timer = setInterval(function(){if(obj.offsetTop < -11 ) {//当子弹飞出游戏窗就销毁该子弹,谨防子弹一直飞,导致子弹过多,页面元素过多影响性能clearInterval(obj.timer);This.oParent.removeChild(obj);} else {obj.style.top = obj.offsetTop - 5 + "px"; //子弹的速度}for(var i = 0; i < This.aLi.length; i++) {if(This.pz(obj,This.aLi[i])) { //如果碰撞了就为true否则为false// 如果敌人血量为0了,就把他干掉if(This.aLi[i].blood == 1 ) { clearInterval(This.aLi[i].timer);This.oNum.innerHTML = parseInt(This.oNum.innerHTML) + This.aLi[i].score;This.list.removeChild(This.aLi[i]);} else { //或者血量减1This.aLi[i].blood--;}clearInterval(obj.timer); //子弹碰到了敌人就把定时器关掉This.oParent.removeChild(obj); //子弹碰到了敌人就把子弹干掉}}if(!This.aLi.length) {//检测过了最后一关,就通关了if(This.gk.length == This.gs.gs) {alert("恭喜你,你通关了!");window.location.reload();}This.gs.gs++; This.createEemey(This.gs.gs);}},30);},//碰撞检测pz : function(obj1,obj2) {var L1 = obj1.offsetLeft;var R1 = obj1.offsetLeft + obj1.offsetWidth;var T1 = obj1.offsetTop;var B1 = obj1.offsetTop + obj1.offsetHeight;//因为小蜜蜂li是装在ul里面的,所以计算小蜜蜂的top、left值是相对于ul的,所以要加上ul的top、left值才算小蜜蜂的值var L2 = obj2.offsetLeft + this.list.offsetLeft;var R2 = obj2.offsetLeft + obj2.offsetWidth + this.list.offsetLeft;var T2 = obj2.offsetTop + this.list.offsetTop;var B2 = obj2.offsetTop +obj2.offsetHeight + this.list.offsetTop;if(R1<L2 || L1 > R2 || T1 < T2 || T1 > B2) {//这里是没有碰撞return false;} else {//碰撞了返回truereturn true;}}
}
最新源码点击这里源码链接
代码要是有看不懂的地方,在码云给我留言,我会第一时间回复你们。
这篇关于原生JS经典射击游戏-小蜜蜂的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!