前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CreatorPrimer|物理小游戏(碰撞监听)

CreatorPrimer|物理小游戏(碰撞监听)

作者头像
张晓衡
发布2019-09-11 17:03:37
6620
发布2019-09-11 17:03:37
举报
文章被收录于专栏:Creator星球游戏开发社区

继续物理小游戏,我们先回顾一下CreatorPrimer仓库中提供的五个组件脚本:

通用物理组件

使用这5个组件脚本,可以构建非常有趣的物理小游戏,下面我们对这5个自定义组件做一个简单介绍:

  1. PhysicsManager: 物理引擎管理器,使用它无需编程即可开启\关闭物理引擎,并提供刚体的着色调试开关。

物理引擎管理器

  1. PhysicsVelocity: 物理速度控制组件,提供了一个force函数方便使用cc.Button在编辑器中调用,为刚体施加外力。
  2. PhysicsColliderNotification: 物理碰撞通知组件,使用它可以让非物理组件或脚本能收到物理碰撞事件。
  3. ScoreNotificationHandle:得分通知处理组件,该组件监听PhysicsColliderNotification发出的事件通知,更新Label文本。
  4. ScoreVerifyNotificationHandle:带验证功能的得分通知处理组件。

我们今天的重点是PhysicsColliderNotification组件的实现。

1. 开启刚体碰撞监听

开启碰撞接触监听

PhysicsColliderNotification组件功能是监听刚体的碰撞事件,因此它需要依赖刚体组件(RigidBody),同时在运行时自动开启刚体的enabledContactListener属性。

代码语言:javascript
复制
cc.Class({    //依赖刚体组件
   editor: CC_EDITOR && {        
            requireComponent: cc.RigidBody,
   },    
    extends: cc.Component,
   ...
   start () {        
        //获取刚体组件
       let rigidBody = this.getComponent(cc.RigidBody);        
        //开启碰撞接触监听
       rigidBody.enabledContactListener = true;
   },
   ...
});

最初,有网友在使用Shawn提供的脚本发现时有不灵,发现是因为未开启刚体碰撞监听开关的原故,因此重构时增加了RigidBody的依赖,同时在组件start生命周期函数中开启刚体的enabledContactListener属性,增强使用体验,减少意外发生。

2. 碰撞事件监听

在篮框节点上开启了刚体的碰撞监听,就可以此节点的任意组件代码上编写碰撞监听处理函数了,我们看一下PhysicsColliderNotification碰撞处理函数的实现细节:

代码语言:javascript
复制
/**
* 物理碰撞通知组件,要以让非物理组件或脚本能收到物理碰撞事件
*/cc.Class({
   ...
   extends: cc.Component,    
    properties: {       
        notificationName:'',       
        _p0: null,       
        _p1: null,
   },    
    /**
    * 只在两个碰撞体开始接触时被调用一次
    */
   onBeginContact(contact, selfCollider, otherCollider) {
       cc.log(otherCollider.node.name);        
        this._p0 = otherCollider.node.position;
   },    
    /**
    * 只在两个碰撞体结束接触时被调用一次
    */
   onEndContact: function (contact, selfCollider, otherCollider) {        
        this._p1 = otherCollider.node.position;        
        if (this.notificationName) {
           cc.director.emit(this.notificationName, contact, this._p0, this._p1);
       }
   },
});

不知道大家是否还记得,在篮框的碰撞组件中需要设置Sensor属性,它可以使用节点不产生物理碰撞效果,让其它动态刚体可以穿透它,但能监听物理碰撞事件,请看下图:

开启Sensor属性

开启了Sensor属性,通过引擎提供的onBeginContact、onEndContact两个事件监听函数获取篮球刚体的坐标点,识别篮球是从上向下投进的,还是从下向上进框的,从而实现正确记分。

组件中的_p0、_p1变量就是刚体碰撞时的开始点和结束点,在onEndContact事件中通过cc.director.emit将自定义事件、碰撞开始\结束坐标点广播出去。

3. 自定义事件

为什么不直接在刚体节点上直接处理得分呢?要使用cc.director.emit中转一下呢?因为刚体碰撞事件,只能在刚体节点上才以监听到,得分的表现使用的是一个Label组件,如果将代码写在一些,那这个PhysicsColliderNotification组件做的事情就不只一件,而且太过去具体,而且设计多个对象,导致通用性会大大降低。

使用cc.director.emit('xxx')将广播一个事件出去,在任意脚本中使用cc.director.on('xxx')接收事件,不论是更新得分,还是处理游戏的流程、特效等等,会更加的灵活可变,可以让策划或设计师发挥出更多的创作空间。

cc.Director是继承成自cc.EventTarget,cc.director是一个全局变量,因此使用cc.director.emit、cc.director.on实现事件的订阅、发布非常简单,是实现组件间的通信的一种非常方便的方案。

很多人都使用过cc.Node.emit、cc.Node.on来发送和监听事件,唯一不方便的就是你需要先获取发送事件的节点对象。相信还有人怀念Cocos2d-x中的CCNotificationCenter,完全可以使用cc.EventTarget实例化一个全局的EventTarget对象来模拟,实现相同的效果。

通过事件可以方便解耦对象之间的依赖,用一个通俗点的说法就是:“你不要打电话给我,我会打电话给你!”。打电话首先需要电话号码就是事件名称,说这句话的人就是EventTarget对象,听话的人就是递交电话号码(事件名)、接听电话的程序同学。

4. 小结

本篇介绍了PhysicsColliderNotification组件的实现,全是代码和逻辑,不能照顾到非程序员同学,还请包涵。

监听物理碰撞一定要开启刚体的enabledContactListener属性,在onBeginContact、onEndContact事件中获取刚体的位置以识别刚体的运行方向。同时使用cc.director.emit将事件、坐标点广播出去,在关心的地方做对应的逻辑处理。

目前源码已经合并到CreatorPrimer仓库主干,欢迎把玩,提出你的建议! 源码地址:https://github.com/ShawnZhang2015/CreatorPrimer

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Creator星球游戏开发社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 开启刚体碰撞监听
  • 2. 碰撞事件监听
  • 3. 自定义事件
  • 4. 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档