HTML5学习+javascript学习:打飞机游戏Service层Control层+源码

2.Service层 如前所述,Service层是Control层与Model层之间桥接的一层,它拥有所有要在屏幕上显示的实体(除了背景)的引用

 

我们知道,当游戏运行时,随时都可能发生碰撞,随时都可能发生飞行物的消失。而我们要想判定飞行物的状态,就必须把所有的飞行物都遍历一遍方可,那么我们要把所有的没消失的飞行物都放在一起。但是如果这些飞行物放在一起都放在control层里,control层会显得很庞大,又要处理飞机的销毁,又要给返回图片。然后如果我们想通过服务器根据条件获得新的飞机,我们是不是又要在control层中添加事件,添加代码。那control层会显得很乱。所以,保险起见,我们在control层和model层之间桥接了一个service层,它就只负责处理飞行物销毁和子弹发射等已有的事件,提供一些可供control层访问的接口(事件其实就是方法),并把图像返回到control层去,将来如果我们从服务器得到更多的飞机要来,那就把这些飞机给传到control层,然后由control层来调用service的接口就好啦。也就是把control层分成两部分,一部分处理业务,一部分处理显示。

我们已经介绍了Model层,我们知道model层的方法是由service来调用的,Model层的所有方法(除了访问其私有变量的方法外)均会返回一个array,而调用方法返回的这个array是如何被service抓取又是如何被service处理的呢?我们又如何来设计这个service层呢?

首先要有一个飞行物的数组来存放所有的飞行物,同时要有一个数组来缓存事件,另外一个数组来缓存图片。然后要有一个接口的方法update,之后要有一个draw方法来返回给control层更新图像的图片和坐标,还要有一些事件来处理Model返回的事件,其流程为:

update:1.遍历model,先判断model是否有可能发生碰撞,如果有(即碰撞体积有重合的部分),那么就调用model的碰撞方法,将返回的结果缓存到注册表中,然后调用draw方法(因为有可能新增飞行物,飞行物消失等改变飞行物数组的事件出现因此不可以一并处理,设想这样:如果一个飞行物已经消失了,还调用它的移动方法是没有意义的 )2.遍历model调用它们的移动方法,更新它们的坐标,将返回的内容缓存到注册表中(因为如果出了边界也有可能出现消失,发射炮弹也有可能新增飞行物)。

 

draw:将注册表的事件逐个取出,执行,并返回一个图像的数组

下面给出service的代码

service.js

 

