aircraft-war(一)

aircraft-war(一)

Game Scene 布局

首先制作場(chǎng)景中的部件,早cocos creator中創(chuàng)建穷蛹,然后放到適當(dāng)?shù)奈恢茫?/p>

image.png

接下來(lái)將組件綁定到腳本上株婴,先創(chuàng)建一個(gè)main腳本作為Game場(chǎng)景的践美,首先要考慮的是界面中的固定布局元素朗兵,比如:分?jǐn)?shù),暫停按鈕柿隙,炸彈等叶洞。所以腳本中先構(gòu)造這些布局元素:

properties: {
      pause: cc.Button,
      scoreDisplay: cc.Label,
      bombAmount: cc.Label,
      bombDisplay: cc.Node
    },
image.png

接下來(lái)分別給這些組件添加widge布局組件進(jìn)行布局處理。舉一個(gè)例子禀崖,其余的也差不多類似:

image.png

接下來(lái)處理暫停按鈕衩辟,要讓暫停按鈕按下后替換成開(kāi)始的按鈕,實(shí)現(xiàn)的思路很多波附,例如切換兩個(gè)button組件艺晴,這里使用替換圖片的方式。首先要在main腳本中添加按鈕圖片組:

let pause = false;

cc.Class({
    extends: cc.Component,

    properties: {
        pause: cc.Button,
        scoreDisplay: cc.Label,
        bombAmount: cc.Label,
        bombDisplay: cc.Node,
        pauseSprite: {
          default: [],
          type: cc.SpriteFrame,
          tooltip:'暫停按鈕圖片組',
        },
    },

    // use this for initialization
    onLoad: function () {

    },

    handlePause: function () {
        if (pause) {
            this.pause.normalSprite = this.pauseSprite[0];
            this.pause.pressedSprite = this.pauseSprite[1];
            this.pause.hoverSprite = this.pauseSprite[1];
            return pause = !pause
        }
        this.pause.normalSprite = this.pauseSprite[2];
        this.pause.pressedSprite = this.pauseSprite[3];
        this.pause.hoverSprite = this.pauseSprite[3];
        return pause = !pause;
    }


    // called every frame, uncomment this function to activate update callback
    // update: function (dt) {

    // },
});

這里需要注意
handlePause中使用了ES6的箭頭函數(shù)語(yǔ)法掸屡,但是this找不到上下文封寞,有可能是兼容上還有些問(wèn)題,保持function寫(xiě)法即可仅财。

image.png

這時(shí)可以啟動(dòng)游戲試試看是否如預(yù)期的結(jié)果那樣狈究。

Hero移動(dòng)

接下來(lái)來(lái)制作Hero。首先想一想可能面臨的問(wèn)題都有哪些盏求?
首先要處理玩家拖動(dòng)Hero移動(dòng)抖锥,接下來(lái)Hero是可以發(fā)射子彈的亿眠,當(dāng)然,Hero被敵機(jī)撞擊是會(huì)爆炸的磅废,爆炸涉及的是碰撞檢測(cè)后播放爆炸動(dòng)畫(huà)纳像。
那么先從Hero移動(dòng)開(kāi)始做起,先創(chuàng)建Hero精靈拯勉。


image.png

創(chuàng)建好Hero精靈后竟趾,需要將hero圖片添加到here節(jié)點(diǎn)上的Sprite屬性中的Sprite Frame中。然后還要添加一個(gè)動(dòng)畫(huà)組件谜喊,并且在左下角的資源區(qū)創(chuàng)建Animation資源。然后將其添加到hero節(jié)點(diǎn)上的Animation組件中倦始。
編輯動(dòng)畫(huà)如下所示:

image.png

接下來(lái)處理Hero移動(dòng)斗遏,游戲中按住Hero來(lái)進(jìn)行拖動(dòng),所以需要監(jiān)聽(tīng)“觸摸事件”類型鞋邑。CCC系統(tǒng)事件類型創(chuàng)建hero腳本來(lái)處理Hero相關(guān)的事物诵次。

cc.Class({
    extends: cc.Component,
    properties: {

    },
    // use this for initialization
    onLoad: function () {
        // 監(jiān)聽(tīng)拖動(dòng)事件
        this.node.on('touchmove', this.onHandleHeroMove, this);
    },
    
    onHandleHeroMove: function (event) {
        // touchmove事件中 event.getLocation() 獲取當(dāng)前已左下角為錨點(diǎn)的觸點(diǎn)位置(world point)
        let position = event.getLocation();
        // 實(shí)際hero是background的子元素,所以坐標(biāo)應(yīng)該是隨自己的父元素進(jìn)行的枚碗,所以要將“world point”轉(zhuǎn)化為“node point”
        let location = this.node.parent.convertToNodeSpaceAR(position);
        this.node.setPosition(location);
    }
});

