用Egret仿制《围住神经猫》游戏

一、概括

        本文讲述用Egret配合Eui仿制一款之前的热门休闲游戏《围住神经猫》,这款游戏在当时1几年的时候挺火的,所以想着模仿下。

二、演示视频

三、开发过程

1.主界面

没什么ui交互,就一个开始游戏的触发。

2.场景加载

module ziyi{
    export class pot2 extends basicui{
        private allpot2_g:eui.Group;

        public constructor(cd?: any) {
            super();

            
        }


        private pots2:Array<Array<eui.Image>>;
        //子类初始化操作
        protected pre_init(): void {
            this.pots2=new Array<Array<eui.Image>>();
            for(let i:number=0;i<9;i++){
                
                var tmp:Array<eui.Image>=new Array<eui.Image>();
                this.pots2.push(tmp);
                for(let j:number=0;j<9;j++){
                    var tmpgroup =<eui.Group> this.allpot2_g.getElementAt(i);
                    var tmpimg=<eui.Image>tmpgroup.getElementAt(j);
                    this.pots2[i].push(tmpimg);
                    this.pots2[i][j].visible=true;
                    this.pots2[i][j].touchEnabled=false;
                }
            }
            
        }
        public visibleSet(i:number,j:number):void{
            this.pots2[i][j].visible=true;
        }
        public allVisibleSet():void{
            for(let i:number=0;i<9;i++){
                for(let j:number=0;j<9;j++){
                    this.pots2[i][j].visible=false;
                }
            }
        }
        public getpots2():Array<Array<eui.Image>>{
            return this.pots2;
        }

        public getall():eui.Group{
            return this.allpot2_g;
        }
    }
}

3.初始化场景

通过代码,添加好红灰两组二维组的格子,初始化红格子不可见。

private obstacles:Array<Array<number>>;
        private init():void{
            this.succeccText.text="";
            this.succbtn.visible=false;
            this.failbtn.visible=false;
            this.pabtn.visible=false;
            this.row=4;
            this.col=4;
            //this.loadTime();
            this.timer.start();         //开始计时
            for(let ii:number=0;ii<9;ii++){
                for(let jj:number=0;jj<9;jj++){
                    this.p1[ii][jj].touchEnabled=true;    //空格可按
                    this.p1[ii][jj].visible=true;
                }
            }
            this.cat.visible=true;
            this.obstacles=new Array<Array<number>>();
            for(let i:number=0;i<9;i++){
                var tmp:Array<number>=new Array<number>();
                this.obstacles.push(tmp);
                for(let j:number=0;j<9;j++){
                    this.obstacles[i].push(0);
                }
            }
            //在中心点方圆3步内(相对于矩阵而非真实排列)随机设置五个障碍点
            for(let i:number=0;i<5;i++){
                var x:number=Math.ceil(Math.random()*3-1);
                var y:number=Math.ceil(Math.random()*3-1);
                if(x==0&&y==0){
                    i=i-1;
                }else{
                    this.obstacles[4+x][4+y]=1;//障碍点设置之后更细障碍矩阵
                    this.p1[4+x][4+y].visible=false;//被设置障碍点的位置的灰色点不可视
                }
            }
            //在图中随机选取8个位置设置障碍点
            for(let i:number=0;i<8;i++){
                var x:number=Math.ceil(Math.random()*9-1);
                var y:number=Math.ceil(Math.random()*9-1);
                if((x==4&&y==4)||this.obstacles[x][y]==1)
                {
                    i=i-1;
                }
                else{
                    this.obstacles[x][y]=1;
                    this.p1[x][y].visible=false;
                }
            }
        }

然后通过代码随机生成13个障碍点,并开启可视,将障碍点作为数据标识“1”存入obstacles二维数组中。

