javascript
JS原生编写飞机大战小蜜蜂游戏
javascript設(shè)計模式之單體模式--飛機大戰(zhàn)小蜜蜂游戲
單體是一個用來劃分命名空間并將一批相關(guān)的屬性和方法組織在一起的對象,如果他可以被實例化,那么他只能被實例化一次。
單體模式是javascript里面最基本但是也是最有用的也是最常用的模式之一。
單體模式的特點:
1,可以用來劃分命名空間,從而清除全局變量所帶來的危險
2,利用分支技術(shù)來封裝瀏覽器直接的差異。
3,可以把代碼組織的更為一體,便于閱讀和維護。
?
單體模式的思路是:
一個類能返回一個對象的引用(并且永遠是同一個)和一個獲得該實例的方法(靜態(tài)方法,通常使用getInstance名稱)。那么當(dāng)我們調(diào)用這個方法時,如果類持有的引用不為空就返回該引用,否者就創(chuàng)建該類的實例,并且將實例引用賦值給該類保持的那個引用再返回。同時將該類的構(gòu)造函數(shù)定義為私有方法,避免其他函數(shù)使用該構(gòu)造函數(shù)來實例化對象,只通過該類的靜態(tài)方法來得到該類的唯一實例。
游戲中的困擾:
1.飛機移動的同時可以發(fā)射子彈--解決辦法:在onkeydown中添加左右移動事件,在onkeyup中添加子彈發(fā)射事件和判斷是否是移動鍵移松開,如果是就讓移動失效,這樣就可以按下飛機移動鍵的同時,按下子彈發(fā)射鍵并松開此鍵發(fā)射子彈,此時飛機仍然移動。
源碼中用到的圖片:
飛機--???? 低級小蜜蜂--??? 中級小蜜蜂-- ?? 高級小蜜蜂--
源代碼:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>無標(biāo)題文檔</title>
<style>
*{ margin:0; padding:0;}
li{ list-style:none;}
#div1{ width:800px; height:600px; overflow:hidden; background:black; margin:20px auto; position:relative;}
#gameName{color:white;font-size:40px;font-family:'華文隸書';position:absolute;top:40px;left:255px;}
#gameAuthor{color:white;font-size:14px;position:absolute;top:578px;left:170px;}
#gameBtn{ color:white; font-size:20px; cursor:pointer; border:1px #FFFFFF solid; width:100px; height:30px; line-height:30px; text-align:center; position:absolute; top:285px; left:350px;}
#score{ color:#FFFFFF;}
#bee{ position:relative;}
.enemy1{ width:40px; height:28px; background:url(images/mf1.png) no-repeat; float:left;}
.enemy2{ width:40px; height:28px; background:url(images/mf2.png) no-repeat; float:left;}
.enemy3{ width:40px; height:28px; background:url(images/mf3.png) no-repeat; float:left;}
.air1{ width:46px; height:60px; background:url(images/fj.png) no-repeat; position:absolute;}
.bullet{ width:1px; overflow:hidden; height:10px; background:white; position:absolute;}
</style>
<script>
window.οnlοad=function(){
?? ?var oBtn=document.getElementById("gameBtn");
?? ?oBtn.οnclick=function(){
?? ??? ?this.style.display='none';
?? ??? ?document.getElementById('gameAuthor').style.display='none';
?? ??? ?document.getElementById('gameName').style.display='none';
?? ??? ?Game.init('div1');//游戲開始
?? ?};
};
var Game={
?? ?
?? ?oEnemy:{//敵人的數(shù)據(jù)
?? ??? ?e1:{style:'enemy1',blood:1,speed:3,score:1},
?? ??? ?e2:{style:'enemy2',blood:2,speed:4,score:2},
?? ??? ?e3:{style:'enemy3',blood:3,speed:4,score:3},
?? ?},
?? ?
?? ?gk:[//關(guān)卡的數(shù)據(jù)
?? ??? ?{//第一關(guān)
?? ??? ??? ?eMap:[
?? ??? ??? ??? ?'e2','e2','e2','e2','e2','e2','e2','e2','e2','e2',
?? ??? ??? ??? ?'e2','e2','e2','e2','e2','e2','e2','e2','e2','e2',
?? ??? ??? ??? ?'e2','e2','e2','e2','e2','e2','e2','e2','e2','e2',
?? ??? ??? ??? ?'e1','e1','e1','e1','e1','e1','e1','e1','e1','e1',
?? ??? ??? ??? ?'e1','e1','e1','e1','e1','e1','e1','e1','e1','e1',
?? ??? ??? ??? ?'e1','e1','e1','e1','e1','e1','e1','e1','e1','e1',
?? ??? ??? ?],
?? ??? ??? ?colNum:10,
?? ??? ??? ?iSpeedX:10,
?? ??? ??? ?iSpeedY:10,
?? ??? ??? ?times:2000//小蜜蜂飛下來的時間間隔
?? ??? ?},
?? ??? ?{//第二關(guān)
?? ??? ??? ?eMap:[
?? ??? ??? ??? ?'e3','e3','e3','e3','e3','e3','e3','e3','e3','e3',
?? ??? ??? ??? ?'e3','e3','e3','e3','e3','e3','e3','e3','e3','e3',
?? ??? ??? ??? ?'e3','e3','e3','e3','e3','e3','e3','e3','e3','e3',
?? ??? ??? ??? ?'e1','e1','e1','e1','e1','e1','e1','e1','e1','e1',
?? ??? ??? ??? ?'e1','e1','e1','e1','e1','e1','e1','e1','e1','e1',
?? ??? ??? ??? ?'e1','e1','e1','e1','e1','e1','e1','e1','e1','e1',
?? ??? ??? ?],
?? ??? ??? ?colNum:10,
?? ??? ??? ?iSpeedX:10,
?? ??? ??? ?iSpeedY:10,
?? ??? ??? ?times:2000//小蜜蜂飛下來的時間間
?? ??? ?}
?? ?],
?? ?
?? ?air:{//飛機的數(shù)據(jù)
?? ??? ?style:'air1',//飛機樣式
?? ??? ?bulletStyle:'bullet'//子彈樣式
?? ?},
?? ?
?? ?init:function(id){//初始化
?? ??? ?this.oParent=document.getElementById(id);
?? ??? ?
?? ??? ?this.createScore();//創(chuàng)建積分
?? ??? ?
?? ??? ?this.createEnemy(0);//創(chuàng)建敵人
?? ??? ?
?? ??? ?this.createAir();//創(chuàng)建飛機
?? ?},
?? ?
?? ?createScore:function(){//積分的創(chuàng)建
?? ??? ?var oS=document.createElement('div');
?? ??? ?oS.id='score';
?? ??? ?oS.innerHTML='積分:<span>0</span>';
?? ??? ?this.oParent.appendChild(oS);
?? ??? ?
?? ??? ?this.oSNum=oS.getElementsByTagName('span')[0];
?? ?},
?? ?
?? ?createEnemy:function(iNow){//敵人的創(chuàng)建
?? ?
?? ??? ?if(this.oUl){//如果敵人整體的ul還存在就把它刪掉
?? ??? ??? ?clearInterval(this.oUl.timer);//清除敵人整體移動的定時器
?? ??? ??? ?this.oParent.removeChild(this.oUl);
?? ??? ?}
?? ??? ?
?? ??? ?document.title='第'+(iNow+1)+'關(guān)';
?? ?
?? ??? ?var gk=this.gk[iNow];//得到關(guān)卡
?? ??? ?var arr=[];//用來存儲ul li蜜蜂的top、left值
?? ??? ?var oUl=document.createElement('ul');
?? ??? ?oUl.id='bee';
?? ??? ?oUl.style.width=gk.colNum*40+'px';
?? ??? ?this.oParent.appendChild(oUl);
?? ??? ?oUl.style.left=(this.oParent.offsetWidth-oUl.offsetWidth)/2+'px';
?? ??? ?
?? ??? ?this.oUl=oUl;//讓oUl變成對象的屬性
?? ??? ?
?? ??? ?for(var i=0;i<gk.eMap.length;i++){//創(chuàng)建li小蜜蜂
?? ??? ??? ?var oLi=document.createElement('li');
?? ??? ??? ?oLi.className=this.oEnemy[gk.eMap[i]].style;
?? ??? ??? ?
?? ??? ??? ?oLi.blood=this.oEnemy[gk.eMap[i]].blood;
?? ??? ??? ?oLi.speed=this.oEnemy[gk.eMap[i]].speed;
?? ??? ??? ?oLi.score=this.oEnemy[gk.eMap[i]].score;
?? ??? ??? ?
?? ??? ??? ?oUl.appendChild(oLi);//每個蜜蜂填到ul中
?? ??? ?}
?? ??? ?this.aLi=oUl.getElementsByTagName('li');//將所有l(wèi)i小蜜蜂設(shè)置為全局的
?? ??? ?
?? ??? ?for(var i=0;i<this.aLi.length;i++){
?? ??? ??? ?arr.push([this.aLi[i].offsetLeft,this.aLi[i].offsetTop]);//arr[][]
?? ??? ?}
?? ??? ?
?? ??? ?//每個蜜蜂轉(zhuǎn)定位
?? ??? ?for(var i=0;i<this.aLi.length;i++){
?? ??? ??? ?//創(chuàng)建蜜蜂存好每個蜜蜂的left、top值后再用JS把ul li蜜蜂原來的浮動改為絕對定位,這樣避免了:子彈碰到一個蜜蜂,該蜜蜂消失,而該蜜蜂的相鄰蜜蜂因為浮動而來補位又和子彈碰撞,又消失
?? ??? ??? ?this.aLi[i].style.position='absolute';
?? ??? ??? ?this.aLi[i].style.left=arr[i][0]+'px';
?? ??? ??? ?this.aLi[i].style.top=arr[i][1]+'px';
?? ??? ?}
?? ??? ?
?? ??? ?this.runEnemy(gk);//敵人整體移動,創(chuàng)建好敵人后就觸發(fā)
?? ?},
?? ?
?? ?runEnemy:function(gk){//敵人整體移動
?? ??? ?var This=this;
?? ??? ?
?? ??? ?var L=0;
?? ??? ?var R=this.oParent.offsetWidth-this.oUl.offsetWidth;//父層的寬減去ul(敵人整體)的寬就是ul能到達的最大值
?? ??? ?
?? ??? ?this.oUl.timer=setInterval(function(){//定時器賦給此timer方便在通關(guān)后銷毀
?? ??? ??? ?
?? ??? ??? ?if(This.oUl.offsetLeft>R){
?? ??? ??? ??? ?gk.iSpeedX*=-1;//反向移動
?? ??? ??? ??? ?This.oUl.style.top=This.oUl.offsetTop+gk.iSpeedY+'px';
?? ??? ??? ?}else if(This.oUl.offsetLeft<L){
?? ??? ??? ??? ?gk.iSpeedX*=-1;
?? ??? ??? ??? ?This.oUl.style.top=This.oUl.offsetTop+gk.iSpeedY+'px';
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ??? ?This.oUl.style.left=This.oUl.offsetLeft+gk.iSpeedX+'px';//移動速度
?? ??? ?},200);//200毫秒移動一次
?? ??? ?
?? ??? ?setInterval(function(){
?? ??? ??? ?This.oneMove();
?? ??? ?},gk.times);//每隔一段時間就有一個蜜蜂移動
?? ?},
?? ?
?? ?oneMove:function(){//單兵作戰(zhàn):一個小蜜蜂移動
?? ??? ?var nowLi=this.aLi[Math.floor(Math.random()*this.aLi.length-1)];//范圍內(nèi)隨機數(shù)取整用來做當(dāng)前小蜜蜂的腳標(biāo)
?? ??? ?var This=this;
?? ??? ?
?? ??? ?nowLi.timer=setInterval(function(){//小蜜蜂被刪掉了但是此定時器還在就會出問題,所以這里賦給timer,在子彈刪掉蜜蜂前可清除此定時器
?? ??? ??? ?var a=(This.oA.offsetLeft+This.oA.offsetWidth/2)-(nowLi.offsetLeft+nowLi.parentNode.offsetLeft+This.oA.offsetWidth/2);//蜜蜂和飛機中心點的水平距離
?? ??? ??? ?var b=(This.oA.offsetTop+This.oA.offsetHeight/2)-(nowLi.offsetTop+nowLi.parentNode.offsetTop+This.oA.offsetHeight/2);//蜜蜂和飛機中心點的垂直距離
?? ??? ??? ?var c=Math.sqrt(a*a+b*b);//這是實際距離
?? ??? ??? ?
?? ??? ??? ?var iSX=nowLi.speed*a/c;//蜜蜂向飛機靠近的水平速度
?? ??? ??? ?var iSY=nowLi.speed*b/c;//蜜蜂向飛機靠近的垂直速度
?? ??? ??? ?
?? ??? ??? ?nowLi.style.left=nowLi.offsetLeft+iSX+'px';
?? ??? ??? ?nowLi.style.top=nowLi.offsetTop+iSY+'px';
?? ??? ??? ?
?? ??? ??? ?if(This.pz(This.oA,nowLi)){
?? ??? ??? ??? ?alert('游戲結(jié)束');
?? ??? ??? ??? ?window.location.reload();
?? ??? ??? ?}
?? ??? ?},30);
?? ?},
?? ?
?? ?createAir:function(){//創(chuàng)建飛機
?? ??? ?var oA=document.createElement('div');
?? ??? ?oA.className=this.air.style;
?? ??? ?
?? ??? ?this.oA=oA;
?? ??? ?
?? ??? ?this.oParent.appendChild(oA);
?? ??? ?oA.style.left=(this.oParent.offsetWidth-oA.offsetWidth)/2+'px';
?? ??? ?oA.style.top=(this.oParent.offsetHeight-oA.offsetHeight)+'px';
?? ??? ?this.bindAir();
?? ?},
?? ?
?? ?bindAir:function(){//操作飛機
?? ??? ?
?? ??? ?var timer=null;
?? ??? ?var iNum=0;
?? ??? ?var This=this;
?? ??? ?
?? ??? ?document.οnkeydοwn=function(ev){//按下按鍵時的處理
?? ??? ??? ?var ev=ev||window.event;
?? ??? ??? ?
?? ??? ??? ?if(!timer){//為了定時器保持只有一份,不會有累加效果
?? ??? ??? ??? ?timer=setInterval(show,30);//把飛機左右移動的定時器賦給timer方便銷毀
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ??? ?if(ev.keyCode==37){//左鍵
?? ??? ??? ??? ?iNum=1;
?? ??? ??? ?}else if(ev.keyCode==39){//右鍵
?? ??? ??? ??? ?iNum=2;
?? ??? ??? ?}
?? ??? ?};
?? ??? ?
?? ??? ?document.οnkeyup=function(ev){//松開按鍵后的處理
?? ??? ??? ?var ev=ev||window.event;
?? ??? ??? ?if(ev.keyCode==37||ev.keyCode==39){//若松開左右鍵則取消對應(yīng)的移動功能
?? ??? ??? ??? ?clearInterval(timer);
?? ??? ??? ??? ?timer=null;
?? ??? ??? ??? ?iNum=0;
?? ??? ??? ?}
?? ??? ??? ?if(ev.keyCode == 32){//空格
?? ??? ??? ??? ?This.createBullet();//創(chuàng)建子彈
?? ??? ??? ?}
?? ??? ?}
?? ??? ?
?? ??? ?function show(){
?? ??? ??? ?if(iNum == 1){
?? ??? ??? ??? ?if(This.oA.style.left == -3 + 'px'){//防止飛機移出游戲窗
?? ??? ??? ??? ??? ?return false;
?? ??? ??? ??? ?}else{
?? ??? ??? ??? ??? ?This.oA.style.left = This.oA.offsetLeft - 10 + 'px';
?? ??? ??? ??? ?}
?? ??? ??? ?}else if(iNum == 2){
?? ??? ??? ??? ?if(This.oA.style.left == 757 + 'px'){//防止飛機移出游戲窗
?? ??? ??? ??? ??? ?return false;
?? ??? ??? ??? ?}else{
?? ??? ??? ??? ??? ?This.oA.style.left = This.oA.offsetLeft + 10 + 'px';
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ?},
?? ?
?? ?createBullet:function(){
?? ??? ??? ?//子彈的left值=飛機的left值+飛機本身寬度的一半
?? ??? ??? ?//子彈的top值=飛機的top值-子彈本身的高度
?? ??? ??? ?var oB=document.createElement('div');
?? ??? ??? ?oB.className=this.air.bulletStyle;
?? ??? ??? ?this.oParent.appendChild(oB);
?? ??? ??? ?oB.style.left=this.oA.offsetLeft+this.oA.offsetWidth/2+'px';
?? ??? ??? ?oB.style.top=this.oA.offsetTop-10+'px';
?? ??? ??? ?
?? ??? ??? ?this.runBullet(oB);
?? ?},
?? ?
?? ?runBullet:function(oB){//子彈運動
?? ??? ?var This=this;
?? ??? ?
?? ??? ?oB.timer=setInterval(function(){
?? ??? ??? ?
?? ??? ??? ?if(oB.offsetTop<-10){//當(dāng)子彈飛出游戲窗就銷毀該子彈,謹(jǐn)防子彈一直飛,導(dǎo)致子彈過多,頁面元素過多影響性能
?? ??? ??? ??? ?clearInterval(oB.timer);
?? ??? ??? ??? ?This.oParent.removeChild(oB);
?? ??? ??? ?}else{
?? ??? ??? ??? ?oB.style.top=oB.offsetTop-10+'px';
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ??? ?for(var i=0;i<This.aLi.length;i++){
?? ??? ??? ??? ?if(This.pz(oB,This.aLi[i])){//如果子彈和小蜜蜂碰撞
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?//蜜蜂的血量判斷
?? ??? ??? ??? ??? ?if(This.aLi[i].blood==1){
?? ??? ??? ??? ??? ??? ?clearInterval(This.aLi[i].timer);//清除蜜蜂落下來的定時器
?? ??? ??? ??? ??? ??? ?This.oSNum.innerHTML=parseInt(This.oSNum.innerHTML)+This.aLi[i].score;
?? ??? ??? ??? ??? ??? ?This.oUl.removeChild(This.aLi[i]);//刪掉蜜蜂
?? ??? ??? ??? ??? ?}else{
?? ??? ??? ??? ??? ??? ?This.aLi[i].blood--;
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?clearInterval(oB.timer);//先把定時器關(guān)閉再刪子彈,這樣可提高性能
?? ??? ??? ??? ??? ?This.oParent.removeChild(oB);//刪掉碰撞的子彈
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ??? ?if(!This.aLi.length){//如果敵人被打完(li的數(shù)組長度為0),就進入下一關(guān)
?? ??? ??? ??? ?This.createEnemy(1);
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ?},30);
?? ?},
?? ?
?? ?pz:function(obj1,obj2){//封裝好碰撞檢測,可實現(xiàn)多對多碰撞檢測
?? ??? ?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+obj2.parentNode.offsetLeft;;
?? ??? ?var R2=obj2.offsetLeft+obj2.offsetWidth+obj2.parentNode.offsetLeft;
?? ??? ?var T2=obj2.offsetTop+obj2.parentNode.offsetTop;
?? ??? ?var B2=obj2.offsetTop+obj2.offsetHeight+obj2.parentNode.offsetTop;
?? ??? ?
?? ??? ?if(R1<L2||L1>R2||B1<T2||T1>B2){
?? ??? ??? ?return false;
?? ??? ?}else{
?? ??? ??? ?return true;
?? ??? ?}
?? ?}
};
</script>
</head>
<body>
<div id="div1">
?? ?<div id="gameName">飛機大戰(zhàn)小蜜蜂</div>
?? ?<div id="gameBtn">開始游戲</div>
??? <div id="gameAuthor">@copyright 2015 | 免責(zé)聲明:本游戲Johnny出品,如有雷同純屬巧合!</div>
</div>
</body>
</html>
總結(jié)
以上是生活随笔為你收集整理的JS原生编写飞机大战小蜜蜂游戏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小猿日记 - 程序猿的日常日记(3)
- 下一篇: JAVA设计模式笔记(简单工厂模式)