Egret社区
本帖最后由 pplboy 于 2014-10-13 12:00 编辑

一切源于  wujian001215  帅哥  
版主 能不能把游戏从无到有的过程给我讲解下 就是说 一个游戏制作需要哪些元素 哪些egret方法哪些素材 刚接触 感觉很有意思,想深入研究

前天 16:14

讲解我可担当不起,只能尽自己的一些经验很浅薄的说说,抛砖引玉,希望真正的大牛来给支支招。


我感觉一个游戏肯定要有的因素是,玩法,角色,其他模式。。咳咳写的自己都觉得寒蝉鸟。


这样吧,说说我怎么想起来做那个粘粘的过程吧。


(一)想法,当时就是觉得想做个比较耐玩的游戏,然后想啊想啊,先尝试别人已经觉得耐玩的游戏吧。正好边学Egret边实现,反正没啥坏处。
之前我也玩过一段时间 消灭星星 那个游戏,感觉上很耐玩,并且也符合我当时的目标,画面很简单么,就是些方块(俺的美术水平就是停留在能拼凑的阶段)
有了这个想法后,没有开始写程序就开始去分析 消灭星星的游戏模式

(二)简单的分析后,感觉这个游戏模式并不复杂,单就玩法分解一下
1 在一个容器里放上一些随机颜色的色块
2 点击一个色块,让与其相连的同色色块都处于被选中状态
3 再次点击色块,让被选中的色块消失掉
4 垒在色块上的色块要往下掉补掉掉下的那些色块
5 如果色块一列都消除了,那么往左平移动所有右方的色块。
6 如果容器里的所有色块都处于两个连接都没有的情况,算是过关,或者说是死局。
7 增加点难度,60秒如果没进入死局的状态,就GameOver

(三)然后就是找蔬菜啦,baidu google 到处爬,看到好看的能激发想法的图片就保存下来,然后对着电脑死盯半个小时开始绘制原型图。把几张原型图画好,基本上也就想清楚这个游戏应该怎么倒腾了。然后把需要的素材,都切出来,保存成资源。
创意1.jpg

(四)按照第二步的分解,开始逐渐在代码中实现各个部分的功能。下面一大波代码前来助兴。
1 在一个容器里放上一些随机颜色的色块
     这个简单,只要将方块往容器里填充就行了,设定x y 的坐标和颜色,行 列,就OK了。
由于之后需要移动方块,所以先得准备一个二维数组,然后将生成的方块的引用都扔到数组里
[mw_shl_code=applescript,true]
private rowNum;
    private colNum;

    private initMapData(){
        this.rowNum = 11; //每行元素数
        this.colNum = 14; //每列元素数
//        this.colNum = 15; //每列元素数
        this.map = [];
        for(var x=0;x<this.rowNum;x++){
            var tmp_array = [];
            for(var y=0;y<this.colNum;y++){
                var type = GameApp.random(1,7);
                var obj = new Block(type,x,y);
                tmp_array[y] = obj;
            }
            this.map[x] = tmp_array;
        }
        //console.log(this.map);
        this.drawMap();
    }

    private drawMap(){
        this.MapContainer = new egret.DisplayObjectContainer;
        for(var x=0;x<this.rowNum;x++){
            for(var y=0;y<this.colNum;y++){
                this.map[x][y].draw();
                this.map[x][y].x = 20+x*40;
                this.map[x][y].y = 140+y*40;
                this.map[x][y].touchEnabled = true;
                this.map[x][y].addEventListener(egret.TouchEvent.TOUCH_TAP,this.onBlockClick,this);
                this.MapContainer.addChild(this.map[x][y]);
            }
        }
        this.addChild(this.MapContainer);
    }

[/mw_shl_code]

2 点击一个色块,让与其相连的同色色块都处于被选中状态
呃,这个步骤我们再拆解一下吧,第一步是让色块可以被点中,点中后会触发一段代码[mw_shl_code=applescript,true]
                this.map[x][y].addEventListener(egret.TouchEvent.TOUCH_TAP,this.onBlockClick,this);

