1,先说下,javascript设计模式之单体模式
单体是一个用来划分命名空间并将一批相关的属性和方法组织在一起的对象,如果他可以被实例化,那么他只能被实例化一次。
单体模式是javascript里面最基本但是也是最有用的也是最常用的模式之一。
单体模式的特点:
1,可以用来划分命名空间,从而清除全局变量所带来的危险。
2,利用分支技术来封装浏览器直接的差异。
3,可以把代码组织的更为一体,便于阅读和维护。
单体模式的思路是:
一个类能返回一个对象的引用(并且永远是同一个)和一个获得该实例的方法(静态方法,通常使用getInstance名称)。那么当我们调用这个方法时,如果类持有的引用不为空就返回该引用,否者就创建该类的实例,并且将实例引用赋值给该类保持的那个引用再返回。同时将该类的构造函数定义为私有方法,避免其他函数使用该构造函数来实例化对象,只通过该类的静态方法来得到该类的唯一实例。
下面是使用单体模式写的,飞机大战小蜜蜂的游戏。
<!DOCTYPE html>
<html>
<head>
<title>飞机大战小蜜蜂游戏</title>
</head>
<style>
*{ margin:0; padding:0;}
li{ list-style:none;}
#div1{ width:800px; height:600px; overflow:hidden; background:black; margin:20px auto; position:relative;}
#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; font-size:20px;}
#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>
//单体的写法:一个大的json 加入了命名空间(用点来分割)的感觉
window.onload = function(){
var oGameBtn = document.getElementById('gameBtn');
oGameBtn.onclick = function(){
this.style.display = "none";
Game.init("div1");
};
};
/*
*
*/
var Game = {
/*
*小蜜蜂的数据oEnemy
*style:样式
*blood:掉血
*speed:飞行的速度
*score:积分
*/
oEnemy : {
e1 :{style:'enemy1',blood:1,speed:5,score:1},
e2 :{style:'enemy2',blood:2,speed:7,score:2},
e3 :{style:'enemy3',blood:3,speed:10,score:3}
},
/*
*关卡
*colNum:一行多少个
*iSpeedX:X抽速度
*iSpeedY:Y皱速度
*times:飞下来的时间
*/
gk : [
{
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
},
{
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
}
],
/*
*飞机的数据
*style:飞机的样式
*bulletStyle:子弹的样式
*/
air : {
style : 'air1',
bulletStyle : 'bullet'
},
/*
*初始化
*/
init : function(id){
this.oParent = document.getElementById(id);
this.createScore();
this.createEnemy(0);
this.createAir();
},
createScore : function(){//创建积分
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){//创建小蜜蜂
var gk = this.gk[iNow];
var oUl = document.createElement('ul');
var arr = [];
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;
for(var i=0; i<gk.eMap.length;i++){
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);
}
this.aLi = oUl.getElementsByTagName('li');
for(var i=0; i<this.aLi.length;i++){
arr.push([this.aLi[i].offsetLeft, this.aLi[i].offsetTop]);
}
for(var i=0; i<this.aLi.length;i++){
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);
},
runEnemy : function(gk){//小蜜蜂的运动
var This = this;
var L = 0;
var R = this.oParent.offsetWidth - this.oUl.offsetWidth;
setInterval(function(){
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);
},
createAir : function(){//创建飞机
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.onkeydown = function(ev){
var ev = ev || window.event;
if(!timer){
timer = setInterval(show,30);
}
if(ev.keyCode == 37){//左键
iNum = 1;
}else if(ev.keyCode == 39){//右键
iNum = 2;
}
};
document.onkeyup = function(ev){//抬起发子弹
var ev = ev || window.event;
clearInterval(timer);
timer = null;
iNum = 0;
if(ev.keyCode == 32){
This.createBullet();
}
};
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(){//创建子弹
var oB = document.createElement('div');
oB.className = this.air.bulletStyle;
this.oParent.appendChild( oB );
oB.style.left = this.oA.offsetLeft + this.oA.offsetWidth/2 - 1 + '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){
clearInterval(oB.timer);
This.oParent.removeChild( oB );
}else{
oB.style.top = oB.offsetTop - 10 + 'px';
}
for(var i=0;This.aLi.length;i++){
if( This.pz(oB,This.aLi[i])){
if(This.aLi[i].blood == 1){
This.oUl.removeChild(This.aLi[i]);
}else{
This.aLi[i].blood--;
}
clearInterval(oB.timer);
This.oParent.removeChild(oB);
}
}
},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;
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 || T1>B2 || B1<T2 ){
return false;
}else{
return true;
}
}
};
</script>
<body>
<div id="div1">
<div id="gameBtn">开始游戏</div>
</div>
</body>
</html>
还没有完成,,但是目前的是可以用的,,可以打蜜蜂,,未完成:积分的累计,蜜蜂攻击飞机。等。。。
未完待续,,,,,
下面是完成的
<!DOCTYPE html>
<html>
<head>
<title>飞机大战小蜜蜂游戏</title>
</head>
<style>
*{ margin:0; padding:0;}
li{ list-style:none;}
#div1{ width:800px; height:600px; overflow:hidden; background:black; margin:20px auto; position:relative;}
#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; font-size:20px;}
#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>
//单体的写法:一个大的json 加入了命名空间(用点来分割)的感觉
window.onload = function(){
var oGameBtn = document.getElementById('gameBtn');
oGameBtn.onclick = function(){
this.style.display = "none";
Game.init("div1");
};
};
/*
*
*/
var Game = {
/*
*小蜜蜂的数据oEnemy
*style:样式
*blood:掉血
*speed:飞行的速度
*score:积分
*/
oEnemy : {
e1 :{style:'enemy1',blood:1,speed:5,score:1},
e2 :{style:'enemy2',blood:2,speed:7,score:2},
e3 :{style:'enemy3',blood:3,speed:10,score:3}
},
/*
*关卡
*colNum:一行多少个
*iSpeedX:X抽速度
*iSpeedY:Y皱速度
*times:飞下来的时间
*/
gk : [
{
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
},
{
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
}
],
/*
*飞机的数据
*style:飞机的样式
*bulletStyle:子弹的样式
*/
air : {
style : 'air1',
bulletStyle : 'bullet'
},
/*
*初始化
*/
init : function(id){
this.oParent = document.getElementById(id);
this.createScore();
this.createEnemy(0);
this.createAir();
},
createScore : function(){//创建积分
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){//创建小蜜蜂
if(this.oUl){
clearInterval(this.oUl.timer);
this.oParent.removeChild(this.oUl);
}
document.title = '第'+(iNow+1)+'关';
var gk = this.gk[iNow];
var oUl = document.createElement('ul');
var arr = [];
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;
for(var i=0; i<gk.eMap.length;i++){
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);
}
this.aLi = oUl.getElementsByTagName('li');
for(var i=0; i<this.aLi.length;i++){
arr.push([this.aLi[i].offsetLeft, this.aLi[i].offsetTop]);
}
for(var i=0; i<this.aLi.length;i++){
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);
},
runEnemy : function(gk){//小蜜蜂的运动
var This = this;
var L = 0;
var R = this.oParent.offsetWidth - this.oUl.offsetWidth;
this.oUl.timer = setInterval(function(){
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);
setInterval(function(){
This.oneMove();
},gk.times);
},
oneMove : function(){//单兵作战
var nowLi = this.aLi[Math.floor(Math.random()*this.aLi.length)];
var This = this;
nowLi.timer = setInterval(function(){
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('游戏结束');
window.location.reload();
}
},30);
},
createAir : function(){//创建飞机
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.onkeydown = function(ev){
var ev = ev || window.event;
if(!timer){
timer = setInterval(show,30);
}
if(ev.keyCode == 37){//左键
iNum = 1;
}else if(ev.keyCode == 39){//右键
iNum = 2;
}
};
document.onkeyup = function(ev){//抬起发子弹
var ev = ev || window.event;
clearInterval(timer);
timer = null;
iNum = 0;
if(ev.keyCode == 32){
This.createBullet();
}
};
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(){//创建子弹
var oB = document.createElement('div');
oB.className = this.air.bulletStyle;
this.oParent.appendChild( oB );
oB.style.left = this.oA.offsetLeft + this.oA.offsetWidth/2 - 1 + '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){
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);
This.oParent.removeChild(oB);
}
}
if( !This.aLi.length ){
This.createEnemy(1);
}
},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;
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 || T1>B2 || B1<T2 ){
return false;
}else{
return true;
}
}
};
</script>
<body>
<div id="div1">
<div id="gameBtn">开始游戏</div>
</div>
</body>
</html>