Cocos Creator開(kāi)發(fā)游戲消滅星星——星星生成

先來(lái)說(shuō)下要實(shí)現(xiàn)的功能

  • 根據(jù)一定規(guī)則生成關(guān)卡
  • 實(shí)現(xiàn)消除等邏輯
  • 游戲結(jié)束檢測(cè)
  • 本地緩存游戲進(jìn)度

準(zhǔn)備工作

建好工程,使用編輯器搭建游戲場(chǎng)景。我搭建的場(chǎng)景如下圖:



簡(jiǎn)單說(shuō)明下:

  • New Sprite是場(chǎng)景中的背景圖片
  • StarRoot是一個(gè)空節(jié)點(diǎn),后面創(chuàng)建的星星方塊都會(huì)加到這個(gè)節(jié)點(diǎn)上
  • ActionRoot是一些做動(dòng)作、動(dòng)畫(huà)節(jié)點(diǎn)的父節(jié)點(diǎn),像comb特效就在這個(gè)節(jié)點(diǎn)上
  • UIRoot,就是用戶界面上的根節(jié)點(diǎn),像游戲的最高分、當(dāng)前分?jǐn)?shù)、當(dāng)前第幾關(guān)等等,都放在這個(gè)節(jié)點(diǎn)上
  • ResultRoot是結(jié)算界面的根節(jié)點(diǎn)。顯示灰色是因?yàn)闆](méi)有激活這個(gè)節(jié)點(diǎn)
  • SoundCTL也是一個(gè)空節(jié)點(diǎn),主要作用是在節(jié)點(diǎn)上掛載一個(gè)腳本處理游戲的聲音

制作星星預(yù)制

方法參考官方文檔


很簡(jiǎn)單,根節(jié)點(diǎn)下只有一個(gè)精靈節(jié)點(diǎn)。顯示藍(lán)色就表示是一個(gè)預(yù)制。主要說(shuō)一下star上的腳本組件starCtr.js

因?yàn)椴恢挂环N星星,所以需要改變New Sprite的紋理。星星有下面幾個(gè)屬性:

properties: {
    _starType: 0,
    _gx: 0,
    _gy: 0,
    starSprite: cc.Sprite,
    starSpriteFrames: {
        default: [],
        type: cc.SpriteFrame,
    },
},

starSprite對(duì)應(yīng)上圖New Sprite的Sprite組件;starSpriteFrames存儲(chǔ)了所有星星的紋理;_starType表示星星的類別,它決定了starSprite顯示starSpriteFrames中的哪個(gè)紋理;_gx、_gy用來(lái)存儲(chǔ)星星方塊在10x10地圖中的格子坐標(biāo)。

initStar (type, gx, gy) {
    this._starType = type;
    this.starSprite.spriteFrame = this.starSpriteFrames[this._starType];
    this.updateGrid(gx, gy);
},
updateGrid (gx, gy) {
    this._gx = gx;
    this._gy = gy;
},

initStar星星的初始化函數(shù),updateGrid用來(lái)更新星星的坐標(biāo)位置

在預(yù)制里還做了一個(gè)操作,就是處理用戶的點(diǎn)擊操作,所以在腳本的start函數(shù)里監(jiān)聽(tīng)觸摸。start是組件腳本生命周期的回調(diào)函數(shù),會(huì)在組件第一次激活前,也就是第一次執(zhí)行update之前觸發(fā)。

start () {
    this.node.on(cc.Node.EventType.TOUCH_START, function (event) {
        //TODO:觸摸處理
    }, this);
},

具體的觸摸處理后面說(shuō)。最后看下屬性檢查器里的腳本組件:


生成關(guān)卡數(shù)據(jù)

  • 生成規(guī)則:每個(gè)格子隨機(jī)生成星星。(這里選取一個(gè)簡(jiǎn)單的邏輯規(guī)則,自己可以根據(jù)實(shí)際情況修改星星生成的邏輯)
  • 用一個(gè)二維數(shù)組存儲(chǔ)10×10的地圖數(shù)據(jù)

下面介紹兩個(gè)對(duì)象,分別創(chuàng)建兩個(gè)腳本gamedata.js、Utils.js
gamedata處理游戲的數(shù)據(jù),像游戲的得分、當(dāng)前第幾關(guān)、地圖數(shù)據(jù)等等都存儲(chǔ)在里面。

// gamedata.js
var level = 0; //記錄當(dāng)前關(guān)卡
var targetScore = 0; //當(dāng)前關(guān)卡目標(biāo)分?jǐn)?shù)
var currScore = 0; //當(dāng)前得分
var bestScore = 0; //歷史最高得分
var starMatrix = null; //地圖數(shù)據(jù),二維數(shù)組
var starSprite = []; //一維數(shù)組,存儲(chǔ)星星的Node

module.exports = {
    level: level,
    targetScore: targetScore,
    currScore: currScore,
    bestScore: bestScore,
    starMatrix: starMatrix,
    starSprite: starSprite,
};

Utils主要是處理一些公用的邏輯,像關(guān)卡生成規(guī)則的邏輯就放這里了。

// Utils.js
var Config = require("psconfig");

var randomColorByArray = function (array) {
    var i = Math.floor(Math.random() * array.length);
    return array[I];
}

//隨機(jī)生成星星關(guān)卡邏輯
function initMatrixDataPortraitRandom () {
    var matrixData = new Array(Config.matrixRow);
    for(var row = 0; row < Config.matrixRow; row++) {
        matrixData[row] = new Array(Config.matrixCol);
        for(var col = 0; col < Config.matrixCol; col++) {
            matrixData[row][col] = randomColorByArray(Config.totalColors);
        }
    }
    return matrixData;
};

