cocos creator 事件

在做一个消除类游戏时,需要对点击的方块做出响应。代码很简单,可背后的原理还多着呢。

1. 普通节点注册click事件

在cc中如果需要相应click事件,需要为该节点添加一个Button组件。或使用类似效果的事件比如

  1. cc.Node.EventType.MOUSE_DOWN

  2. cc.Node.EventType.TOUCH_END

//author herbert qq:464884492
//注册按钮click事件
btn.node.on("click", event=>{cc.log("button click")});
//注册MOUSE_DOWN
btn.node.on(cc.Node.EventType.MOUSE_DOWN,event=>{cc.log("button MOUSE_DOWN")});
//注册TOUCH_END
btn.node.on(cc.Node.EventType.TOUCH_END,event=>{cc.log("button TOUCH_END")})

2. 应该减少事件注册量

是否没有问题了?在写juqery时,有事件委托(delegate)的概念。啥意思呢,就是在节点的父级注册事件,来响应子节点的事件源。为啥可以实现,主要归功于js事件的两大机制

  1. 事件冒泡,事件响应从子节点往上冒泡到顶层节点

  2. 事件捕获,事件响应冲顶层节点依次传递到最末级节点

所以问题来了,消除类游戏都是通过预制资源生成不同样式的方块。若在每一方块上都注册事件,势必导致内存上涨(虽然现在内存很大了)。看看cc文档,事件机制完全是一样的(最终都是JS),然而我想在我的Canvas上注册一个click事件,问题出现了。

3.问题来了

问题就是我在Canvas上注册了click事件,点击button时,Canvas 上居然没有收到我的click事件。由此我查看cc源码,写了一堆测试代码,最总得出以下结

  1. click事件确实Button组件特殊存

  2. click事件不会向上或向下传递

  3. node.emit触发事件不会向上或向下传递

  4. node.dispatchEvent支持事件向上或向下传递

  5. 使用node.dispatchEvent参数必须是 cc.Event.EventCustom对象

4.click事件特殊在哪里

cc.Button 组件中的click事件,其实是cc的自定义事件,源码为证

//author:herbert wx:464884492
...
this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this);
...
_onTouchEnded (event) {
if (!this.interactable || !this.enabledInHierarchy) return;
if (this._pressed) {
cc.Component.EventHandler.emitEvents(this.clickEvents, event);
this.node.emit('click', this);//触发事件
}
this._pressed = false;
this._updateState();
event.stopPropagation(); //停止冒泡
},
...

所以,之所Button能响应click事件,是因为组件注册了TOUCH_END事件,并在响应该事件函数中发射一个click事件。

5. javascript 自定义事件

参考mdn文档,js自定事件方式如下

// author:herbert wx:464884492
<script text="javascript">
let cusEvent = new Event("custom", {
bubbles: true //允许冒泡
});
document.body.addEventListener("custom", e => {
console.log("自定义事件");
console.log(" Body event by custom");
}); let btn = document.querySelector("#btn");
btn.addEventListener("custom", e => {
console.log("自定义事件");
console.log("Button event by custom");
})
btn.dispatchEvent(cusEvent);
</script>

5.了解下cc.node.emit

cc.node.emit 最终调用的是CallbacksInvoker.prototype.invoke 方法,从源码来看,是从对应的缓存对象中找到注册的回调方法,依次调用回调函数。

//author herbert wx:464884492
CallbacksInvoker.prototype.invoke = function (key, p1, p2, p3, p4, p5) {
var list = this._callbackTable[key];
if (list) {
var rootInvoker = !list.isInvoking;
list.isInvoking = true;
var callbacks = list.callbacks;
var targets = list.targets;
for (var i = 0, len = callbacks.length; i < len; ++i) {
var callbmhtack = callbacks[i];
if (callback) {
var target = targets[i];
if (target) {
callback.call(target, p1, p2, p3, p4, p5);
}
else {
callback(p1, p2, p3, p4, p5);
}
}
}
if (rootInvoker) {
list.isInvoking = false;
if (list.containCanceled) {
list.purgeCanceled();
}
}}};

所以click自然不会往上或往下传递。

6.dispatchEvent,事件冒泡

dispatchEvent 利用自定义事件的 bubbles 属性,实现冒泡。至于为啥使用 btn.node.dispatchEvent(new cc.Event.EventMouse(cc.Node.EventType.MOUSE_DOWN, true))没有触发事件是因为cc在底层,将事件类型统一改成了 cc.Event.MOUSE,源码为证

author:herbert wx:464884492
...
var EventMouse = function (eventType, bubbles) {
cc.Event.call(this, cc.Event.MOUSE, bubbles);
...
};

场景

运行效果

7.总结

做开发,不管是开发游戏还是其他应用程序。思路基本是一样的。在简单的事,多想想,再发散一下,你会收获更多。
需要进cocos游戏开发群的朋友,请添加我微信回复cocos


欢迎感兴趣的朋友关注我的订阅号“小院不小”,或点击下方二维码关注。我将多年开发中遇到的难点,以及一些有意思的功能,体会都会一一发布到我的订阅号中。如需本文demo请在订阅号中回复ccevent