[/mw_shl_code]

第二个步骤是找到附近相同颜色的色块,然后让他们都处于被选中的状态。
[mw_shl_code=applescript,true]
private onBlockClick(evt:egret.TouchEvent){
        if(this.clickNum==1){
            // 高亮当前色附近的同色色块
            this.startBlock = evt.target;
            try{
                this.selectArea = [];
                this.checkNear(evt.target);
            }catch(e){
                //console.log(e);
            }
            //console.log(this.selectArea);
            if(this.selectArea.length>0){
                this.clickNum=2;
                this.selectArea.push(evt.target);
                for(var i=0;i<this.selectArea.length;i++){
                    var em = egret.Tween.get( this.selectArea );
                    em.to( {scaleX:1.2,scaleY:1.2}, 500);
                }
            }
        }else if(this.clickNum == 2){
            //消除
            this.clickNum = 1;
            if(this.selectArea.length>=2 && evt.target.type == this.startBlock.type){
                for(var i=0;i<this.selectArea.length;i++){
                    this.MapContainer.removeChild(this.selectArea);
                    this.map[this.selectArea.GX][this.selectArea.GY] = 0;
                    //刷新地图
                    this.resetMap();
                }
//                this.sounddd.play();
                if(this.selectArea.length>6){
//                    this.soundhc.play();
                }

                this.score +=this.selectArea.length*this.selectArea.length;
                this.scoreTextField.text = "得分:"+(this.score);


            }else{
                for(var i=0;i<this.selectArea.length;i++){
                    this.selectArea.checked = 0;
                    var em = egret.Tween.get( this.selectArea );
                    em.to( {scaleX:1,scaleY:1}, 500);
                }
            }
        }
    }

//检查相邻的元素    贪婪周边算法
    private checkNear(em){
        //console.log("em.GX:"+em.GX);
        //console.log("em.GY:"+em.GY);
        var x = em.GX;
        var y = em.GY;
        em.checked = 1;

        var tmpArray= [];
        if((y-1)>=0 && this.map[x][y-1].checked==0 && this.map[x][y-1].type==em.type ){
            this.map[x][y-1].checked = 1;
            tmpArray.push(this.map[x][y-1]);
            //console.log("上同色");
        }
        if((y+1)<this.colNum && this.map[x][y+1].checked==0 && this.map[x][y+1].type==em.type){
            this.map[x][y+1].checked = 1;
            tmpArray.push(this.map[x][y+1]);
            //console.log("下同色");
        }
        if((x-1)>=0&&this.map[x-1][y].checked==0 && this.map[x-1][y].type==em.type){
            this.map[x-1][y].checked = 1;
            tmpArray.push(this.map[x-1][y]);
            //console.log("左同色");
        }
        if((x+1)<this.rowNum&&this.map[x+1][y].checked==0 && this.map[x+1][y].type==em.type){
            this.map[x+1][y].checked = 1;
            tmpArray.push(this.map[x+1][y]);
            //console.log("右同色");
        }
        if(tmpArray.length==0){
            return false;
        }else{
            for(var i=0;i<tmpArray.length;i++){
                this.selectArea.push(tmpArray);
            }
            for(var i=0;i<this.selectArea.length;i++){
                this.checkNear(this.selectArea);
            }
        }
        return false;
    }

[/mw_shl_code]