module.exports = {
    initMatrixDataPortraitRandom: initMatrixDataPortraitRandom,
};

腳本Utils.js加載了另一個(gè)腳本psconfig.js,它主要存放游戲的一些配置,代碼如下:

//psconfig.js
var cellSize = 73; //星星紋理的邊長(zhǎng)
var matrixRow = 10; //地圖的行數(shù)(高)
var matrixCol = 10; //地圖的列數(shù)(寬)
var totalColors = [0,1,2,3,4]; //表示五種星星

module.exports = {
    cellSize: cellSize,
    matrixRow: matrixRow,
    matrixCol: matrixCol,
    totalColors: totalColors,
};

到這里,關(guān)卡數(shù)據(jù)已經(jīng)生成,下面就是根據(jù)生成的數(shù)據(jù)繪制星星地圖。

繪制星星

一開(kāi)始提到,創(chuàng)建的所有星星都會(huì)放在StarRoot的節(jié)點(diǎn)上。場(chǎng)景中StarRoot是一個(gè)空節(jié)點(diǎn),有一個(gè)腳本組件matrixCtr,看下圖:


單個(gè)格子邊長(zhǎng)73,格子間有2個(gè)像素的縫隙,所以StarRoot是邊長(zhǎng)748的正方形,把它的錨點(diǎn)設(shè)置在左下角,為了方便格子坐標(biāo)和像素位置坐標(biāo)之間的轉(zhuǎn)換。

在Utils腳本上添加兩個(gè)函數(shù)用于坐標(biāo)之間的轉(zhuǎn)換。

//Utils.js
function grid2Pos (gx, gy) {
    var px = Config.cellSize * 0.5 + (Config.cellSize + 2) * gy;
    var py = Config.cellSize * 0.5 + (Config.cellSize + 2) * gx;
    return cc.v2(px, py);
};
function pos2Grid (px, py) {
    var gx = (py - Config.cellSize * 0.5) / (Config.cellSize + 2);
    var gy = (px - Config.cellSize * 0.5) / (Config.cellSize + 2);
    return cc.v2(Math.round(gx), Math.round(gy));
};

最后別忘了導(dǎo)出,在module.exports中添加變量:

module.exports = {
    grid2Pos: grid2Pos,
    pos2Grid: pos2Grid,
    initMatrixDataPortraitRandom: initMatrixDataPortraitRandom,
};

下面說(shuō)一下腳本matrixCtr.js
上圖中可以看到,腳本中有兩個(gè)預(yù)制類型的屬性star、particle,其中star就是開(kāi)始制作的星星預(yù)制。particle主要是播放粒子,是星星消除時(shí)的特效。

properties: {
        starPrefab: cc.Prefab,
        starParticle: cc.Prefab,
        _starPool: null,
        uiCtr: cc.Node,
        actCtr: cc.Node,
        combCtr: cc.Node,
        soundCtr: cc.Node,
},

因?yàn)橛螒蛑幸l繁創(chuàng)建和銷毀星星,而這些操作是非常耗費(fèi)性能的,所以這里使用了對(duì)象池。關(guān)于它的介紹和使用方法參考官方文檔

//matrixCtr.js
var Utils = require("Utils");
var Config = require("psconfig");
var GameData = require("gamedata");

onLoad () {
    //初始化對(duì)象池
    this._starPool = new cc.NodePool();
    for(var i = 0; i < Config.matrixCol*Config.matrixRow; ++i) {
        var star = cc.instantiate(this.starPrefab);
        this._starPool.put(star);
    }
}
onDestroy () {
    this._starPool.clear();
},
createStar (type, gx, gy) {
    var star = null;
    if (this._starPool.size() > 0) {
        star = this._starPool.get();
    }
    else {
        star = cc.instantiate(this.starPrefab);
    }
    star.setPosition(Utils.grid2Pos(gx, gy));
    this.node.addChild(star);
    var starCtr = star.getComponent("starCtr");
    starCtr.initStar(type, gx, gy);
    return star
},

注意,這里省略了cc.Class等一些通用代碼,有了createStar函數(shù),我們就可以根據(jù)前面生成的數(shù)據(jù)來(lái)繪制星星了。

// matrixCtr.js
initMatrix () {
    for(var row = 0; row < GameData.starMatrix.length; row++) {
        var cols = GameData.starMatrix[row];
        for(var col = 0; col < cols.length; col++) {
            var type = cols[col];
            var index = Utils.indexValue(row, col);
            if (type >= 0) {
                var node = this.createStar(type, row, col);
                GameData.starSprite[index] = node;
            }
            else {
                 GameData.starSprite[index] = null;
            }
        }
    }
},

initMatrix函數(shù)中使用了Utils腳本中的indexValue函數(shù)。這是因?yàn)榇鎯?chǔ)星星數(shù)據(jù)的是二維數(shù)組,存儲(chǔ)星星Node的是一維數(shù)組,它是兩者索引的轉(zhuǎn)換。當(dāng)然,存儲(chǔ)星星Node也可以使用二維數(shù)組。

//Utils.js
function indexValue (row, col) {
    return row * Config.matrixCol + col;
};
function resolveIndex (index) {
    var col = index % Config.matrixCol;
    var row = (index - col) / Config.matrixCol;
    return cc.v2(row, col);
};

別忘了在module.exports中導(dǎo)出變量,這里就省略了,最后上一張效果圖。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。