接下來(lái)將腳本綁定到Hero精靈上就可以啟動(dòng)看看Hero已經(jīng)可以被拖動(dòng)了逾一。

Hero發(fā)射子彈

先想一下發(fā)射子彈這個(gè)動(dòng)作,需要怎么去實(shí)現(xiàn)肮雨?不知道大家有沒(méi)有注意過(guò)大街上的LED廣告牌遵堵,橫向移動(dòng)的字會(huì)讓你覺(jué)得“字”是在移動(dòng)的。而原理和幀動(dòng)畫(huà)差不多怨规,就是每個(gè)亮起的顯示單元不停的在變化陌宿,從而造成“移動(dòng)的錯(cuò)覺(jué)”。

子彈是否可以像這樣的實(shí)現(xiàn)思路去做呢波丰?把子彈依次排開(kāi)壳坪,鋪滿整個(gè)屏幕,Hero有一個(gè)出發(fā)點(diǎn)去觸發(fā)亮起的子彈掰烟,然后依次亮起該列向上所有的子彈爽蝴。我覺(jué)得是可以的,說(shuō)實(shí)話第一次看到這個(gè)游戲纫骑,第一時(shí)間想到的就是LED顯示牌蝎亚。

那么還是換一種更“cocos”的方式來(lái)做,和剛剛實(shí)現(xiàn)Hero移動(dòng)的方式一樣先馆。子彈是自動(dòng)發(fā)射颖对,所以要處理的是獲取到當(dāng)前Hero的位置,然后從當(dāng)前位置磨隘,不斷累加“positionY”的值來(lái)實(shí)現(xiàn)向上移動(dòng)缤底。

無(wú)限子彈(基礎(chǔ)版)

首先要明確一下游戲規(guī)則顾患,游戲中分為兩種類型的子彈,普通單道子彈和道具雙道子彈个唧,現(xiàn)在先來(lái)制作普通單道子彈江解。
有點(diǎn)需要注意,ccc中不斷重復(fù)創(chuàng)建的組件做成Prefab這個(gè)是很有必要的徙歼,雖然不用Prefab也是可以達(dá)到目的犁河。

首先把圖片資源從資源管理器中拖到層級(jí)管理器中,在屬性檢查器中調(diào)整好大小等參數(shù)后魄梯,將其拖拽到資源管理器相對(duì)應(yīng)的目錄下即可桨螺,然后刪除層級(jí)管理器中的原資源即可。(圖中屬性是隨意拖拽顯示的酿秸,具體請(qǐng)自己嘗試灭翔。)


image.png

接下來(lái)開(kāi)始編寫(xiě)腳本,首先需要知道的參數(shù)應(yīng)該有位置辣苏、速度這兩個(gè)參數(shù)目前就夠了肝箱,位置需要通過(guò)獲取Hero的位置原點(diǎn),速度可以由自己給出稀蟋,所以腳本如下:

// 提供思路參考用的代碼
cc.Class({
    extends: cc.Component,
    properties: {
        speed: cc.Integer,
        bullet: cc.Prefab
    },
    // use this for initialization
    onLoad: function () {
        // cc.instantiate() 克隆指定的任意類型的對(duì)象煌张,或者從 Prefab 實(shí)例化出新節(jié)點(diǎn)。
        this.newNode = cc.instantiate(this.bullet);
        this.node.addChild(this.newNode);
        this.newNode.setPosition({x: 0, y: 0});
    },
    // called every frame, uncomment this function to activate update callback
    update: function (dt) {
        this.newNode.y += dt * this.speed;
    },
});

起初我的想法是退客,將上述腳本綁在Hero上骏融,這樣{x: 0, y: 0}就是子彈發(fā)出的起始點(diǎn),但是實(shí)際運(yùn)行中萌狂,出現(xiàn)的問(wèn)題是绎谦,Hero是需要移動(dòng)的,子彈Prefab也就作為了Hero的子元素粥脚,會(huì)隨著Hero移動(dòng)而移動(dòng)窃肠,如下GIF所以:

image.png

