[Cocos Creator Press Tutorial (8)] – Titting Bricks (Physics Engine)

Reproduced from: http://blog.csdn.net/potato47/article/details/73197021

Return of missing persons


Create a new project and call it brick-breaker. What does brick mean? It means brick. Every time I name a project, I can learn a new word.

The directory structure is as follows:

game scene, set Canvas
Set up a game background first
Build another physical layer to install things with physical attributes in the game, set the anchor point to the lower left corner
It’s time to learn vocabulary again, please take it Write your notebook:

wall: Wall//The kind of wall where the ball will bounce when it hits it.< br>ground: the ground//the ball hits the ground, the game is over
brick_layout: the brick layout//This word we have talked about before Don’t talk about it
ball: Ball//Just It’s a ball
paddle: Paddle//This specifically refers to the white rectangle that can control movement

This wall is sure To have collision properties, add a physical component in the properties panel
Because our wall has top, left and right sides, we add three more collision components (a node can have multiple collision components).
Edit it
same ground, small ball In the same way, the tray is the same.
Now the collision bounding box of several physical nodes has been edited, but their physical properties (cc.RigidBody) have not been edited yet

Start with the small ball, click on the ball node, you can see it in the property inspector

put The first parameter is checked, which means that the collision callback is enabled. You can write the callback function in the script.

Bullet: Turn on high-speed objects to avoid penetration , Do not check here

type select Dynamic,

static: will not be affected by force, will not be affected by speed, refers to the physics engine, we can still change the position by moving nodes
kinematic: not affected by force , Will be affected by speed
dynamic: affected by force, affected by speed
animated: It is said that it is used in combination with animation, but I haven’t figured it out yet. . .

Why not choose kinematic? Leave an assignment.

Gravity Scale is set to 0 (the standard is 1, the value represents the scale), that is, there is no gravity.

Set line speed (1000,1000)

Because the small ball is our protagonist, the collision between the left and right is for the ball, so the collision properties are all Just set it on the side of the small ball.

In addition, set the type of wall, ground, paddle, and brick to static
brick tag Is 1,
ground’s tag is 2,
paddle’s tag is 3,
wall’s tag is 4

below Look at the script

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  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 span> = -this.padding-Math.floor(i / this.cols) * (brickNode.height + this.spacing)-brickNode .height / 2;} }} );
  • 1< /li>
  • 2
  • 3< /li>
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • < li>16

  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

I wrote a layout script for dynamically adding bricks. You can add the number of bricks that need to be added dynamically. In the layout node.

BrickPrefab is so long, I will prefab by default
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();} });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

End interface
Paddle.js

