【Cocos Creator實戰教程(8)】——打磚塊(物理引擎)

來源:互聯網
上載者:User

失蹤人口迴歸


本篇教程要基於Cocos Creator1.5的物理引擎,編寫一個簡單的打磚塊遊戲,儘可能多講一點,但現在已經快11點了,我12點要睡覺啊,好像又講不了多少,這個世界啊,本來就是一個矛盾體。

建立一個工程,取名叫做brick-breaker,brick是什麼意思呢,就是磚塊的意思,每次給工程起名字,我都能學會一個新單詞。

目錄結構如下:

game情境,設定Canvas

先搭一個遊戲背景

(因為我已經做完了,我就不從頭做一遍了,所以暫時用不到的節點我就把active關掉)

再建一個物理層,用來裝遊戲裡的帶有物理屬性的東西,設定錨點為左下角

又到了學單詞的時間,請拿出你們的小本本:

wall:牆//小球碰到就會反彈的那種牆
ground:地面//球碰到地面,這局遊戲就結束了
brick_layout:磚塊布局//這個單詞我們之前講過了就不講了
ball:球//就是球
paddle:槳//這裡特指那個可以控制移動的白色長方形

這個wall肯定是要有碰撞屬性的,在屬性面板,添加一個物理組件

因為我們的牆有上,左,右三面,所以再添加三個碰撞組件(一個節點可以有多個碰撞組件)。

編輯一下

地面同理,小球同理,托盤同理

(這裡把地面和牆分開是為了後面牆和地面可能有不同的邏輯)

現在已經編輯了幾個物理節點的碰撞包圍盒,但還沒有編輯他們的物理屬性(cc.RigidBody)

先從小球開始,點擊ball節點,在屬性偵測器可以看到

把第一個參數勾選,代表啟用碰撞回調,可以在指令碼裡寫回呼函數

Bullet:高速運動的物體開啟,避免穿透,這裡不用勾選

type選擇Dynamic,

static:不會受到力的影響,不會受到速度影響,指的是物理引擎,我們依然可以通過移動節點來改變位置
kinematic:不受力的影響,會受到速度影響
dynamic:受力影響,受速度影響
animated:據說和動畫結合使用,我還沒弄懂。。。

為什麼不選kinematic呢。留個作業。

Gravity Scale設定為0(標準是1,數值代表比例),也就是沒有重力。

設定線速度(1000,1000)


在下面的碰撞組件裡,設定Friction (摩擦係數)等於0(沒有摩擦力),Restitution(彈性係數)等於1(沒有動量損耗)

因為小球是我們的主角,左右的碰撞都是對球來說的,所以碰撞屬性都在小球這一方設定就可以了。

另外要設定wall,ground,paddle,brick的type為static
brick的tag為1,
ground的tag為2,
paddle的tag為3,
wall的tag位4

下面來看指令碼

BrickLayout.js

cc.Class({    extends: cc.Component,    properties: {        padding: 0,        spacing: 0,        cols: 0,        brickPrefab: cc.Prefab,        bricksNumber: 0,    },    init(bricksNumber) {        this.node.removeAllChildren();        this.bricksNumber = bricksNumber;        for (let i = 0; i < this.bricksNumber; i++) {            let brickNode = cc.instantiate(this.brickPrefab);            brickNode.parent = this.node;            brickNode.x = this.padding + (i % this.cols) * (brickNode.width + this.spacing) + brickNode.width / 2;            brickNode.y = -this.padding - Math.floor(i / this.cols) * (brickNode.height + this.spacing) - brickNode.height / 2;        }    }});

自己寫了一個動態添加磚塊的布局指令碼,傳入需要添加的磚塊數量就可以動態加入的布局節點中。

BrickPrefab長這樣,我就預設你會做prefab了

OverPanel.js