所以子彈應(yīng)該單獨(dú)作為一層去處理,或者將bullet腳本綁在“background”層上刷允,然后將Hero的位置通過(guò)傳參的形式傳過(guò)來(lái)即可冤留。參考代碼是單獨(dú)用子彈層處理所有子彈的事件,所以也參考這種做法树灶,用單獨(dú)的層級(jí)去處理這個(gè)層級(jí)的所有相關(guān)事物纤怒。

在層級(jí)管理器中創(chuàng)建空節(jié)點(diǎn)并命名為bulletGroup,這個(gè)節(jié)點(diǎn)需要做的事就是處理Hero與Bullet的發(fā)射位置與發(fā)射頻率天通。所以首先需要的就是HeroBullet-Prefab泊窘,發(fā)射頻率的話,需要用到ccc中的定時(shí)器來(lái)實(shí)現(xiàn)固定間隔創(chuàng)建bullet節(jié)點(diǎn)并發(fā)射炮彈的功能,所以需要一個(gè)cc.Integer類型的變量烘豹。
有一個(gè)非常值得注意的性能問(wèn)題:

在運(yùn)行時(shí)進(jìn)行節(jié)點(diǎn)的創(chuàng)建(cc.instantiate)和銷毀(node.destroy)操作是非常耗費(fèi)性能的瓜贾,因此在比較復(fù)雜的場(chǎng)景中,通常只有在場(chǎng)景初始化邏輯(onLoad)中才會(huì)進(jìn)行節(jié)點(diǎn)的創(chuàng)建携悯,在切換場(chǎng)景時(shí)才會(huì)進(jìn)行節(jié)點(diǎn)的銷毀祭芦。

所以,要實(shí)現(xiàn)不間斷發(fā)射子彈憔鬼,除了定時(shí)器龟劲,還需要引入對(duì)象池(cc.NodePool)

無(wú)限子彈(進(jìn)階版)

下面開(kāi)始構(gòu)建腳本:
首先修改腳本bullet.js轴或,bullet作為Prefab昌跌,只需要完成自己作為子彈的使命,那就是發(fā)射照雁,銷毀蚕愤,碰撞檢測(cè)。所以先來(lái)做一個(gè)只有發(fā)射的基礎(chǔ)子彈腳本囊榜。

cc.Class({
    extends: cc.Component,

    properties: {
        speed: cc.Integer,
    },

    // use this for initialization
    onLoad: function () {

    },
    // called every frame, uncomment this function to activate update callback
    update: function (dt) {
        this.node.y += dt * this.speed;
    },
});

然后將腳本添加到bullet的Prefab上审胸,設(shè)定速度為1500亥宿。


image.png

接著開(kāi)始編寫(xiě)bulletGroup的腳本:

cc.Class({
    extends: cc.Component,

    properties: {
        bullet: cc.Prefab,
        hero: cc.Node,
        rate: cc.Integer
    },

    onLoad: function () {
            // 創(chuàng)建子彈對(duì)象池
        this.genBulletPool();
            // 設(shè)置定時(shí)器卸勺,每個(gè)0.2s創(chuàng)建一個(gè)新的bullet
        this.schedule(function () {
            this.startShoot(this.bulletPool)
        }.bind(this), this.rate);
    },

    genBulletPool: function () {
        this.bulletPool = new cc.NodePool();
        let initCount = 100;
        for (let i = 0; i < initCount; ++i) {
            let newBullet = cc.instantiate(this.bullet); // 創(chuàng)建節(jié)點(diǎn)
            this.bulletPool.put(newBullet); // 通過(guò) putInPool 接口放入對(duì)象池
        }
    },
    //獲取子彈位置
    getBulletPosition: function(){
        let heroP = this.hero.getPosition();
        let newV2_x = heroP.x;
        let newV2_y = heroP.y;
        return cc.p(newV2_x, newV2_y);
    },
      // 發(fā)射子彈
    startShoot: function (pool) {
        let newNode = null;
        if (pool.size() > 0) {
            newNode = pool.get();
            this.node.addChild(newNode);
            let p = this.getBulletPosition();
            newNode.setPosition(p);
        }
    },
    //銷毀子彈
    destroyBullet: function (bullet) {
    }

    // called every frame, uncomment this function to activate update callback
    // update: function (dt) {

    // },
});

然后將組建綁到腳本上:


image.png