3 再次点击色块,让被选中的色块消失掉
当第二次点击的时候,清除色块
这个的实现在上面的 逻辑中了
[mw_shl_code=applescript,true]
if(this.clickNum == 2){
[/mw_shl_code]

4 垒在色块上的色块要往下掉补掉掉下的那些色块
这个就看出来之前需要的map了,其实就是地图存方块的那个数组,先把一列里空掉的最后一个0 往上挪动到不能挪动为止,
然后再挪动 第二个为空的元素,递归遍历一下,最后的结果就是空的被挪动上去了,则有元素的东西就掉下来了。
我这个方法很笨了,但是能用就行。
[mw_shl_code=applescript,true]
public resetMap(){
        var moveCol = [];
        var moveRow = [];
        for(var x=0;x<this.rowNum;x++){
            var colEmNum = 0;
            for(var y=0;y<this.colNum;y++){
                if(this.map[x][y]==0){
                    //查找上方元素 如有元素整体下移
                    if((y-1)>=0 && this.map[x][y-1]!=0 ){
                        moveCol[x] = x;
                        //console.log("下移动列"+x);
                    }
                    //查找右方元素 如有元素整体左移
                }else{
                    colEmNum++;
                };
            }
            if(colEmNum==0){
                moveRow[x] = x;
            }
        }

        //console.log("moveRow-");
        //console.log(moveRow);
        //console.log("moveRow-");
        //console.log(this.map);
        if(moveCol.length>0){
            for(var e in moveCol){
                //console.log(e);
                this.moveCol(e);
            }
        }
        if(moveRow.length>0){
            for(var e in moveRow){
                //console.log(e);
                this.moveRow(e);
            }
        }

        if(this.checkMap()){
            console.log("死局");
//            this.soundhc.play();
            this.levelUp();
        }
        //console.log(this.map);


    }
[/mw_shl_code]
5 如果色块一列都消除了,那么往左平移动所有右方的色块。
同上,这次搞右边的空方块,代码也在上面那坨里了,补上移动的方法

[mw_shl_code=applescript,true] //冒泡算法向上移动0元素
    public moveCol(e){
        //下落元素
        for(var n=this.colNum;n>0;n--){
            for(var y=this.colNum;y>0;y--){
                if(this.map[e][y]==0){
                    this.map[e][y] = this.map[e][y-1];
                    this.map[e][y-1]=0;
                    this.map[e][y].GY +=1;
                    this.map[e][y].y  +=40;
                    break;
                }
            }
        }
    }

    //将e 右面的所有元素偏移到当前e列
    public moveRow(e){
        for(var x=e;x<this.rowNum;x++){
            for(var y=this.colNum-1;y>=0;y--){
                //不抛出异常就会有一个错误
                try{
                    this.map[x][y] = this.map[parseInt(x)+1][y];
                    this.map[parseInt(x)+1][y]=0;
                    if(this.map[x][y]!=0){
                        this.map[x][y].GX -=1;
                        this.map[x][y].x -=40;
                    }

                }catch(e){}
            }
        }
    }[/mw_shl_code]


6 如果容器里的所有色块都处于两个连接都没有的情况,算是过关,或者说是死局。
这个游戏怎么了结呢,其实有一个很噁心的防止死局的算法,穷举所有的色块,一旦发现有两个以上相连的同色色块,就退出,否则,就往死里穷举
如果都试玩了,还没有,就算是死局啦。
[mw_shl_code=applescript,true]
  public checkMap(){
        var tmpArray= [];
        for(var x=0;x<this.rowNum;x++){
            for(var y=0;y<this.colNum;y++){
                if(this.map[x][y]!=0){
                    var em = this.map[x][y];
                    if((y-1)>=0 && this.map[x][y-1].checked==0 && this.map[x][y-1].type==em.type ){
                        tmpArray.push(this.map[x][y-1]);
                        //console.log("上同色");
                    }
                    if((y+1)<this.colNum && this.map[x][y+1].checked==0 && this.map[x][y+1].type==em.type){
                        tmpArray.push(this.map[x][y+1]);
                        //console.log("下同色");
                    }
                    if((x-1)>=0&&this.map[x-1][y].checked==0 && this.map[x-1][y].type==em.type){
                        tmpArray.push(this.map[x-1][y]);
                        //console.log("左同色");
                    }
                    if((x+1)<this.rowNum&&this.map[x+1][y].checked==0 && this.map[x+1][y].type==em.type){
                        tmpArray.push(this.map[x+1][y]);
                        //console.log("右同色");
                    }
                }
            }
        }
        console.log(tmpArray.length);

        if(tmpArray.length==0){
            return true;
        }
    }


[/mw_shl_code]
7 增加点难度,60秒如果没进入死局的状态,就GameOver
这些属于给游戏增加难度的了,好的游戏不光要有玩法,还要有很多限制,人嘛就是要有些挑战才会玩的开心(看来自虐心人人有啊)。
[mw_shl_code=applescript,true]
    private initTime(){
        this.gameTime.addEventListener(egret.TimerEvent.TIMER,this.onGameTime,this);
    }

    private onGameTime(){

        this.nowTime -=1;
        var tw = egret.Tween.get( this.timeLine );
        tw.to( {widththis.timeLineStartWidth/120)*this.nowTime}, 1000);

        //////console.log(this.nowTime);
        if(this.nowTime<=0){
            //Game Over
            this.stopTime();
            //////console.log("Time Over");
            var daterEvent:GameEvent = new GameEvent(GameEvent.GAMEOVER);
            daterEvent._gametype = 1;
            daterEvent._score = this.score;
            //时间到
            daterEvent._dieType = 1;
            this.dispatchEvent(daterEvent);

        }
    }

