【Cocos Creator实战教程(8)】——打砖块(物理引擎)

【Cocos Creator实战教程(8)】——打砖块(物理引擎),第1张

概述转自:http://blog.csdn.net/potato47/article/details/73197021 失踪人口回归   本篇教程要基于Cocos Creator1.5的物理引擎,编写一个简单的打砖块游戏,尽可能多讲一点,但现在已经快11点了,我12点要睡觉啊,好像又讲不了多少,这个世界啊,本来就是一个矛盾体。 新建一个工程,取名叫做brick-breaker,brick是什么意思呢,

转自:http://blog.csdn.net/potato47/article/details/73197021

失踪人口回归



本篇教程要基于Cocos Creator1.5的物理引擎,编写一个简单的打砖块游戏,尽可能多讲一点,但现在已经快11点了,我12点要睡觉啊,好像又讲不了多少,这个世界啊,本来就是一个矛盾体。

新建一个工程,取名叫做brick-breaker,brick是什么意思呢,就是砖块的意思,每次给工程起名字,我都能学会一个新单词。

目录结构如下:

game场景,设置Canvas

先搭一个游戏背景

(因为我已经做完了,我就不从头做一遍了,所以暂时用不到的节点我就把active关掉)

再建一个物理层,用来装游戏里的带有物理属性的东西,设置锚点为左下角

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

wall:墙//小球碰到就会反d的那种墙
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(d性系数)等于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;        }    }});
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.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;    },221);">   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

总结

以上是内存溢出为你收集整理的【Cocos Creator实战教程(8)】——打砖块(物理引擎)全部内容,希望文章能够帮你解决【Cocos Creator实战教程(8)】——打砖块(物理引擎)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1085631.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-27
下一篇2022-05-27

发表评论

登录后才能评论

评论列表(0条)

    保存