1、消息事件
事件就是一个动作或状态的改变的发生,例如用户单击了屏幕、状态的变更、当一个角色的血量低于0时触发的死亡事件等。当一个事件发生时,系统调用注册的事件函数。
与一般的模块直接调用相比,事件可以不用依赖于事件响应者的实现而预先定义一 组事件类型,事件的响应者甚至可以在运行时动态地添加或者移除,从而增强了事件分发的灵活性。例如玩家单击了屏幕,程序中任何的元素或者逻辑可以对其作出响应。
(1)采用消息事件处理机制的优缺点
(1)降低了软件内模块之间的耦合度,使得模块之间更加独立。
(2)一个事件可以多个响应函数。
(3)比直接调用效率低。
(2)消息事件系统的组成
一个事件由触发到完成响应,主要由三个角色协作完成:
(1) 事件分发器:EventDispatcher;
(2) 事件:EventTouch、EventKeyboard等;
(3) 事件处理:EventListenerTouch、EventListenerKeyboard等。
2、消息事件系统
接收事件需要派生一个EventListener类,
触摸:EventListenerTouch
键盘:EventListenerKeyboard
重力:EventListenerAcceleration
(1)单点触摸
bool onTouchBegan(Touch *touch, Event *unused_event);
void onTouchMoved(Touch *touch, Event *unused_event);
void onTouchEnded(Touch *touch, Event *unused_event);
void onTouchCancelled(Touch *touch, Event *unused_event);
(2)多点触摸
void onTouchesBegan(const std::vector<Touch*>& touches, Event unused_event);
void onTouchesMoved(const std::vector<Touch>& touches, Event unused_event);
void onTouchesEnded(const std::vector<Touch>& touches, Event unused_event);
void onTouchesCancelled(const std::vector<Touch>&touches, Event *unused_event);
(3)重力加速事件
void onAcceleration(Acceleration* acc, Event* unused_event)
(4)CCLayer中事件开关
(1)void setTouchEnabled(bool value)
触摸事件开关
(2)void setAccelerometerEnabled(bool value)
重力加速事件开关
(3)void setKeyboardEnabled(bool value);
键盘加速事件开关
3、事件分发EventDispatcher
(1)注册事件
void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
EventListenerCustom* addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback);
(2)删除事件
void removeEventListener(EventListener* listener);
void removeEventListenersForType(EventListener::Type listenerType);
void removeEventListenersForTarget(Node* target, bool recursive = false);
void removeCustomEventListeners(const std::string& customEventName);
void removeAllEventListeners();
if( _touchMode == Touch::DispatchMode::ALL_AT_ONCE )
{
// Register Touch Event
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesBegan = CC_CALLBACK_2(Layer::onTouchesBegan, this);
listener->onTouchesMoved = CC_CALLBACK_2(Layer::onTouchesMoved, this);
listener->onTouchesEnded = CC_CALLBACK_2(Layer::onTouchesEnded, this);
listener->onTouchesCancelled = CC_CALLBACK_2(Layer::onTouchesCancelled, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
_touchListener = listener;
}
else
{
// Register Touch Event
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(_swallowsTouches);
listener->onTouchBegan = CC_CALLBACK_2(Layer::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(Layer::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(Layer::onTouchEnded, this);
listener->onTouchCancelled = CC_CALLBACK_2(Layer::onTouchCancelled, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
_touchListener = listener;
}
4、自定义消息CCNotificationCenter
通知中心主要用在跨页面或者类传递参数,一个类做了某个操作后,想通知另一类,可以通过通知来实现。
(1)注册通知接收函数
void addObserver(Ref *target,
SEL_CallFuncO selector,
const std::string& name,
Ref *sender);
(2)发送通知
void postNotification(const std::string& name, Ref *sender);
(3)取消注册
int removeAllObservers(Ref *target);
void removeObserver(Ref *target,const std::string& name);
class CCMyLay: public cocos2d::CCLayer
{
public:
CCMyLay();
~CCMyLay();
virtual bool init();
void OnNotificationCenterMsg(CCObject* obj);
CREATE_FUNC(CCMyLay);
};
bool CCMyLay::init()
{
if ( !CCLayer::init() )
{
return false;
}
// 接收消息
CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(CCMyLay::OnNotificationCenterMsg),
"Notification_Name", // 通知名称
NULL
);
//发送通知消息
CCNotificationCenter::sharedNotificationCenter()->postNotification(
"Notification_Name", // 通知名称
(CCObject*)NULL
);
return true;
}
void CCMyLay::OnNotificationCenterMsg( CCObject* obj )
{
log("OnNotificationCenter");
}