cocos creator 事件的更多相关文章

  1. Cocos Creator学习五:触摸和重力传感响应事件

    1.移动设备上主要涉及触摸响应事件以及重力传感响应事件的处理. 事件主要分两类: 针对节点事件处理的节点响应事件cc.Node.EventType(主要是触摸响应事件和鼠标响应事件): 针对全局系统事 ...

  2. Cocos Creator学习四:按钮响应事件

    1.方法一:通过编辑器对cc.Button的属性进行拖放操作进行控制 (1)创建脚本BtnClick1.js,增加btnClick1函数,然后拖放到Canvas节点中(记得拖放,否则下面步骤将找不到对 ...

  3. cocos creator Touch事件应用(触控选择多个子节点)

    最近参与了cocos creator的研究,开发小游戏,结果被一个事件坑得不行不行的.现在终于解决了,分享给大家. 原理 1.触控事件是针对节点的 2.触控事件的冒泡,是一级一级往上冒泡,中间可以阻止 ...

  4. cocos creator实现棋牌游戏滑动选牌的功能

    最近在玩cocos creator,打算学着做一款类似双扣游戏的棋牌,名字叫文成三星,比双扣还要多一扣,因为需要三幅牌,在我们老家比较流行这种玩法. 目前实现了绝大部分的逻辑效果如下: 有一点不好的体 ...

  5. Cocos Creator 资源加载流程剖析【一】——cc.loader与加载管线

    这系列文章会对Cocos Creator的资源加载和管理进行深入的剖析.主要包含以下内容: cc.loader与加载管线 Download部分 Load部分 额外流程(MD5 Pipe) 从编辑器到运 ...

  6. Cocos Creator学习二:查找节点和查找组件

    1.目的:只有通过方便的获取节点对象以及组件,才能较好的进行逻辑控制. 2.通过 cc.find(节点全路径名称字符串) 获取节点. 3.通过getComponent获取组件(注意一个是类型,一个是类 ...

  7. Cocos Creator学习一:学习目录以及v2.0 必须关注的网址

    学习目录: <Cocos Creator学习二:查找节点和查找组件> <Cocos Creator学习三:生命周期回调函数> <Cocos Creator学习四:按钮响应 ...

  8. Cocos Creator实现的《点我+1》

    一.前言 在学习Cocos中,需要一些东西来练手,于是前段时间就开发仿照一款公司之前的产品<点我+1>来做,仿照过程中,所有的算法逻辑都是自己研究的,并没有参考公司代码,也没有使用公司的美 ...

  9. 初识cocos creator的一些问题

    本文的cocos creator版本为v1.9.01.color赋值cc.Label组件并没有颜色相关的属性,但是Node有color的属性. //如果4个参数,在ios下有问题let rgb = [ ...

随机推荐

  1. python之unittest框架实现接口测试实例

    python之unittest框架实现接口测试实例 接口测试的方法有很多种,具体到工具有postman,jmeter,fiddler等,但是工具的局限性是测试数据的组织较差,接口的返回工具的判断有限, ...

  2. [leetcode]95 Unique Binary Search Trees II (Medium)

    原题 字母题添加链接描述 一开始完全没有思路.. 百度看了别人的思路,对于这种递归构造的题目还是不熟,得多做做了. 这个题目难在构造出来.一般构造树都需要递归. 从1–n中任意选择一个数当做根节点,所 ...

  3. 用框架名唬人谁都会,那你知道Web开发模式吗?——莫问前程莫装逼

    前言:这两天总结了一些Servlet和JSP里面的知识,写了几篇博客,果然有种“温故而知新”的感觉,学完这些,继续前行,开始整合框架里的知识,框架虽好,可底层原理该掌握的也得掌握,防止以后做项目的时候 ...

  4. Cesium 学习(一)环境搭建

    网上已有很多文章来教我们搭建Cesium的环境,我也没有必要再写一次:下面是我参照的文章的地址: 1.https://www.cnblogs.com/huqi-code/p/8287403.html  ...

  5. 分布式锁----Redis实现

    分布式锁 为什么需要有分布式锁呢,在单点的时候synchronized 就能解决,但是服务拆分之后,每个服务都是单独的机器,无法解决,所以出现了分布式锁,其实也就是用各种手段,实现获取唯一锁,别人无法 ...

  6. ironic+nova详解

    ironic+nova详解 说明: Openstack 的安装步骤省略,按照社区的文档即可搭建出一套相对稳定的使用环境.本文档基于Newton版本. 假设现在已经有一套可用的Newton环境, 以下的 ...

  7. linux初学者-DNS配置篇

    linux初学者-DNS配置篇 DNS在之前的网络管理篇已经做过介绍,下文将叙述DNS在学习工作中的一些配置以及应用. 1.高速缓存DNS 一台主机通过DNS服务器询问域名解析IP是需要一定的时间的, ...

  8. HDU 多校 第三场 Find the answer

    这题是原来cf上的一道原题,不过对于有一些数据范围修改了,不过还是很好想的 题意:给定一个长度为N的数组,对于数组中的每个位置,满足当前和小于M所需要去掉的最小代价 分析:对于当前是否需要进行去掉一些 ...

  9. 2019前端面试系列——Vue面试题

    Vue 双向绑定原理        mvvm 双向绑定,采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter.getter,在数 ...

  10. 洛谷 P5150 题解

    题面 因为 n=lcm(a,b)n = lcm(a, b)n=lcm(a,b) ,可以得出: a  和 b  的质因数都是 n 的质因数 对于 n  的每个质因数 x ,在 n 中的次数为 y ,那么 ...