有关事件机制,官方的文档写的非常完整详实,所以本篇并不打算过多的赘述,这里给出官方文档的地址:http://www.cocos2d-x.org/docs/manual/framework/native/input/event-dispatcher/zh。
下面的内容主要是作为我的学习笔记来发表的,各位可以做一个参考,主要内容如下:
- 触摸事件
- 键盘事件
- 鼠标事件
- 自定义事件
- 加速事件(缺乏真机环境,未测试)
首先,我还是创建一个EventManager来管理事件测试,头文件如下:
#include "cocos2d.h"
USING_NS_CC;
class EventManager :public cocos2d::Sprite{
public:
//调用宏CREATE_FUNC,使系统自动的为SimpleGUIManager类创建一个create方法
CREATE_FUNC(EventManager);
//测试事件
void testEvent();
private:
//测试触摸事件
void testEventListenerTouch();
//测试键盘事件
void testEventListenerKeyboard();
//测试鼠标事件
void testEventListenerMouse();
//测试自定义事件
void testEventListenerCustom();
//测试加速事件,需真机
void testEventListenerAcceleration();
//触摸开始的回调函数
bool onTouchBegan(Touch* touch, Event* event);
//触摸移动的回调函数
void onTouchMoved(Touch* touch, Event* event);
//触摸结束的回调函数
void onTouchEnded(Touch* touch, Event* event);
//键盘按下
void onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event);
//键盘释放回调函数
void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event);
//初始化测试精灵图片
void initSprite();
//鼠标按下回调函数
void onMouseDown(Event *event);
//鼠标抬起回调函数
void onMouseUp(Event *event);
//鼠标移动回调函数
void onMouseMove(Event *event);
//鼠标滚动回调函数
void onMouseScroll(Event *event);
//自定义事件的回调
void onCustomEvent(EventCustom* event);
//分发自定义事件
void dispatchCustomEvent();
private:
Sprite *sprite1;
Sprite *sprite2;
Sprite *sprite3;
};
触摸事件
EventManager.cpp示例代码如下:
//测试触摸事件
void EventManager::testEventListenerTouch(){
// 创建一个事件监听器 OneByOne 为单点触摸
auto listener1 = EventListenerTouchOneByOne::create();
//设置是否吞没事件,在 onTouchBegan 方法返回 true 时吞没
//当设置为true时,在 onTouchBegan 中会执行相应的判断,以决定其返回值是 false 还是 true,
//用来处理触摸事件是否依据显示的顺序关系向后传递。
listener1->setSwallowTouches(true);
//官方在此处使用了一个lambda函数,但是我却没有这样做
//多年的面向对象编程经历,使我养成了一种凡事必须强对象的观念,包括函数的定义也从未使用过匿名函数
//因此,我在这里明确的定义出了开始触摸的函数
listener1->onTouchBegan = CC_CALLBACK_2(EventManager::onTouchBegan, this);
listener1->onTouchEnded = CC_CALLBACK_2(EventManager::onTouchEnded, this);
listener1->onTouchMoved = CC_CALLBACK_2(EventManager::onTouchMoved, this);
//CC_CALLBACK说明
//CC_CALLBACK_0 0个参数
//CC_CALLBACK_1 1个参数
//CC_CALLBACK_2 2个参数
//.................
//对于这个我有点无力吐槽了,系统默认最多是支持3个,那我如果想传递四个及四个以上的参数怎么办呢?
// 添加监听器
//估计此处官方会在后面进行修改吧,这个clone的用法可是有点令人不爽
//有一点非常重要,FixedPriority listener添加完之后需要手动remove,
//而SceneGraphPriority listener是跟node绑定的,在node的析构函数中会被移除
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);
}
//开始触摸事件
bool EventManager::onTouchBegan(Touch* touch, Event* event){
// 获取事件所绑定的 target
auto target = static_cast<Sprite*>(event->getCurrentTarget());
// 获取当前点击点所在相对按钮的位置坐标
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
Size s = target->getContentSize();
Rect rect = Rect(0, 0, s.width, s.height);
// 点击范围判断检测
if (rect.containsPoint(locationInNode)){
log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
target->setOpacity(180);
return true;
}
return false;
}
//触摸事件终止
void EventManager::onTouchEnded(Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
log("sprite onTouchesEnded.. ");
target->setOpacity(255);
if (target == sprite2){
sprite1->setLocalZOrder(100);
}
else if (target == sprite1){
sprite1->setLocalZOrder(0);
}
}
//触摸事件移动
void EventManager::onTouchMoved(Touch* touch, Event* event){
auto target = static_cast<Sprite*>(event->getCurrentTarget());
target->setPosition(target->getPosition() + touch->getDelta());
}
//初始化测试Sprite
void EventManager::initSprite(){
Point origin = Director::getInstance()->getVisibleOrigin();
Size size = Director::getInstance()->getVisibleSize();
sprite1 = Sprite::create("Images/CyanSquare.png");
sprite1->setPosition(origin + Point(size.width / 2, size.height / 2) + Point(-80, 80));
addChild(sprite1, 10);
sprite2 = Sprite::create("Images/MagentaSquare.png");
sprite2->setPosition(origin + Point(size.width / 2, size.height / 2));
addChild(sprite2, 20);
sprite3 = Sprite::create("Images/YellowSquare.png");
sprite3->setPosition(Point(0, 0));
sprite2->addChild(sprite3, 1);
}
键盘事件
示例代码如下:
//测试键盘事件
void EventManager::testEventListenerKeyboard(){
// 初始化并绑定
auto listener = EventListenerKeyboard::create();
listener->onKeyPressed = CC_CALLBACK_2(EventManager::onKeyPressed, this);
listener->onKeyReleased = CC_CALLBACK_2(EventManager::onKeyReleased, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}
// 键位响应函数原型
void EventManager::onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event){
log("Key with keycode %d pressed", keyCode);
}
void EventManager::onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event){
log("Key with keycode %d released", keyCode);
}
鼠标事件
示例源码如下:
//测试鼠标事件
void EventManager::testEventListenerMouse(){
auto mouseListener = EventListenerMouse::create();
mouseListener->onMouseMove = CC_CALLBACK_1(EventManager::onMouseMove, this);
mouseListener->onMouseUp = CC_CALLBACK_1(EventManager::onMouseUp, this);
mouseListener->onMouseDown = CC_CALLBACK_1(EventManager::onMouseDown, this);
mouseListener->onMouseScroll = CC_CALLBACK_1(EventManager::onMouseScroll, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(mouseListener, this);
}
void EventManager::onMouseDown(Event *event)
{
EventMouse* e = (EventMouse*)event;
//string str = "Mouse Down detected, Key: ";
//str += tostr(e->getMouseButton());
log("Mouse Down detected");
// ...
//鼠标按下时,分发自定义事件
dispatchCustomEvent();
}
void EventManager::onMouseUp(Event *event)
{
EventMouse* e = (EventMouse*)event;
//string str = "Mouse Up detected, Key: ";
//str += tostr(e->getMouseButton());
log("Mouse Up detected");
// ...
}
void EventManager::onMouseMove(Event *event)
{
EventMouse* e = (EventMouse*)event;
//string str = "MousePosition X:";
//str = str + tostr(e->getCursorX()) + " Y:" + tostr(e->getCursorY());
//log("MousePosition");
}
void EventManager::onMouseScroll(Event *event)
{
EventMouse* e = (EventMouse*)event;
//string str = "Mouse Scroll detected, X: ";
//str = str + tostr(e->getScrollX()) + " Y: " + tostr(e->getScrollY());
log("Mouse Scroll detected");
}
自定义事件
示例源码:
void EventManager::testEventListenerCustom(){
auto listener = EventListenerCustom::create("game_custom_event1", CC_CALLBACK_1(EventManager::onCustomEvent,this));
_eventDispatcher->addEventListenerWithFixedPriority(listener, 1);
}
void EventManager::dispatchCustomEvent(){
static int count = 0;
++count;
char* buf = new char[10];
sprintf(buf, "recept custom event %d", count);
//自定义事件
EventCustom event("game_custom_event1");
//设置事件参数
event.setUserData(buf);
//分发事件
_eventDispatcher->dispatchEvent(&event);
}
void EventManager::onCustomEvent(EventCustom* event){
log("Custom event 1 received, ");
char* buf = static_cast<char*>(event->getUserData());
log(buf);
}
至此,事件机制的内容就介绍完了。事件机制也是游戏中的重要组成部分之一,熟练掌握事件机制,也是前端程序必备的能力之一。下一节,我们将介绍一个非常酷的模块,那就是Cocos的粒子系统,游戏中很多炫酷的效果就是由粒子制作出来的,让我们拭目以待吧。