cc.Class({    extends: cc.Component,    properties: {        resultLabel:cc.Label,        scoreLabel:cc.Label,    },    // use this for initialization    onLoad: function () {    },    init(gameCtl){        this.gameCtl = gameCtl;        this.node.active = false;    },    show(score,isWin){        this.node.active = true;        if(isWin){            this.resultLabel.string = 'YOU WIN!';        }else{            this.resultLabel.string = 'YOU LOSE!';        }        this.scoreLabel.string = score+'';    },    onBtnRestart(){        this.gameCtl.startGame();    }});

結束介面

Paddle.js

cc.Class({    extends: cc.Component,    onLoad: function () {        this.node.parent.on("touchmove", (event) => {            //將全局座標轉化為本地座標            let touchPoint = this.node.parent.convertToNodeSpace(event.getLocation());            this.node.x = touchPoint.x;        });    },    init(){        this.node.x = 360;    }});

托盤隨著手指移動

Ball.js

cc.Class({    extends: cc.Component,    properties: {    },    init(gameCtl) {        this.gameCtl = gameCtl;        this.node.position = cc.v2(360,270);//初始化位置        this.getComponent(cc.RigidBody).linearVelocity = cc.v2(800,800);//初始化速度    },    onBeginContact(contact, self, other) {        switch (other.tag) {            case 1://球碰到磚塊                this.gameCtl.onBallContactBrick(self.node, other.node);                break;            case 2://球碰到地面                this.gameCtl.onBallContactGround(self.node, other.node);                break;            case 3://球碰到托盤                this.gameCtl.onBallContactPaddle(self.node, other.node);                break;            case 4://球碰到牆                this.gameCtl.onBallContactWall(self.node, other.node);                break;        }    },});

球碰到其他物體,讓gameCtl處理

GameCtl.js

const GameModel = require('GameModel');cc.Class({    extends: cc.Component,    properties: {        gameView: require('GameView'),        ball: require('Ball'),        paddle: require('Paddle'),        brickLayout: require('BrickLayout'),        overPanel: require('OverPanel'),    },    // use this for initialization    onLoad: function () {        //安卓返回鍵退出        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, (event) => {            if (event.keyCode === cc.KEY.back) {                cc.director.end();            }        });        this.physicsManager = cc.director.getPhysicsManager();        this.gameModel = new GameModel();        this.startGame();    },    //this.physicsManager.debugDrawFlags =0;    // cc.PhysicsManager.DrawBits.e_aabbBit |    // cc.PhysicsManager.DrawBits.e_pairBit |    // cc.PhysicsManager.DrawBits.e_centerOfMassBit |    // cc.PhysicsManager.DrawBits.e_jointBit |    // cc.PhysicsManager.DrawBits.e_shapeBit    // ;     init() {        this.physicsManager.enabled = true;        this.gameModel.init();        this.gameView.init(this);        this.ball.init(this);        this.paddle.init();        this.brickLayout.init(this.gameModel.bricksNumber);        this.overPanel.init(this);    },    startGame() {        this.init();    },    pauseGame() {        this.physicsManager.enabled = false;    },    resumeGame() {        this.physicsManager.enabled = true;    },    stopGame() {        this.physicsManager.enabled = false;        this.overPanel.show(this.gameModel.score, this.gameModel.bricksNumber === 0);    },    onBallContactBrick(ballNode, brickNode) {        brickNode.parent = null;        this.gameModel.addScore(1);        this.gameModel.minusBrick(1);        this.gameView.updateScore(this.gameModel.score);        if (this.gameModel.bricksNumber <= 0) {            this.stopGame();        }    },    onBallContactGround(ballNode, groundNode) {        this.stopGame();    },    onBallContactPaddle(ballNode, paddleNode) {    },    onBallContactWall(ballNode, brickNode) {    },    onDestroy() {        this.physicsManager.enabled = false;    }});

GameCtl掛在Canvas上,保證第一個執行,將對應的組件拖入

GameView.js

cc.Class({    extends: cc.Component,    properties: {        scoreLabel:cc.Label,    },    init(gameCtl){        this.gameCtl = gameCtl;        this.scoreLabel.string = '0';    },    updateScore(score){        this.scoreLabel.string = score;    }});

GameModel.js

cc.Class({    extends: cc.Component,    properties: {        score:0,        bricksNumber:0,    },    init(){        this.score = 0;        this.bricksNumber = 50;    },    addScore(score){        this.score += score;    },    minusBrick(n){        this.bricksNumber -= n;    },});

嘗試著寫的mvc,並不規範,簡單的理解就是,model和view分離,溝通都通過control。

邏輯清楚的代碼是不需要過多講解的,對吧,對的。

源碼在此:https://github.com/potato47/brick-breaker-master

遊戲試玩:http://119.29.40.244/brick-breaker/

關愛失蹤人口:

《畢業前的程式員》系列正在更新。。。如果你不關注,你就會錯過一個天才的成長曆程。。。233

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.