首頁 > web前端 > H5教程 > 主體

HTML5實現圈泡泡遊戲的程式碼分享

黄舟
發布: 2017-03-24 15:29:40
原創
3268 人瀏覽過

功能說明:

  在一分鐘內,使用滑鼠按左鍵,在畫布上圈泡泡,其中泡泡的分數分別為10(白)、20(淺藍)、30(黃)、-10(紅)、-20(綠)、-30(深藍)分,可以一次圈多個泡泡,倒數結束即計算總分值,遊戲基於cnGameJS

效果預覽:

 HTML5實現圈泡泡遊戲的程式碼分享

#實現分析: 

## 先每個小球定義一個ball類,由於小球需要使用圖片,並且有一定的尺寸和運動,所以使該類

繼承cnGameJS的sprite類。 ball類別除了擁有x,y座標外,還擁有一個z座標,該座標用於使小球具有離玩家遠近的視覺差。

/*    小球对象    */
var Ball=function(opt){
    this.parent.call(this,opt);
    this.oriPos=[this.x+this.width/2,this.y+this.height/2];
    this.oriSize=opt.size;
    this.z=opt.z||0;
    this.score=opt.score||0;
    this.oriSpeedZ=4+Math.random()*4;
    this.scale=1;
    this.resetXY();
    
}
cg.core.inherit(Ball,Sprite);
登入後複製

  之後我們為小球添加resetXY方法,該方法根據小球的z坐標,改變小球的位置以及尺寸,使小球有遠近的視覺差。首先根據z計算縮放比scale,然後根據scale調整x,y和width,height,另外我們使小球z大於1000時,小球消失,這樣就避免了小球過大而佔據整個屏幕。

cg.core.extendProto(Ball,{
    disappear:function(){//小球被选中消失
        list.remove(this);
    },
    resetXY:function(){//根据Z改变x,y的位置和尺寸
        var oriX=this.oriPos[0];
        var oriY=this.oriPos[1];
        var oriSize=this.oriSize;
        this.scale=((center[0]+this.z)/center[0]);//相对于现时的scale        
        this.x=(oriX-center[0])*this.scale+center[0];
        this.y=(oriY-center[1])*this.scale+center[1];
        this.height=this.width=this.oriSize*this.scale;
        this.speedZ=this.oriSpeedZ*this.scale;
        if(this.z>1000){
            this.disappear();
        }
    },
    update:function(){
        this.parent.prototype.update.call(this);
        this.resetXY();
    }
});
登入後複製

  之後,為了管理多個小球,可以增加一個小球管理器。管理器負責動態改變小球到玩家的距離以及使小球在畫布隨機的位置出現:

/*    小球对象管理器    */
var ballsManager={
    createDuration:200,
    ballSize:30,
    lastCreateTime:Date.now(),
    /*    随机生成小球    */
    createRandomBalls:function(num){
        var now=Date.now();
        if(now-this.lastCreateTime>this.createDuration){
            for(var i=0;i<num;i++){
                var x=Math.random()* cg.width;
                var y=Math.random()* cg.height;
                var randomKind=ballKinds[Math.floor(Math.random()*6)];//随机获得的小球种类和分值    
                var newBall=new Ball({x:x,y:y,size:this.ballSize,z:-280,score:randomKind[1]});
                newBall.setCurrentImage(srcObj[randomKind[0]]);//设置图片
                list.add(newBall);
            }
            this.lastCreateTime=now;
        }
    },
    /*    改变小球位置    */
    changeBallsPos:function(){
        var ballsArr=list.get(function(elem){
            return elem instanceof Ball;                               
        });
        for(var i=0,len=ballsArr.length;i<len;i++){
            var ball=ballsArr[i];
            ball.z+=ball.speedZ;    
        }
    }
}
登入後複製

  關於小球管理就介紹到這裡,之後主要介紹怎樣實現滑鼠的圈選。

  如果我們在每次幀

更新時,根據滑鼠現時的位置以及上一次的位置繪製一條線段,那麼滑鼠的移動軌跡就可以被一條曲線表示出來,該曲線由每次繪製的線段組成,因此我們也可以說該曲線是一條由多條線段首尾相連組成的曲線。因此我們可以先實作一個線段類別:

/*    直线    */
        var line=function(options){
            if (!(this instanceof arguments.callee)) {
                return new arguments.callee(options);
            }
            this.init(options);
        }
    
        
        line.prototype = {
            /**
            *初始化
            **/
            init: function(options) {    
                this.start=[0,0];
                this.end=[0,0];    
                this.style="red";
                this.lineWidth=1;
                this.context=cg.context;
                options = options || {};
                cg.core.extend(this,options);
            },
登入後複製

  該類別保存線段的起始點座標和結束點座標,以及寬度,樣式等。

  之後需要考慮的就是怎麼實現圈選了。當我們用滑鼠畫出一個圈時,每條小線段就組成了一個閉合的多邊形,這時我們就可以說滑鼠圈出了一個閉合區域,之後就可以進一步計算哪些小球在該區域裡面。

  但是怎麼判斷滑鼠是否圈出了一個閉合區域呢?這裡使用的方法是:

遍歷每一條線段,從該線段的下一條再下一條線段開始遍歷餘下的線段,判斷它們中是否有線段和開始的那條線段相交,如果相交,則證明曲線閉合了。 注意這裡從線段的下條再下條線段開始遍歷是為了跳過線段首尾相連的情況。 (例如,第一條線段肯定和第二條線段相交,因此從第三條線段開始判斷,跳過相鄰線段收尾相交的情況),代碼如下:

/*    返回轨迹是否闭合    */
    var isClose=function(lines){    
        var hasClose=false;
        for(var i=0;i<lines.length;i++){
            var l1=lines[i];
            for(var j=i+2;j<lines.length;j++){
                var l2=lines[j];
                if(l2){
                    var point=l1.isCross(l2);//交点坐标
                    if(point){//非连接的相交
                        resetLineSegs(lines,i,j,point);
                        hasClosed=true;
                        return true;
                    }
                }
            }
        }
        
        return false;
    };
登入後複製

  isCross方法返回線段交點的座標,我們獲得該座標後,還需要把多邊形修正成為真正的多邊形,因為用滑鼠圈出來的多邊形並不是一個真正的多邊形,它的開始和結束部分很可能會有突出的地方,如下圖:

  我們假設滑鼠從綠色部分開始圈一個圈,到藍色部分結束。

這樣的話軌跡就不是一個嚴格的多邊形,因為它多出了藍色和綠色的部分。 因此我們需要對圈出來的多邊形進行一個修正操作,使其變成一個真正的閉合多邊形:

    /*    重置线段    */
    var resetLineSegs=function(lines,i,j,point){
        lines[i].end[0]=point[0];
        lines[i].end[1]=point[1];
        lines[i+1].start[0]=point[0];
        lines[i+1].start[1]=point[1];
        
        lines[j].start[0]=point[0];
        lines[j].start[1]=point[1];
    
        lines[j-1].end[0]=point[0];
        lines[j-1].end[1]=point[1];        for(var m=i+1;m<j;m++){
            closedLineSegsArr.push(lines[m]);
        }    
    }
登入後複製

  當我們判斷到兩條線段相交後,可以獲取到這兩條線段的

索引,這裡分別為i和j(i陣列中,我們後面就要使用這些邊,建構多邊形物件了。

       for(var i=0,len=closedLineSegsArr.length;i<len;i++){
                            pointsArr.push([closedLineSegsArr[i].start[0],closedLineSegsArr[i].start[1]]);    
                        }
                        polygon=new Polygon({pointsArr:pointsArr,style:"rgba(241,46,8,0.5)"});
登入後複製

  透過多邊形的邊對象的數組,可以獲取到多邊形每個頂點的座標,並根據這些座標構造多邊形對象,之後的工作就是判斷小球是否在多邊形裡面了。

  判断小球是否在多边形里,可以转化为判断小球的中点是否在多边形里,这里使用的方法叫射线法,意思是从一点向左发射出一条射线,如果射线和多边形有奇数个交点,则证明点在多边形内部。根据该定理实现的isInside方法如下:

/**
            *判断某点是否在多边形内(射线法)
            **/
            isInside:function(point){
                var lines=this.getLineSegs();

                var count=0;//相交的边的数量
                var lLine=new Line({start:[point[0],point[1]],end:[-9999,point[1]]});//左射线
                var crossPointArr=[];//相交的点的数组
                for(var i=0,len=lines.length;i<len;i++){
                    var crossPoint=lLine.isCross(lines[i]);
                    if(crossPoint){
                        for(var j=0,len2=crossPointArr.length;j<len2;j++){
                            //如果交点和之前的交点相同,即表明交点为多边形的顶点
                            if(crossPointArr[j][0]==crossPoint[0]&&crossPointArr[j][1]==crossPoint[1]){
                                break;    
                            }
                            
                        }
                        if(j==len2){
                            crossPointArr.push(crossPoint);    
                            count++;
                        }
                        
                    }
                }
        
                if(count%2==0){//不包含
                    return false;
                }
                return true;//包含
            },
登入後複製

  另外需要注意的是,由于射线与多边形相交交点个数是通过射线和多边形的每条边是否相交来判断,所以如果射线通过多边形的顶点,我们得出的结果就是相交了两次(通过顶点使射线与两条边都有相交)。因此我们需要记录判断过的交点,每次判断时检查该交点是否已经出现过,若出现过则不纳入计数,这样就基本实现了判断小球是否在鼠标圈选的多边形区域内。

   

以上是HTML5實現圈泡泡遊戲的程式碼分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板