/*
*后台控制层类,完成model层和view层的控制和数据传递服务,它通过不停地调用自己的私有数组的特有方法,收集这些方法返回的
*事件,放到注册表中,最后一并处理:调注册表中的事件,事件会更新自己的私有数组内容,并将欲传递给view层显示的图片信息缓存。
*/
var service=function(){
    var registry=[];//存放注册时间的列表,是model层返回的内容
    var bulletNum=0;//只是暂时存储子弹的数目。
    var flies=[];//飞行物的列表,私有数组,遍历访问其方法,返回的事件就存储在registry中
    var images=[];//用于缓存显示图片的数组:{img,x,y}
    var is_array = function(value) {//判断值是否为数组
                    return value &&
                typeof value === 'object' &&
                value.constructor === Array;

        }

    
    
    function registEvent(regist){//注册事件,参数为事件数组/事件对象
    if(regist) {
        // 如果是数组,则调用concat方法把方法名和参数推进注册表中
        if(is_array(regist)){
        
        registry=registry.concat(regist);
        
        }
        else{
        //如果这个方法名和数组返回了不可以识别的值,则什么都不做否则用push方法压入注册表。
        if(typeof regist!=='undefined'){
        registry.push(regist);
        }
        }
        
    }
    }
    function peng(fly1,fly2){//碰撞判断
        //sqr1,sqr2表示碰撞体的左上角坐标和右下角坐标。即,从图片的中心开始,上下左右均为碰撞边长的1/2
        var sqr1={
        x1:fly1.x()+fly1.width()/2-fly1.cflctSqr()/2,
        x2:fly1.x()+fly1.cflctSqr()/2+fly1.width()/2,
        y1:fly1.y()+fly1.height()/2-fly1.cflctSqr()/2,
        y2:fly1.y()+fly1.cflctSqr()/2+fly1.height()/2
        };
        var sqr2={
        x1:fly2.x()+fly2.width()/2-fly2.cflctSqr()/2,
        x2:fly2.x()+fly2.cflctSqr()/2+fly2.width()/2,
        y1:fly2.y()+fly2.height()/2-fly2.cflctSqr()/2,
        y2:fly2.y()+fly1.cflctSqr()+fly2.height()/2
        };
        var x1=sqr1.x1<sqr2.x1?sqr1.x1:sqr2.x1;
        var x2=sqr1.x2>sqr2.x2?sqr1.x2:sqr2.x2;
        var y1=sqr1.y1>sqr2.y1?sqr1.y1:sqr2.y1;
        var y2=sqr1.y2<sqr2.y2?sqr1.y2:sqr2.y2;
        var sqr=fly1.cflctSqr()+fly2.cflctSqr();//是碰撞边长之和
        if((x2-x1)<sqr&&(y1-y2)<sqr){//如果最右边的横坐标减去最左边的横坐标小于两个飞行物碰撞边长之和,而且纵坐标也如此,那么碰撞成立。
        //if((typeof fly1.isbullet !== 'undefined' && typeof fly2.isbullet==='undefined')||(typeof fly2.isbullet !== 'undefined' && typeof fly1.isbullet==='undefined')){
        //var ale="sqr1:x1:"+sqr1.x1+"y1:"+sqr1.y1+"x2:"+sqr1.x2+"y2:"+sqr1.y2+"\n";
        //ale+="fly1:"+"x:"+fly1.x()+"y:"+fly1.y()+"width:"+fly1.width();
        //alert(ale);
        //}
        return true;
        }
        
        return false;
    }
    return {//上面的都是私有方法和变量,下面是返回值。
        total:function(){//求出飞行物的总数,在添加新的飞行物时会用到这个函数。
            return flies.length;
        },
        spliceflies:function(ndex){//删除一个对应序列号的飞行物,并更新飞行物数组中被改变下表的元素的序号。
                flies.splice(ndex,1);
                var i;
            for(i=ndex;i<flies.length;i++)
            {
                flies[i].setIndex(i);//从删除的那个起,数组元素的序列号均与数组下标保持一致
            }
        },
        conflict:function(){//判断是否有碰撞的必要,并检测是否碰撞成功
        var length=flies.length;//飞行物的个数
        var i=0;//遍历被碰者
        var j=0;//遍历碰撞发起者确保飞行物中所有的元素均两两配过对

        if(length>=2){//小于2不会发生碰撞
        for(i=0;i<length;i+=1){
        for(j=i+1;j<length;j+=1){//自己也不会跟自己碰撞,自己之前的已经判定过了。
            if(flies[i].target() !== flies[j].target()){//如果目标不同,就是敌人,就有‘血拼’或者拼血的必要
                if(peng(flies[i],flies[j])){//判断它们是否确实会发生碰撞
                    var regist=flies[i].onConflict(flies[j]);//调用飞行物的碰撞方法。
                    registEvent(regist);//把碰撞方法的返回事件压入注册表中
                    
            //    var q;
            //if(regist){
            //for(q=0;q<regist.length;q++){
            //    alert(regist[q].func+"  "+regist[q].params[0]+"  "+regist[q].params[1]);
            //}}
                    
                    
                }
                
            }
        }
        }
        
    }
    },
        update:function(){//更新,先看是否会发生碰撞,如果碰撞,让碰撞应该消失的消失,然后再更新仍存在于flies中的元素的位置。
        
        //registry= getSameNameAndInitParams(registry,'disapear','func');
        images.length=0;//图像清空
        this.conflict();//碰撞判断
        this.draw();//把注册表中的事件逐个取出,看是否需要更新flies数组(包括添加,删除)
        var length=flies.length;
        var i=0;
        for(i=0;i<length;i++){//然后根据每个飞行物的移动方法不同,分别改变各个飞行物的坐标
            var regist=flies[i].onMove();
            registEvent(regist);//注册移动后的事件,主要是把图片压到缓存区去。
            
        }
        },
        disapear:function(){//消失事件,碰撞成功导致飞行物损毁,就调用这个事件
            var len=arguments.length;
            var i;
            for(i=0;i<len;i+=1){
            //alert("splice");
            //flies.splice(arguments[i],1);
            this.spliceflies(arguments[i]);//把应该消失的飞行物从飞行物数组中移除。
            }
            //alert(flies.length);
        },
        explore:function(img,x,y){//爆炸,所有飞行物通过碰撞消失之前都会爆炸
            //alert("explore");
            this.drawimg(img,x,y);
        },
        drawimg:function(img,x,y){//把飞行物的图片压入缓存
            images.push({img:arguments[0],x:arguments[1],y:arguments[2]});
            
        },
        draw:function(){//就是把注册表中的事件一个个取出然后执行,最后返回缓存区的图像。
            
            //var q;
            //for(q=0;q<registry.length;q++){
            //    var s;
            //    if(registry[q].func !== 'drawimg'){
            //    for(s=0;s<registry[q].params.length;s+=1){alert(registry[q].func+"  "+registry[q].params[s]);
        //    }
        //}}
            var handle=registry.pop();
            
            while(typeof handle !== 'undefined'){
                
                var fuc=handle.func;
                
                    //alert(fuc);
                //if(fuc=='disapear'){
                //alert(flies.length);
                //}
                fuc=this[fuc];
                fuc.apply(this,handle.params);//第一个参数:上下文,第二个参数:传入函数的参数
                handle=registry.pop();
            }
            
            return images;
        },
        shoot:function(spec){//事件:射击,飞行物数组中压入选手的炮弹,这个选手的炮弹
            bullet=playerbullet(spec);
            bullet.setIndex(this.total());
            flies.push(bullet);
            bulletNum+=1;
        },
        reduceBulet:function(){//就是改变bulletNum这个变量的值。
            bulletNum-=1;
            //alert(bulletNum);
        },
        newfly:function(flier){//新飞行物
            //alert(flier.index());
            flier.setIndex(this.total());
            flies.push(flier);
        },
        newplane:function(){//这个以及下面的几个方法都是可有可无的,只是作为例子来看。
            var plane={
                x:Math.random()*CANVAS_WIDTH,
                y:Math.random()*CANVAS_HEIGHT,
                hp:10,
                index:flies.length,
                exploreImg:getImg("img/blasts3.png"),
                img:getImg("img/dplayerplane.png"),
                target:0,
                conflictSquare:20,
                speedX:5,
                speedY:5,
                movex:-1,
                movey:-1
                };
            var pl=fly(plane);
            flies.push(pl);
                
        },
        newenemy:function(){
            var plane={
                x:Math.random()*CANVAS_WIDTH,
                y:Math.random()*CANVAS_HEIGHT,
                hp:1,
                index:flies.length,
                exploreImg:getImg("img/blasts3.png"),
                img:getImg("img/amay.png"),
                target:1,
                conflictSquare:7,//碰撞体积
                speedX:5,
                speedY:5,
                movex:1,
                movey:-1
                };
            var pl=fly(plane);
            flies.push(pl);
        },
        newbullets:function(){
            var plane={
                x:Math.random()*CANVAS_WIDTH,
                y:Math.random()*CANVAS_HEIGHT,
                hp:1,
                index:flies.length,
                exploreImg:getImg("img/bossbullet2.png"),
                img:getImg("img/bossbullet3.png"),
                target:1,
                conflictSquare:2,//碰撞体积
                speedX:5,
                speedY:-5,
                movex:1,
                movey:-1
                };
            var pl=bullets(plane);
            
            
            flies.push(pl);
        }    
    };
};
service.js
33人参与, 0条评论 登录后显示评论回复

你需要登录后才能评论 登录/ 注册