Cocos2dx 事件处理机制 学习笔记

1、演示场景优先事件监听示例:

 	Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    auto closeItem = MenuItemImage::create(
        "CloseNormal.png",
        "CloseSelected.png",
        CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width / 2,
        origin.y + closeItem->getContentSize().height / 2));
    auto removeAllTouchItem = MenuItemFont::create("删除所有的触摸监听器",
        [this](Ref* sender) {
            auto senderItem = static_cast<MenuItemFont*>(sender);
            senderItem->setString("触摸监听器删除成功");
            _eventDispatcher->removeEventListenersForType(EventListener::Type::TOUCH_ONE_BY_ONE);
        });
    removeAllTouchItem->setPosition(visibleSize.width / 2, visibleSize.height * 0.2);
    auto menu = Menu::create(removeAllTouchItem, closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu);
    auto title = Label::createWithSystemFont("单点触摸(场景优先)测试", "", 64);
    title->setPosition(visibleSize.width / 2, visibleSize.height * 0.9);
    this->addChild(title);
    auto subtitle = Label::createWithSystemFont("请单击或拖动滑块", "", 32);
    subtitle->setPosition(visibleSize.width / 2, visibleSize.height * 0.8);
    this->addChild(subtitle);
    auto sprite1 = Sprite::create("CyanSquare.png");
    sprite1->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2) + Vec2(-80, 80));
    addChild(sprite1, 10);
    auto sprite2 = Sprite::create("MagentaSquare.png");
    sprite2->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2));
    addChild(sprite2, 20);
    auto sprite3 = Sprite::create("YellowSquare.png");
    sprite3->setPosition(Vec2(0, 0));
    sprite2->addChild(sprite3, 1);
    // ①创建一个单点触摸事件监听器,处理触摸事件逻辑
    auto listener1 = EventListenerTouchOneByOne::create();
    // 设置是否向下传递触摸
    listener1->setSwallowTouches(true);
    // 通过 lambda 表达式 直接实现触摸事件的响应函数
    listener1->onTouchBegan = [](Touch* touch, Event* event) {
        // 获得当前事件触摸的目标对象
        auto target = static_cast<Sprite*>(event->getCurrentTarget());
        // 获得当前的触摸点
        Point locationInNode = target->convertToNodeSpace(touch->getLocation());
        // 获得触摸对象的ContentSize
        Size s = target->getContentSize();
        // 获得位置矩形
        Rect rect = Rect(0, 0, s.width, s.height);
        // 如果位置矩形包含触摸点
        if (rect.containsPoint(locationInNode))
        {
            log("onTouchBegan... x = %f, y = %f", locationInNode.x, locationInNode.y);
            // 设置透明度
            target->setOpacity(180);
            // 表明用户触摸事件已经被处理,后续的onTouchMoved、onTouchEnded和onTouchCancelled会接着响应,其他事件监听器则不会再去进行监听本次触摸事件。
            return true;
        }
        return false;
    };

    listener1->onTouchMoved = [](Touch* touch, Event* event) {
        auto target = static_cast<Sprite*>(event->getCurrentTarget());
        // 移动触摸的精灵
        target->setPosition(target->getPosition() + touch->getDelta());
    };

    listener1->onTouchEnded = [=](Touch* touch, Event* event) {
        auto target = static_cast<Sprite*>(event->getCurrentTarget());
        // 设置透明度
        target->setOpacity(255);
        std::string name;
        if (target == sprite2)
        {
            name = "MagentaSquare.png";
            sprite1->setZOrder(100);
            subtitle->setString("响应事件的是酒红色滑块,青色滑块的ZOrder值修改为100");
        }
        else if (target == sprite1)
        {
            name = "CyanSquare.png";
            sprite1->setZOrder(0);
            subtitle->setString("响应事件的是青色滑块,青色滑块的ZOrder值修改为0");
        }
        else {
            name = "YellowSquare.png";
        }
        log("onTouchEnded.. 您触摸的是%s", name.c_str());
    };
    // 添加场景优先事件监听器。
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
    // ④注意:在使用addEventListenerWithSceneGraphPriority或者addEventListenerWithFixedPriority函数时,	会对当前使用的事件监听器添加一个已注册的标记,这使得它不能够被添加多次。所以当我们再次使用listener1的时候,需要使用clone()函数创建一个新的克隆。
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite3);