bulletGroup腳本中,直接給對(duì)象池中放了一百發(fā)子彈烫扼,打完了卻沒(méi)有回收曙求,這是不合理的,接下來(lái)要處理的就是回收資源映企。要注意的是對(duì)象池中的數(shù)量與發(fā)射子彈的關(guān)系悟狱,如果對(duì)象池中的對(duì)象用完了,而這時(shí)卻沒(méi)有及時(shí)補(bǔ)充堰氓,就會(huì)“延遲發(fā)貨”挤渐。可以試著調(diào)整bulletCount來(lái)驗(yàn)證效果双絮。如果對(duì)象池中的對(duì)象太多浴麻,每次最多只能用10個(gè),之后就會(huì)被補(bǔ)充進(jìn)來(lái)囤攀,那么剩下的就會(huì)浪費(fèi)了软免。
如下bulletGroup.js:

cc.Class({
    extends: cc.Component,

    properties: {
        bullet: cc.Prefab,
        hero: cc.Node,
        rate: cc.Integer,
        bulletCount: {
            default: 10,
            type: cc.Integer
        }
    },

    onLoad: function () {
        this.genBulletPool();
        this.schedule(function () {
            this.startShoot(this.bulletPool)
        }.bind(this), this.rate);
           // 將對(duì)象池添加到window對(duì)象中,方便瀏覽器查看對(duì)象池狀態(tài)
        window.pool = this.bulletPool;
    },

    genBulletPool: function () {
        this.bulletPool = new cc.NodePool();
        for (let i = 0; i < this.bulletCount; ++i) {
            let newBullet = cc.instantiate(this.bullet); // 創(chuàng)建節(jié)點(diǎn)
            this.bulletPool.put(newBullet); // 通過(guò) putInPool 接口放入對(duì)象池
        }
    },
    //獲取子彈位置
    getBulletPosition: function(){
        let heroP = this.hero.getPosition();
        let newV2_x = heroP.x;
        let newV2_y = heroP.y;
        return cc.p(newV2_x, newV2_y);
    },
    startShoot: function (pool) {
        let newNode = null;
        if (pool.size() > 0) {
            newNode = pool.get();
            this.node.addChild(newNode);
            let p = this.getBulletPosition();
            newNode.setPosition(p);
            newNode.getComponent('bullet').bulletGroup = this;
        }
    },

    // called every frame, uncomment this function to activate update callback
    // update: function (dt) {

    // },
});
image.png

子彈的銷毀就是當(dāng)子彈飛出屏幕之后峰髓,將其重新放回對(duì)象池中尺栖,這樣一直都是對(duì)象池中的對(duì)象在被使用楣导,而沒(méi)有不斷創(chuàng)建新的對(duì)象闰歪。目前先在bullet腳本中去處理對(duì)象銷毀榛泛。

cc.Class({
    extends: cc.Component,

    properties: {
        speed: cc.Integer,
    },

    // use this for initialization
    onLoad: function () {

    },
    // called every frame, uncomment this function to activate update callback
    update: function (dt) {
        this.node.y += dt * this.speed;
        if (this.node.y > this.node.parent.height){
            this.bulletGroup.bulletPool.put(this.node);
        }
    },
});

目前無(wú)限子彈類型已經(jīng)差不多完成了蝌蹂,但是只是實(shí)現(xiàn)了功能,接下來(lái)做雙彈道的子彈挟鸠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末叉信,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子艘希,更是在濱河造成了極大的恐慌硼身,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件覆享,死亡現(xiàn)場(chǎng)離奇詭異佳遂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)撒顿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門丑罪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人凤壁,你說(shuō)我怎么就攤上這事吩屹。” “怎么了拧抖?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵煤搜,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我唧席,道長(zhǎng)擦盾,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任淌哟,我火速辦了婚禮迹卢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘徒仓。我一直安慰自己腐碱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布掉弛。 她就那樣靜靜地躺著症见,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狰晚。 梳的紋絲不亂的頭發(fā)上筒饰,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音壁晒,去河邊找鬼瓷们。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谬晕。 我是一名探鬼主播碘裕,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼攒钳!你這毒婦竟也來(lái)了帮孔?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤不撑,失蹤者是張志新(化名)和其女友劉穎文兢,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體焕檬,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姆坚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了实愚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兼呵。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖腊敲,靈堂內(nèi)的尸體忽然破棺而出击喂,到底是詐尸還是另有隱情,我是刑警寧澤碰辅,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布懂昂,位于F島的核電站,受9級(jí)特大地震影響乎赴,放射性物質(zhì)發(fā)生泄漏忍法。R本人自食惡果不足惜潮尝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一榕吼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧勉失,春花似錦羹蚣、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至徒蟆,卻和暖如春胁出,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背段审。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工全蝶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓抑淫,卻偏偏與公主長(zhǎng)得像绷落,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子始苇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容