内容纲要

1.游戏原图

开心消消乐插图

开心消消乐插图(1)

2.游戏介绍及规则

  • 《开心消消乐》是一款乐元素研发的一款三消类休闲游戏。
  • 把三个颜色相同的小动物连成一条直线,即可消除;四个小动物连在一起会生成横向消除一行的新道具,五个连接在一起会生成魔力鸟,魔力鸟可以和任何小动物交换并消除交换的所有小动物。

3.游戏特效

  • 游戏中的特效主要有直线特效,爆炸特效、魔力鸟特效,任意2个特效都可以组合在一块使用。
    • 直线特效:四个相同的动物一行或一列可以合成一个直线特效,触发直线特效可以消除一行或一列
    • 爆炸特效:五个相同的不同行动物可以合成一个爆炸特效,触发爆炸特效可以消除附近的动物
    • 魔力鸟特效:任意五个同行且相同的动物可以合成一个魔力鸟特效,触发魔力鸟特效可以消除所有相同的动物

4.游戏开发过程

  • 搭建游戏Logo界面
    • 在assets上创建一个文件夹名为Scence,这个文件夹用来存放场景,新建一个场景Scence改名为Login
    • 在Canvas上建一个background节点,在这个节点上插入Sprite(图片精灵)组件,把LoGo图片拖进去,调整大小,这个就是游戏LoGo界面
    • 在Canvas上面加一个Button按钮,改名为loginButton,将游戏按钮图片托入,调整大小
    • 在Canvas上创建一个UI节点ProgressBar,改名为LoadProgressBar此节点为进度条,在bar上拖入进度条图片,Lable上写入(Loading)文字,调整进度条大小
  • 新建js脚本
    • 在assets中新建一个文件夹名为Script,在文件夹中创建一个LoginController脚本,这个脚本用于LoGo与游戏界面的切换,将这个脚本加入在Canvas中,把该加入的文件和资源加进去
    • 保存场景Logo,LoGo场景搭建完成!搭建场景如下:
      开心消消乐插图(2)
  • 搭建游戏UI界面
    • 在Scence文件夹中新建一个Scence场景文件,改名为Game,大小改为630*630,这个场景是游戏界面场景
    • 在Canvas上新建一个GameScence节点,用于处理游戏总逻辑显示
    • 在GameScence节点上创建一个Grid节点,再添加一个组件Mask,用于遮挡最上层随机生成的动物,将游戏资源中的背景图托在节点上,Grid节点主要用于动物的预制体随机生成在界面上,及动物消除时的音效
    • 在Canvas上新建一个EffecLaye节点,这个节点主要用于特殊道具的特效和音效
    • 在Canvas上创建一个AudioUtils节点,这个节点主要用于所有的音效
    • 搭建场景如下:
      开心消消乐插图(3)
  • 制作预制体和动画特效
    • 制作各种动物的各种动画,特殊道具生效时的动画
    • 在Script文件夹中新建一个js脚本名为CellView,这个脚本主要用于对预制体做在界面上的生成处理
    • 创建预制体,以小熊为例(其他做法都相同),在Canvas上新建一个空节点Bear,在Bear上添加一个动画组件和一个图片精灵组件分别把对相应的动画和图片拖进去,将CellView脚本添加到Bear节点上,拖入小熊的图片
    • 在assets上新建一个Prefabs文件夹,把Bear节点拖入Prefabs文件夹中,预制体完成(其他动物制作方法相同)
    • 预制体做好了以后删除Canvas上的所有动物节点。这样所有的预制体就做好了
  • 编写脚本
    • 在文件夹Script中新建一个js脚本AudioUtils,用于管理所有的音效逻辑(动物之间交换的音效,点击动物时的音效,动物消除时的音效,连续消除时的音效),把这个脚本拖入AudioUtils节点中,将各种相应的音效加入脚本组件中
    • 在Script中新建一个js脚本EffectLayer,这个脚本加入特效,和发生特效时的音效,把这个脚本拖入EffectLayer节点中,把特效预制体和AudioUtils节点加入脚本组件中
    • 在Script文件夹中新建一个js脚本GridViwe,这个脚本主要负责游戏中的特效和动物移动的动态处理,将这个脚本加入Grid节点中,加入每个动物的预制体,EffectLayer和AudioUtils节点。
    • 在在Script文件夹中新建一个js脚本GameModel,这个脚本时游戏最重要的逻辑,消除逻辑。

5.算法逻辑

特殊道具的生成
    let rowResult = checkWithDirection.call(this,x,y,[cc.p(1, 0), cc.p(-1, 0)]);//左右移动
    let colResult = checkWithDirection.call(this,x,y,[cc.p(0, -1), cc.p(0, 1)]);//上下移动
    let result = [];
    let newCellStatus = "";//新的状态
    //如果一行有五个相同的动物,生成大鸟
    if(rowResult.length >= 5 || colResult.length >= 5){
        newCellStatus = CELL_STATUS.BIRD;
    }
    //如果一行有三个相同的的动物,消除
    else if(rowResult.length >= 3 && colResult.length >= 3){
        newCellStatus = CELL_STATUS.WRAP;
    }
    //如果横向移动,四个动物相同,生成消除一行的的这个动物
    else if(rowResult.length >= 4){
        newCellStatus = CELL_STATUS.LINE;
    }
    //如果纵向移动,四个动物相同,生成一列的这个动物
    else if(colResult.length >= 4){
        newCellStatus = CELL_STATUS.COLUMN;
    }