4.路径记录(最短路径算法)--核心代码

 private initmap():void{//初始化map图,将边缘点设置为1,正常点设置为0,障碍点设置为-1
            for(let i:number=0;i<9;i++){
                for(let j:number=0;j<9;j++){
                    this.map[i][j]=0;
                }
            }
            this.changeflag=0;
            for(let i:number=0;i<9;i++){
                for(let j:number=0;j<9;j++){
                    if(this.isObstacle[i][j]==1)
                    {
                        this.map[i][j]=-1;
                    }
                }
            }
            for(let i:number=0;i<9;i++){
                if(this.isObstacle[i][0]==0){
                    this.map[i][0]=1;
                }
                if(this.isObstacle[i][8]==0){
                    this.map[i][8]=1;
                }
                if(this.isObstacle[8][i]==0){
                    this.map[8][i]=1;
                }
                if(this.isObstacle[0][i]==0){
                    this.map[0][i]=1;
                }
            }
        }
        public setcolandrow(i:number,j:number){
            this.row=i;
            this.col=j;
        }
        private recurshort():void{//回溯进行map最短距离的更新
            this.changeflag=0;
            for(let i:number=1;i<8;i++){
                for(let j:number=1;j<8;j++){                  
                    //上
                    if(this.map[i][j-1]>0&&(this.map[i][j-1]<this.map[i][j]-1||this.map[i][j]==0)){
                        this.changeflag=1;
                        this.map[i][j]=this.map[i][j-1]+1;
                    }
                    //下
                    if(this.map[i][j+1]>0&&(this.map[i][j+1]<this.map[i][j]-1||this.map[i][j]==0)){
                        this.changeflag=1;
                        this.map[i][j]=this.map[i][j+1]+1;
                    }
                    //左
                    if(this.map[i-1][j]>0&&(this.map[i-1][j]<this.map[i][j]-1||this.map[i][j]==0)){
                        this.changeflag=1;
                        this.map[i][j]=this.map[i-1][j]+1;
                    }
                    //右
                    if(this.map[i+1][j]>0&&(this.map[i+1][j]<this.map[i][j]-1||this.map[i][j]==0)){
                        this.changeflag=1;
                        this.map[i][j]=this.map[i+1][j]+1;
                    }
                    if(i%2==0){
                        //奇数行,左上(i-1,j-1)左下(i+1,j-1)
                        //左上
                        if(this.map[i-1][j-1]>0&&(this.map[i-1][j-1]<this.map[i][j]-1||this.map[i][j]==0)){
                            this.changeflag=1;
                            this.map[i][j]=this.map[i-1][j-1]+1;
                        }
                        //左下
                        if(this.map[i+1][j-1]>0&&(this.map[i+1][j-1]<this.map[i][j]-1||this.map[i][j]==0)){
                            this.changeflag=1;
                            this.map[i][j]=this.map[i+1][j-1]+1;
                        }
                    }else{
                        //偶数行,右上(i-1,j+1)右下(i+1,j+1)
                        //右上
                        if(this.map[i-1][j+1]>0&&(this.map[i-1][j+1]<this.map[i][j]-1||this.map[i][j]==0)){
                            this.changeflag=1;
                            this.map[i][j]=this.map[i-1][j+1]+1;
                        }
                        //右下
                        if(this.map[i+1][j+1]>0&&(this.map[i+1][j+1]<this.map[i][j]-1||this.map[i][j]==0)){
                            this.changeflag=1;
                            this.map[i][j]=this.map[i+1][j+1]+1;
                        }
                    }
                }
            }
            if(this.changeflag==1)
            {
                //changeflag为1说明距离矩阵改变,需要回溯
                this.recurshort();
            }
        }
        private move():number{
            //已经走在边界了,成功逃脱
            if(this.row==0||this.row==8||this.col==0||this.col==8){
                return -1;
            }
            var d1:number=this.map[this.row-1][this.col];//猫所处位置的上
            var d2:number=this.map[this.row+1][this.col];//猫所处位置的下
            var d3:number=this.map[this.row][this.col-1];//猫所处位置的左
            var d4:number=this.map[this.row][this.col+1];//猫所处位置的右
            if(this.row%2==0){
                //奇数行,左上左下
                var d5:number=this.map[this.row-1][this.col-1];//猫所处位置的左上
                var d6:number=this.map[this.row+1][this.col-1];//猫所处位置的左下
            }else{
                //偶数行,右上右下
                var d5:number=this.map[this.row-1][this.col+1];//猫所处位置的右上
                var d6:number=this.map[this.row+1][this.col+1];//猫所处位置的右上
            }
            var min:number=Math.min(d1,Math.min(d2,Math.min(d3,Math.min(d4,Math.min(d5,d6)))));
            var max:number=Math.max(d1,Math.max(d2,Math.max(d3,Math.max(d4,Math.max(d5,d6)))));
            if(max==0){//max为0说明已经被困住但是还可以走
                this.flag=true;
                if(max==d1){
                    return 1;//上
                }else if(max==d2){
                    return 2;//下
                }else if(max==d3){
                    return 3;//左
                }else if(max==d4){
                    return 4;//右
                }else if(max==d5){
                    return 5;//左上或右上
                }else if(max==d6){
                    return 6;//左下或右下
                }
            }else if(max==-1){//max为-1说明六个方向都是障碍,即成功围住
                return 0;
            }else if(min==1){//min为1说明猫已经走到了边缘,可以逃脱
                return -1;
            }
            if(d1==-1){
                d1=100;
            }
            if(d2==-1){
                d2=100;
            }
            if(d3==-1){
                d3=100;
            }
            if(d4==-1){
                d4=100;
            }
            if(d5==-1){
                d5=100;
            }
            if(d6==-1){
                d6=100;
            }
            min=Math.min(d1,Math.min(d2,Math.min(d3,Math.min(d4,Math.min(d5,d6)))));
            if(min==d1){
                return 1;//上
            }else if(min==d2){
                return 2;//下
            }else if(min==d3){
                return 3;//左
            }else if(min==d4){
                return 4;//右
            }else if(min==d5){
                return 5;//左上或右上
            }else if(min==d6){
                return 6;//左下或右下
            }
        }

findpath()类用来计算存储路径数据的,首先将内部二维数组初始化为0,然后接收外部Main中的obstacles的障碍物标识,通过边缘1,障碍物-1,正常0的标识对obstacles二维数据存储,根据边缘数据求得往中心点的路径标识为2,3,4。在每次点击制造障碍物的时候进行更新,同时猫会根据自己附近最少的那个标识进行移动,一旦标识为0则证明没有路可以走,然后进行变猫(动画),一旦走到标识1的位置则证明游戏胜利。

反之,附近标识为-1的情况则失败

四、总结:

        这款《围住疯狂猫》难度不难,主要运用到了最短路径的算法,然后就是灵活运用二维数组存储数据,依我来看,这个寻路算法还有缺陷。有待提高,或者可以设定它的随机概率。不然,很容易预判到猫的移动轨迹(那边近走那边)。。。

猜你喜欢

转载自blog.csdn.net/qq_57250692/article/details/134429861