cc.Class({ extends: cc.Component, onLoad: function () {this.node.parent.on("touchmove", (event) => {//Convert world coordinates to local coordinates let touchPoint = this.node< span class="hljs-preprocessor">.parent .convertToNodeSpace(event.getLocation()); this.node.x = touchPoint.x; }); }, init(){ this.node.x = 360; }});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

The tray moves with the finger

< p style="background-color:rgb(255,255,255);">< span style="font-weight:700;">Ball.js

cc.Class({ extends: cc.Component, properties : {}, init(gameCtl) {this.gameCtl = gameCtl; this.node.position = cc.v2(360,270);//initialization location this.getComponent(cc.RigidBody).linearVelocity = cc.v2(800,800 );//initialization speed  }, onBeginContact(contact, self, other) {switch (other.tag) {case 1://The ball hits a brick this.gameCtl.onBallContactBrick(self.node, other.node); break; case 2://ball hits the ground this< span class="hljs-preprocessor">.gameCtl.onBallContactGround(self.node, other.node); break; case 3://ball hit Tray this.gameCtl.onBallContactPaddle(self.node, other.node); break; case 4://ball hits the wall this .gameCtl.onBallContactWall(self.node, other.node); break; } },});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • < li>15

  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27< /li>
  • 28
  • 29
  • 30

The ball hits Let gameCtl handle other objects

GameCtl.js< /span>

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 span> initialization onLoad: function () {//< /span>Android return key to exit 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 span>(); }, //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< /span> //; init() {this< /span>.physicsManager.enabled = true; this.gameModel.init(); this.gameView.init(this ); this.ball.init< /span>(this); this .paddle.init(); < span class="hljs-title">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< /span> = false; this.overPanel.show(this.gameModel.score, this.gameModel.bricksNumber === 0); },  onBallContactBrick(ballNode, brickNode) {brickNode.parent = null; this.gameModel .addScore(1); this.gameModel.minusBrick< span class="hljs-params">(1); this.gameView.updateScore(this.gameModel.score); if (this.gameModel.bricksNumber <= 0) {this< /span>.stopGame();} }, onBallContactGround (ballNode, groundNode) {this. stopGame(); }, onBallContactPaddle( ballNode, paddleNode) {}, onBallContactWall(ballNode, brickNode) {}, onDestroy() {this.physicsManager.enabled = false;} });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • < li>7

  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19< /li>
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • < li>32

  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44< /li>
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • < li>57

  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

GameCtl hangs on Canvas, guarantees the first execution, will correspond Drag the components into
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;  }});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • < li>7

  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

GameModel.js

cc.Class({ extends: cc.Component, properties: {score:0, bricksNumber:0, }, init(){ this. score = 0; this.bricksNumber< /span> = 50; }, addScore(score){ this.score += score; }, minusBrick(n){ this.bricksNumber -= n; },});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Try The mvc written is not standardized. The simple understanding is that the model and the view are separated, and the communication is through the control.

Logically clear code does not require much explanation, right, right.

The source code is here: https://github.com/potato47/brick-breaker-master

Game demo: http://119.29.40.244/brick-breaker/

Caring for missing persons:< /p>

The “Programmer before Graduation” series is being updated…If you don’t pay attention, you will miss the growth of a genius…233

Reposted from: http://blog.csdn.net/potato47/article/details/73197021

Return of missing persons


Create a new project and name it brick-breaker. What does brick mean? It means brick. Every time I name a project, I can learn a new word .

The directory structure is as follows:

game scene, set Canvas
Set up a game background first
build another physical layer to install things with physical attributes in the game, set the anchor point to the lower left corner
< img src="/wp-content/uploads/images/mobile/cocos2dx/1626793176898.net/20170613230306920

又到了学单词的时间,请拿出你们的小本本:

wall:墙//小球碰到就会反弹的那种墙 
ground:地面//球碰到地面,这局游戏就结束了 
brick_layout:砖块布局//这个单词我们之前讲过了就不讲了 
ball:球//就是球 
paddle:桨//这里特指那个可以控制移动的白色长方形

这个wall肯定是要有碰撞属性的,在属性面板,添加一个物理组件 
因为我们的墙有上,左,右三面,所以再添加三个碰撞组件(一个节点可以有多个碰撞组件)。 
编辑一下 
地面同理,小球同理,托盘同理 
现在已经编辑了几个物理节点的碰撞包围盒,但还没有编辑他们的物理属性(cc.RigidBody)

先从小球开始,点击ball节点,在属性检查器可以看到

把第一个参数勾选,代表启用碰撞回调,可以在脚本里写回调函数

Bullet:高速运动的物体开启,避免穿透,这里不用勾选

type选择Dynamic,

static:不会受到力的影响,不会受到速度影响,指的是物理引擎,我们依然可以通过移动节点来改变位置 
kinematic:不受力的影响,会受到速度影响 
dynamic:受力影响,受速度影响 
animated:据说和动画结合使用,我还没弄懂。 . .

为什么不选kinematic呢?留个作业。

Gravity Scale设置为0(标准是1,数值代表比例),也就是没有重力。

设置线速度(1000,1000)

因为小球是我们的主角,左右的碰撞都是对球来说的,所以碰撞属性都在小球这一方设置就可以了。

另外要设置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;        }    }});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

自己写了一个动态添加砖块的布局脚本,传入需要添加的砖块数量就可以动态加入的布局节点中。

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();    }});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

结束界面 
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;    }});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

托盘随着手指移动

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; } },});

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

球碰到其他物体,让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< /span>.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; } });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

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;    }});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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;    },});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

尝试着写的mvc,并不规范,简单的理解就是,model和view分离,沟通都通过control。

逻辑清楚的代码是不需要过多讲解的,对吧,对的。

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

游戏试玩:http://119.29.40.244/brick-breaker/

关爱失踪人口:

《毕业前的程序员》系列正在更新。。。如果你不关注,你就会错过一个天才的成长历程。。。233

Leave a Comment

Your email address will not be published.