[/mw_shl_code]







以上就是一个游戏从无到有的过程,wujian001215 满意了吧~~~~~  

其实啊从无到有,就是个“做”字。祝你好好学习,天天向上。{:6_142:学习本身就是一个很快乐的事情,自己构想,自己实现,一点点的,爽歪歪。都是些小玩意,通一则通百。
所以捏,有问题我很乐意解答哈。charlie19817 我的微信,欢迎小伙伴们一起愉快的玩耍。。。。。

最后附上 粘粘 的地址 http://isqgame.com/app/cl/nn/launcher/release.html










参与人数 1银子 +10 贡献 +3 收起 理由
张宇 + 10 + 3 很给力!

查看全部评分

分享到 :
3 人收藏

51 个回复

倒序浏览
pow303433732  登堂入室 | 2014-12-1 18:09:38
我更关注的是楼主是怎么发布到服务器上去的 要付费的嘛  楼主可以给我科普一下吗
taqrmh  登堂入室 | 2015-6-4 15:33:07
QQ图片20150604153000.png   有BUG  还有没消灭的块, 时间在走。  方块不能点了
samzomie  圆转纯熟 | 2014-10-13 09:22:32
赞一个
wujian001215  登堂入室 | 2014-10-13 10:26:04
谢谢啦 大神
dreamstone  官方团队 | 2014-10-13 11:20:38
赞~\(≧▽≦)/~
change  斑竹 | 2014-10-13 11:33:27
学习ING……谢谢分享!
slert  圆转纯熟 | 2014-10-13 13:49:09
赞啊 看完了 挑点小骨头
moveCol[x] = x;是不是多余?直接调用this.moveCol(e);也可以吧?
moveRow[x] = x; 同理
bestscw  登堂入室 | 2014-10-13 16:11:21
功能是有了,用户体验太差,楼主在改下用户体验就不错了。加些动画
卤煮火烧  登堂入室 | 2014-10-13 18:22:14
顶一个,正好最近在考虑作一个游戏,学习了
pplboy  斑竹 | 2014-10-14 08:33:34
slert 发表于 2014-10-13 13:49
赞啊 看完了 挑点小骨头
moveCol[x] = x;是不是多余?直接调用this.moveCol(e);也可以吧?
moveRow[x]  ...

楼上看的很仔细啊,貌似可能可以这么替换
pplboy  斑竹 | 2014-10-14 08:34:13
bestscw 发表于 2014-10-13 16:11
功能是有了,用户体验太差,楼主在改下用户体验就不错了。加些动画

嗯,俺会继续优化的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|京网文[2014]0791-191号|京ICP证150115号|Egret社区 ( 京ICP备14025619号 )

Powered by Discuz! X3.4 © 2001-2019 Comsenz Inc.

返回顶部