Skip to content

cocos2d x 3.3 009 核心概念和相关类 层

cheyiliu edited this page Jan 19, 2015 · 5 revisions

layer概述

  • 继承自Node
  • 成员有键盘、touch、加速仪的事件监听器和事件相关的几个状态变量,那肯定和这些事件的监听相关了
     bool _touchEnabled;
     bool _accelerometerEnabled;
     bool _keyboardEnabled;
     EventListener* _touchListener;
     EventListenerKeyboard* _keyboardListener;
     EventListenerAcceleration* _accelerationListener;
    
     Touch::DispatchMode _touchMode;
     bool _swallowsTouches;
    

主要api

  • "乱花渐欲迷人眼"阿,头文件里各种CC_DEPRECATED_ATTRIBUTE, final修饰, 忽略掉对应的方法就好
//touch
    virtual bool onTouchBegan(Touch *touch, Event *unused_event); 
    virtual void onTouchMoved(Touch *touch, Event *unused_event); 
    virtual void onTouchEnded(Touch *touch, Event *unused_event); 
    virtual void onTouchCancelled(Touch *touch, Event *unused_event);

    virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event);
    virtual void onTouchesCancelled(const std::vector<Touch*>&touches, Event *unused_event);

//acceleration
    virtual void onAcceleration(Acceleration* acc, Event* unused_event);

//key
    virtual void onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event);
    virtual void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event);

源码查看

1.上述的onTouchXXX onAcceleration  onKeyXXX
全部代码都类似下面,实现脚本语言的事件处理
#if CC_ENABLE_SCRIPT_BINDING
    if(kScriptTypeNone != _scriptType)
    {
        ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
    }
#endif

2. _touchEnabled相关
/// isTouchEnabled setter
void Layer::setTouchEnabled(bool enabled)
{
//值真的变了才处理
    if (_touchEnabled != enabled)
    {
        _touchEnabled = enabled;
        if (enabled)
        {
            if (_touchListener != nullptr)
                return;
//all at once 类型, 设置对应的监听器, 多点触摸
            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
            {
//one by one mode, 单点触摸监听设置
                // 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;
            }
        }
        else
        {
//disable 则移除监听器
            _eventDispatcher->removeEventListener(_touchListener);
            _touchListener = nullptr;
        }
    }
}

3._accelerometerEnabled相关
void Layer::setAccelerometerEnabled(bool enabled)
{
    if (enabled != _accelerometerEnabled)
    {
        _accelerometerEnabled = enabled;

        Device::setAccelerometerEnabled(enabled);
//先移除
        _eventDispatcher->removeEventListener(_accelerationListener);
        _accelerationListener = nullptr;

        if (enabled)
        {
//设置监听器
            _accelerationListener = EventListenerAcceleration::create(CC_CALLBACK_2(Layer::onAcceleration, this));
            _eventDispatcher->addEventListenerWithSceneGraphPriority(_accelerationListener, this);
        }
    }
}

4._keyboardEnabled相关
/// isKeyboardEnabled setter
void Layer::setKeyboardEnabled(bool enabled)
{
    if (enabled != _keyboardEnabled)
    {
        _keyboardEnabled = enabled;

//移除
        _eventDispatcher->removeEventListener(_keyboardListener);
        _keyboardListener = nullptr;

        if (enabled)
        {
            auto listener = EventListenerKeyboard::create();
            listener->onKeyPressed = CC_CALLBACK_2(Layer::onKeyPressed, this);
            listener->onKeyReleased = CC_CALLBACK_2(Layer::onKeyReleased, this);
//设置
            _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
            _keyboardListener = listener;
        }
    }
}

5. _swallowsTouches相关
5.1 默认值true
5.2 在void Layer::setTouchEnabled(bool enabled)过程中,
    针对单点事件时, listener->setSwallowTouches(_swallowsTouches);
    最后调用到了void EventListenerTouchOneByOne::setSwallowTouches(bool needSwallow)
    这个值的最终用处是在CEventDispatcher.cpp, dispatchTouchEvent方法中, 结合dispatchEventToListeners
    的代码看
{
设置needSwallow=true后, 在dispatchEventToListeners的参数onEvent将会返回true,
事件派发的循环将break,
导致剩下的事件监听器接受不到事件,从而实现事件不被进一步传播
}
5.3 void Layer::setSwallowsTouches(bool swallowsTouches)
{
//值变化了才继续
    if (_swallowsTouches != swallowsTouches)
    {
        _swallowsTouches = swallowsTouches;

        if( _touchEnabled)
        {
//若touch enabled则先设置enable为false,移除之前的监听器
//再重新设置监听器
            setTouchEnabled(false);
            setTouchEnabled(true);
        }
    }
}

小结

  • Layer层提供的默认事件处理是针对脚本引擎相关的,但接口是虚的,也即允许我们重写。
  • 几个状态相关的变量都是设置监听器或者取消监听器
  • setSwallowsTouches设置之后,在事件分发器生效,大致过程是, 在one by one(单点) touch的事件分发时,若设置了swallowTouch,在分发遍过程中,遍历监听器时会导致循环break,从而导致事件不被进一步传播
Clone this wiki locally