cocos creator怎么做cocoscreator碰撞检测测

1821人阅读
Cocos Creator实战教程(9)
最后一个寒假说没就没。。。
话说我等Creator 的物理引擎等了好久好久,终于。。。。。。还是没等到。。。。。。
我们今天就用碰撞检测系统和一些算法简单的模拟一下2D平台动作的物理特性吧
先来看一下我们的主角
是不是很可爱啊
所以我们要给她起一个可爱的名字,
就叫她大马猴吧。。。
水平移动:
我们先来实现一下按键控制大马猴左右移动的效果
用渲染节点里的单色Sprite(后面的平台也用这个)制作一个地面平台,把大马猴放在地面上
新建MonkeyControl脚本,挂载在大马猴节点上
MonkeyControl.js
cc.Class({
extends: cc.Component,
properties: {
maxSpeed:0,
direction: 0
onLoad: function () {
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this)
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this)
onDestroy() {
cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this)
cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this)
onKeyDown(event) {
switch (event.keyCode) {
case cc.KEY.a:
case cc.KEY.left:
this.direction = -1
case cc.KEY.d:
case cc.KEY.right:
this.direction = 1
onKeyUp(event) {
switch (event.keyCode) {
case cc.KEY.a:
case cc.KEY.left:
case cc.KEY.d:
case cc.KEY.right:
this.direction = 0
update: function (dt) {
if (this.direction === 0) {
if (this.speed & 0) {
this.speed -= this.acce * dt
if (this.speed &= 0) this.speed = 0
else if (this.speed & 0) {
this.speed += this.acce * dt
if (this.speed &= 0) this.speed = 0
this.speed += (this.direction & 0 ? 1 : -1) * this.acce * dt
if (Math.abs(this.speed) & this.maxSpeed) {
this.speed = this.speed & 0 ? this.maxSpeed : -this.maxSpeed
this.node.x += this.speed * dt
我们在大马猴的控制脚本里加了四个属性
speed:x轴的速度
maxSpeed:x轴的最大速度,避免大马猴越跑越快
acce:x轴加速度
direction:按键控制方向,-1:左(按下左键),1:右(按下右键),0:不动(松开按键)
通常对物体运动的位置计算会放在update函数里,核心逻辑就是:位移=速度x时间,速度=加速度x时间
update这个函数是一个循环周期函数,每隔一个固定的时间(dt)就会调用一次
这里的if,else部分就是为了得出本次update的速度,然后根据速度乘时间更新本次大马猴的位置
如果感觉不好理解,是时候拿出高中物理课本复习一遍了
设置一下参数:
效果如下:
突然脑子里响起了广播体操的音乐。。。
修改MonkeyControl.js
cc.Class({
extends: cc.Component,
properties: {
speed: cc.v2(0, 0),
maxSpeed: cc.v2(0, 0),
direction: 0,
jumpSpeed:0,
gravity:0,
groundY: 0
onLoad: function () {
this.groundY = this.node.y
this.jumping = false
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this)
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this)
onDestroy() {
cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this)
cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this)
onKeyDown(event) {
switch (event.keyCode) {
case cc.KEY.a:
case cc.KEY.left:
this.direction = -1
case cc.KEY.d:
case cc.KEY.right:
this.direction = 1
case cc.KEY.w:
case cc.KEY.up:
if(!this.jumping){
this.jumping = true
this.speed.y = this.jumpSpeed
onKeyUp(event) {
switch (event.keyCode) {
case cc.KEY.a:
case cc.KEY.left:
case cc.KEY.d:
case cc.KEY.right:
this.direction = 0
update: function (dt) {
if (this.jumping) {
this.speed.y += this.gravity * dt
if (Math.abs(this.speed.y) & this.maxSpeed.y) {
this.speed.y = this.speed.y & 0 ? this.maxSpeed.y : -this.maxSpeed.y
if (this.direction === 0) {
if (this.speed.x & 0) {
this.speed.x -= this.acce * dt
if (this.speed.x &= 0) this.speed.x = 0
else if (this.speed.x & 0) {
this.speed.x += this.acce * dt
if (this.speed.x &= 0) this.speed.x = 0
this.speed.x += (this.direction & 0 ? 1 : -1) * this.acce * dt
if (Math.abs(this.speed.x) & this.maxSpeed.x) {
this.speed.x = this.speed.x & 0 ? this.maxSpeed.x : -this.maxSpeed.x
this.node.x += this.speed.x * dt
this.node.y += this.speed.y * dt
if(this.node.y &= this.groundY){
this.node.y = this.groundY
this.jumping = false
这里我们给大马猴又加了几个属性
jumpSpeed:起跳速度
gravity:重力
groundY:大马猴落到地面时的Y轴位置
同时把speed和maxSpeed都变成了二维的
测试参数:
效果如下:
利用碰撞检测实现平台动作
首先我们再添加一个平台节点,然后给地面,平台和大马猴都添加碰撞组件
修改MonkeyControl.js
cc.Class({
extends: cc.Component,
properties: {
speed: cc.v2(0, 0),
maxSpeed: cc.v2(0, 0),
direction: 0,
jumpSpeed: 0,
gravity: 0,
onLoad: function () {
cc.director.getCollisionManager().enabled = true
cc.director.getCollisionManager().enabledDebugDraw = true
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this)
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this)
this.jumping = false
this.collisionX = 0
this.collisionY = 0
this.touchingNumber = 0
onDestroy() {
cc.director.getCollisionManager().enabled = false
cc.director.getCollisionManager().enabledDebugDraw = false
cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this)
cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this)
onKeyDown(event) {
switch (event.keyCode) {
case cc.KEY.a:
case cc.KEY.left:
this.direction = -1
case cc.KEY.d:
case cc.KEY.right:
this.direction = 1
case cc.KEY.w:
case cc.KEY.up:
if (!this.jumping) {
this.jumping = true
this.speed.y = this.jumpSpeed
onKeyUp(event) {
switch (event.keyCode) {
case cc.KEY.a:
case cc.KEY.left:
case cc.KEY.d:
case cc.KEY.right:
this.direction = 0
onCollisionEnter: function (other, self) {
this.node.color = cc.Color.RED
this.touchingNumber++
// 1st step
// get pre aabb, go back before collision
var otherAabb = other.world.aabb
var otherPreAabb = other.world.preAabb.clone()
var selfAabb = self.world.aabb
var selfPreAabb = self.world.preAabb.clone()
// 2nd step
// forward x-axis, check whether collision on x-axis
selfPreAabb.x = selfAabb.x
otherPreAabb.x = otherAabb.x
if (cc.Intersection.rectRect(selfPreAabb, otherPreAabb)) {
if (this.speed.x & 0 && (selfPreAabb.xMax & otherPreAabb.xMax)) {
this.node.x = otherPreAabb.xMax - this.node.parent.x
this.collisionX = -1
else if (this.speed.x & 0 && (selfPreAabb.xMin & otherPreAabb.xMin)) {
this.node.x = otherPreAabb.xMin - selfPreAabb.width - this.node.parent.x
this.collisionX = 1
this.speed.x = 0
other.touchingX = true
// 3rd step
// forward y-axis, check whether collision on y-axis
selfPreAabb.y = selfAabb.y
otherPreAabb.y = otherAabb.y
if (cc.Intersection.rectRect(selfPreAabb, otherPreAabb)) {
if (this.speed.y & 0 && (selfPreAabb.yMax & otherPreAabb.yMax)) {
this.node.y = otherPreAabb.yMax - this.node.parent.y
this.jumping = false
this.collisionY = -1
else if (this.speed.y & 0 && (selfPreAabb.yMin & otherPreAabb.yMin)) {
this.node.y = otherPreAabb.yMin - selfPreAabb.height - this.node.parent.y
this.collisionY = 1
this.speed.y = 0
other.touchingY = true
onCollisionExit: function (other) {
this.touchingNumber--
if (this.touchingNumber === 0) {
this.node.color = cc.Color.WHITE
if (other.touchingX) {
this.collisionX = 0
other.touchingX = false
else if (other.touchingY) {
other.touchingY = false
this.collisionY = 0
this.jumping = true
update: function (dt) {
if (this.collisionY === 0) {//如果Y轴没有碰撞
this.speed.y += this.gravity * dt
if (Math.abs(this.speed.y) & this.maxSpeed.y) {
this.speed.y = this.speed.y & 0 ? this.maxSpeed.y : -this.maxSpeed.y
if (this.direction === 0) {
if (this.speed.x & 0) {
this.speed.x -= this.acce * dt
if (this.speed.x &= 0) this.speed.x = 0
else if (this.speed.x & 0) {
this.speed.x += this.acce * dt
if (this.speed.x &= 0) this.speed.x = 0
this.speed.x += (this.direction & 0 ? 1 : -1) * this.acce * dt
if (Math.abs(this.speed.x) & this.maxSpeed.x) {
this.speed.x = this.speed.x & 0 ? this.maxSpeed.x : -this.maxSpeed.x
if (this.speed.x * this.collisionX & 0) {
this.speed.x = 0
this.node.x += this.speed.x * dt
this.node.y += this.speed.y * dt
碰撞检测系统有三个检测碰撞的函数,分别是:
onCollisionEnter(other,self):碰撞体刚碰撞时触发
onCollisionStay(other,self):碰撞体持续碰撞时触发
onCollisionExit(other):碰撞体分开时触发
他们传入的参数other和self指的是什么呢?
指的就是他们的碰撞组件
比如我们在onCollisionEnter函数里写上这样两行代码
other.node.color = cc.Color.RED;
self.node.color = cc.Color.GREEN;
就可以实现让两个碰撞组件的节点变色的效果
那碰撞组件(这里用的是cc.BoxCollider)里还有什么属性方法呢?
通常我们遇到这种问题时,第一反应就是去查一下api,可是人生充满意外,Creator的api并不全,很多东西都没有
这里我给新手介绍一个查看属性的方法
我们这次不用模拟器,选择浏览器(谷歌浏览器)运行,按下F12启动调试窗口,然后在onCollisionEnter函数的第一行代码旁边单击设置一个断点,然后刷新浏览器
这样我们的程序就会运行到断点的位置,如下图
这时就可以进行相应的变量查看、测试
在控制台输入other,敲回车,就可以得到other组件的全部属性方法,真的是全部哦,一点都不会少(有时候函数名忘了,不查api,通过这种方式获得提示也是一种方法)
这里我们用到的属性主要是world里的几个
aabb:axis-aligned bounding box,轴对齐包围盒,也就是碰撞检测的区域
aabb.x、aabb.y:碰撞盒的位置,矩形的中心位置
aabb.xMin、aabb.xMax、aabb.yMin、aabb.yMax:碰撞盒的边缘位置,矩形的四个边
preAabb的属性跟aabb相同,代表着碰撞盒的上一次位置,我们利用这个”上一次位置”就可以实现“前面有障碍物,大马猴走不过去”的效果了
简单的思路就是:如果发生了不可移动的碰撞(障碍物),就退回到“上一次位置”
现在我们再来看MonkeyContro.js的代码
onCollisionEnter里我们做的事情就是保存上一次计算碰撞组件的位置,如果发生碰撞了就返回上一次位置,分别进行了x轴检测和y轴检测,如果想加深理解,可以尝试自己画个图
算了,我知道你也不会画
上图就是X轴碰撞的情况,Y轴碰撞的情况类似
最后来看一下效果吧
跟随平台移动
添加触摸按键
找个天气好的日子再写
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:124918次
积分:1988
积分:1988
排名:第19985名
原创:70篇
评论:152条
(1)(4)(2)(4)(1)(10)(1)(8)(7)(11)(1)(1)(4)(4)(5)(2)(8)(4)--------------AD1----------------
--------------AD2----------------
--------------AD3----------------主题 : spine碰撞检测--怎样做区域检测?
级别: 新手上路
可可豆: 135 CB
威望: 135 点
在线时间: 60(时)
发自: Web Page
spine碰撞检测--怎样做区域检测?&&&
求大侠帮帮忙
级别: 骑士
可可豆: 509 CB
威望: 509 点
在线时间: 540(时)
发自: Web Page
spine提供boundingbox,去它官网看教程
关注本帖(如果有新回复会站内信通知您)
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版cocosCreator(2)
properties: {
directionX:0,
//根据组件上设置的数字来进行方向移动
directionY:0,
// use this for initialization
onLoad: function () {
var manager = cc.director.getCollisionManager();
manager.enabled = true;
manager.enabledDebugDraw = true;
* 当碰撞产生的时候调用
{Collider} other 产生碰撞的另一个碰撞组件
{Collider} self
产生碰撞的自身的碰撞组件
onCollisionEnter: function (other, self) {
// 碰撞系统会计算出碰撞组件在世界坐标系下的相关的值,并放到 world 这个属性里面
var world = self.
// 碰撞组件的 aabb 碰撞框
var aabb = world.
// 上一次计算的碰撞组件的 aabb 碰撞框
var preAabb = world.preA
var r = world.radius;
var point = cc.p(preAabb.x,preAabb.y)
//cc.log(aabb.x ,aabb.y,preAabb.x,preAabb.y)
var offsetX = aabb.x - preAabb.x
var offsetY = aabb.y - preAabb.y
if(offsetX !=0)offsetX = offsetX/Math.abs(offsetX) * 5
//碰撞时反弹
if(offsetY !=0)offsetY = offsetY/Math.abs(offsetY) * 5
point = cc.pAdd(cc.p(preAabb.x,preAabb.y),cc.p(r - offsetX, r - offsetY))
point = this.node.parent.convertToNodeSpaceAR(point)
//point = this.sprite.parent.convertToNodeSpaceAR(point)
this.node.setPosition(point)
//this.sprite.setPosition(point)
// 碰撞框的世界矩阵
var t = world.transform;
// 以下属性为圆形碰撞组件特有属性
var r = world.radius;
var p = world.position;
// 以下属性为 矩形 和 多边形 碰撞组件特有属性
var ps = world.points;
* 当碰撞产生后,碰撞结束前的情况下,每次计算碰撞结果后调用
{Collider} other 产生碰撞的另一个碰撞组件
{Collider} self
产生碰撞的自身的碰撞组件
onCollisionStay: function (other, self) {
//this.node.x -= 10
//this.sprite.x += 10
* 当碰撞结束后调用
{Collider} other 产生碰撞的另一个碰撞组件
{Collider} self
产生碰撞的自身的碰撞组件
onCollisionExit: function (other, self) {
// called every frame, uncomment this function to activate update callback
update: function (dt) {
if(this.directionX !=0){
this.directionX = this.directionX/Math.abs(this.directionX)
this.node.x +=this.directionX * 100 * dt
if(this.directionY !=0){
this.directionY = this.directionY/Math.abs(this.directionY)
this.node.y +=this.directionY * 100 * dt
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:6947次
排名:千里之外
原创:25篇
转载:27篇
(1)(10)(30)(7)(7)cocos碰撞检测的方法 - 开源中国社区
当前访客身份:游客 [
当前位置:
发布于 日 13时,
cocos碰撞检测的方法。/cheyiliu/CollisionDetection
代码片段(1)
1.&[代码]详见/cheyiliu/CollisionDetection&&&&
class Role {
virtual ~Role() {
// 主动撞击目标,一般会造成目标损坏
virtual void hit(Role* target) = 0;
// 被撞击等,遭到损坏
virtual void gotDamage(int damage)= 0;
// HP为0了,倒下
virtual void down()= 0;
Role* a = dynamic_cast&Role * &(contact.getShapeA()-&getBody()-&getNode());
Role* b = dynamic_cast&Role * &(contact.getShapeB()-&getBody()-&getNode());
if(a && b) {
log("onContactBegin,牛顿说: 力的作用是相互的");
a-&hit(b);
b-&hit(a);
开源中国-程序员在线工具:
相关的代码(159)
0回/12612阅
1回/7422阅
2回/3080阅
0回/1073阅
0回/7398阅
0回/2312阅
1回/3306阅
0回/3245阅
开源从代码分享开始
cheyiliu的其它代码

我要回帖

更多关于 cocos creator 教程 的文章

 

随机推荐