随机生成
//格子中动物的类型
export const CELL_TYPE = {
    EMPTY : 0,
    A : 1,
    B : 2,
    C : 3,
    D : 4,
    E : 5,
    F : 6,
    BIRD : 7
}

// 随要生成一个类型
GameModel.prototype.getRandomCellType = function(){
    var index = Math.floor(Math.random() * this.cellTypeNum) ;
    return this.cellCreateType[index];
消除
GameModel.prototype.processBomb = function(bombModels, cycleCount){
    while(bombModels.length > 0){
        let newBombModel = [];
        let bombTime = ANITIME.BOMB_DELAY;
        bombModels.forEach(function(model){
            //横向消除
            if(model.status == CELL_STATUS.LINE){
                for(let i = 1; i<= GRID_WIDTH; i++){
                    if(this.cells[model.y][i]){
                        if(this.cells[model.y][i].status != CELL_STATUS.COMMON){
                            newBombModel.push(this.cells[model.y][i]);
                        }
                        this.crushCell(i, model.y, false, cycleCount);//false是是否需要消除前摇晃
                    }
                }
                this.addRowBomb(this.curTime, cc.p(model.x, model.y));
            }
            //纵向消除
            else if(model.status == CELL_STATUS.COLUMN){
                for (let i = 1; i <= GRID_HEIGHT; i++) {
                    if (this.cells[i][model.x]) {
                        if (this.cells[i][model.x].status != CELL_STATUS.COMMON) {
                            newBombModel.push(this.cells[i][model.x]);
                        }
                        this.crushCell(model.x, i, false, cycleCount);
                    }
                }
                this.addColBomb(this.curTime, cc.p(model.x, model.y));
            }
            //三消
            else if(model.status == CELL_STATUS.WRAP){
                let x = model.x;
                let y = model.y;
                for(let i = 1;i <= GRID_HEIGHT; i++){
                    for(let j = 1;j <= GRID_WIDTH; j++){
                        let delta = Math.abs(x - j) + Math.abs(y - i);
                        if(this.cells[i][j] && delta <= 2){
                            if (this.cells[i][j].status != CELL_STATUS.COMMON) {
                                newBombModel.push(this.cells[i][j]);
                            }
                            this.crushCell(j, i, false, cycleCount);
                        }
                    }
                }
            }
            //大鸟消除
            else if(model.status == CELL_STATUS.BIRD){
                let crushType = model.type
                if(bombTime < ANITIME.BOMB_BIRD_DELAY){
                    bombTime = ANITIME.BOMB_BIRD_DELAY;
                }
                if(crushType == CELL_TYPE.BIRD){
                    crushType = this.getRandomCellType(); 
                }
                for(let i = 1;i <= GRID_HEIGHT; i++){
                    for(let j = 1;j <= GRID_WIDTH; j++){
                        if(this.cells[i][j] && this.cells[i][j].type == crushType){
                            if (this.cells[i][j].status != CELL_STATUS.COMMON) {
                                newBombModel.push(this.cells[i][j]);
                            }
                            this.crushCell(j, i, true, cycleCount);
                        }
                    }
                }
            }
        },this);
        if(bombModels.length > 0){
            this.curTime += bombTime;
        }
        bombModels = newBombModel;
    }
}
下落
// 下落
GameModel.prototype.down = function(){
    let newCheckPoint = [];
     for(var i = 1;i<=GRID_WIDTH;i++){
        for(var j = 1;j <= GRID_HEIGHT;j++){
            if(this.cells[i][j] == null){
                var curRow = i;
                for(var k = curRow; k<=GRID_HEIGHT;k++){
                    if(this.cells[k][j]){
                        this.pushToChangeModels(this.cells[k][j]);
                        newCheckPoint.push(this.cells[k][j]);
                        this.cells[curRow][j] = this.cells[k][j];
                        this.cells[k][j] = null;
                        this.cells[curRow][j].setXY(j, curRow);
                        this.cells[curRow][j].moveTo(cc.p(j, curRow), this.curTime);
                        curRow++; 
                    }
                }
                var count = 1;

                //随机生成,不出现在Mask中
                for(var k = curRow; k<=GRID_HEIGHT; k++){
                    this.cells[k][j] = new CellModel();
                    this.cells[k][j].init(this.getRandomCellType());// 随要生成一个类型
                    this.cells[k][j].setStartXY(j, count + GRID_HEIGHT);
                    this.cells[k][j].setXY(j, count + GRID_HEIGHT);
                    this.cells[k][j].moveTo(cc.p(j, k), this.curTime);
                    count++;
                    this.changeModels.push(this.cells[k][j]);
                    newCheckPoint.push(this.cells[k][j]);
                }

            }
        }
    }
    this.curTime += ANITIME.TOUCH_MOVE + 0.3
    return newCheckPoint;
}

GameModel.prototype.pushToChangeModels = function(model){
    if(this.changeModels.indexOf(model) != -1){
        return ;
    }
    this.changeModels.push(model);
}

GameModel.prototype.cleanCmd = function(){
    for(var i = 1;i<=GRID_WIDTH;i++){
        for(var j = 1;j <= GRID_HEIGHT;j++){
            if(this.cells[i][j]){
                this.cells[i][j].cmd = [];
            }
        }
    }
}

6.参考

参考: https://blog.csdn.net/sinat_39291423/article/details/78089828

7.GitHub文档

地址:https://github.com/mintao1106/kx

1 对 “开心消消乐”的想法;

  1. Pingback: viagra

发表评论