在这里插入图片描述
通过示例,可以总结出实现事件处理机制的基本步骤;
1、创建一个触摸事件监听器
2、实现触摸事件的响应方法
3、添加事件监听器
4、当用户触摸时,事件分发器就会将事件分发给监听器去响应

2、演示滑动屏幕选择菜单示例:

	Size visibleSize = Director::getInstance()->getVisibleSize();
    // ③创建菜单
    _itemMenu = Menu::create();
    // 循环添加菜单项
    for (int i = 0; i < itemCount; ++i)
    {
        // 创建Label
        auto label = Label::createWithSystemFont(itemNames[i].itemName, "", 48);
        // 创建menuItemLabel,触碰时调用menuCallback函数
        auto menuItem = MenuItemLabel::create(label, CC_CALLBACK_1(ContentLayer::menuCallback, this));
        // 设置tag,用于menuCallback中判断触碰的菜单在itemNames中的下标
        menuItem->setTag(i);
        // 将菜单项添加到菜单
        _itemMenu->addChild(menuItem);
        // 控制台打印每一个菜单项的坐标位置,读者可以进行观察调试
        log("x:%f,y:%f", visibleSize.width / 2, (visibleSize.height - (i + 1) * LINE_SPACE));
        // 设置菜单项位置
        menuItem->setPosition(Vec2(visibleSize.width / 2, (visibleSize.height - (i + 1) * LINE_SPACE)));
    }
    _itemMenu->setPosition(Vec2::ZERO);
    // 将菜单添加为当前层的子节点
    this->addChild(_itemMenu, 1);
    // ④注册触碰监听器
    auto listener = EventListenerTouchOneByOne::create();
    // 设置是否向下传递触摸
    listener->setSwallowTouches(true);
    // 设置触碰开始时调用onTouchBegan函数
    listener->onTouchBegan = CC_CALLBACK_2(ContentLayer::onTouchBegan, this);
    // 设置触碰移动时调用onTouchMoved函数
    listener->onTouchMoved = CC_CALLBACK_2(ContentLayer::onTouchMoved, this);
    // 添加场景优先事件监听器。
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

在这里插入图片描述
在这里插入图片描述
屏幕向上滑动时,可以显示更多的菜单项,向下滑动屏幕,则会显示之前的菜单选项,单击任何一个菜单项,将会进入HelloWorld场景

3、演示多点触摸示例:

	Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    auto closeItem = MenuItemImage::create(
        "CloseNormal.png",
        "CloseSelected.png",
        CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width / 2,
        origin.y + closeItem->getContentSize().height / 2));
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);
    auto title = Label::createWithSystemFont("多点触摸(缩放功能)测试", "", 64);
    title->setPosition(visibleSize.width / 2, visibleSize.height * 0.9);
    this->addChild(title);
    auto subtitle = Label::createWithSystemFont("请用手指(iOS模拟器可使用鼠标+option键)缩放屏幕", "", 32);
    subtitle->setPosition(visibleSize.width / 2, visibleSize.height * 0.8);
    this->addChild(subtitle);
    _bgSprite = Sprite::create("HelloWorld.png");
    _bgSprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
    this->addChild(_bgSprite, 0);
    _mscale = 1.0;
    auto listener = EventListenerTouchAllAtOnce::create();
    listener->onTouchesBegan = CC_CALLBACK_2(HelloWorld::onTouchesBegan, this);
    listener->onTouchesMoved = CC_CALLBACK_2(HelloWorld::onTouchesMoved, this);
    listener->onTouchesEnded = CC_CALLBACK_2(HelloWorld::onTouchesEnded, this);
    listener->onTouchesCancelled = CC_CALLBACK_2(HelloWorld::onTouchesCancelled, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

在这里插入图片描述
实现缩放功能的步骤如下:
1、在OnTouchsBegin中检测,若触摸点个数大于两个,取前两个触摸点
2、计算两个触摸点的距离,计算方式为横纵坐标差的平方和开根号
3、在OnTouchsMoved函数中做同样的检测,如果触摸点的个数大于两个,取前两个触摸点
4、再次计算这两个点的距离,通过距离比计算得到缩放比例,并保存新触摸点两点之间的距离,
5、调用精灵类的setScale函数设置新的缩放比例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值