Cocos2d-x处理Touch触摸和鼠标事件demo

请参考《Ubuntu18.04搭建Cocos2d开发环境》搭建项目

默认情况下,Cocos2d-x会将鼠标左点击当作触摸。

第一步:在/home/kyun/Desktop/Games/MyGame/CMakeLists.txt文件添加TouchScene.h和TouchScene.cpp:

# add cross-platforms source files and header files 
list(APPEND GAME_SOURCE
     Classes/AppDelegate.cpp
     Classes/TouchScene.cpp
     )
list(APPEND GAME_HEADER
     Classes/AppDelegate.h
     Classes/TouchScene.h
     )

第二步:编写TouchScene.h和TouchScene.cpp

TouchScene.h:


#include "cocos2d.h"

class TouchScene : public cocos2d::Layer {
public:
    static cocos2d::Scene* createScene();
    virtual  bool init();
	//Touch事件回调方法
    virtual bool onTouchBegan(cocos2d::Touch*,cocos2d::Event*);
    virtual void onTouchEnded(cocos2d::Touch*,cocos2d::Event*);
    virtual void onTouchMoved(cocos2d::Touch*,cocos2d::Event*);
    virtual void onTouchCancelled(cocos2d::Touch*,cocos2d::Event*);
    CREATE_FUNC(TouchScene);
private:
    cocos2d::Label* labelTouchInfo;

};

TouchScene.cpp:

//
// Created by kyun on 20-3-12.
//

#include "TouchScene.h"

USING_NS_CC;


Scene* TouchScene::createScene() {
    auto scene = Scene::create();
    auto layer = TouchScene::create();
    scene->addChild(layer);
    return scene;
}

bool TouchScene::init() {
    if(!Layer::init()){
        return false;
    }
	// Label标签
    labelTouchInfo = Label::createWithSystemFont("Touch or clicksomewhere to begin","Arial",30);
    labelTouchInfo->setPosition(Vec2(Director::getInstance()->getVisibleSize().width/2,Director::getInstance()->getVisibleSize().height/2));
    // 创建EventListenerTouchOneByOne类型的事件监听器
    auto touchListener = EventListenerTouchOneByOne::create();
    // 将处理函数绑定到事件监听器上
    touchListener->onTouchBegan = CC_CALLBACK_2(TouchScene::onTouchBegan,this);
    touchListener->onTouchEnded = CC_CALLBACK_2(TouchScene::onTouchEnded,this);
    touchListener->onTouchMoved = CC_CALLBACK_2(TouchScene::onTouchMoved,this);
    touchListener->onTouchCancelled = CC_CALLBACK_2(TouchScene::onTouchCancelled,this);


	// 将事件监听器注册到节点的_eventDispatcher上
    _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener,this);
    this->addChild(labelTouchInfo);
    return true;
}

bool TouchScene::onTouchBegan(cocos2d::Touch * touch, cocos2d::Event * event) {
    labelTouchInfo->setPosition(touch->getLocation());
    labelTouchInfo->setString("You touched here");
    return true;

}

void TouchScene::onTouchEnded(cocos2d::Touch * touch, cocos2d::Event * event) {
    cocos2d::log("touch ended");
}

void TouchScene::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event * event) {
    cocos2d::log("touch moved");
}

void TouchScene::onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *event) {
    cocos2d::log("touch cancelled");
}

第三步:修改AppDelegate.cpp

#include "TouchScene.h"
...
bool AppDelegate::applicationDidFinishLaunching() {
    ...

    // create a scene. it's an autorelease object
	auto scene = TouchScene::createScene();
    // run
    director->runWithScene(scene);

    return true;
}

最后,运行就可以了。

分析TouchScene中的用到的方法

  • 关于EventListenerTouchOneByOne事件监听器处理函数的定义
class CC_DLL EventListenerTouchOneByOne : public EventListener
{   
    
public:
    typedef std::function<bool(Touch*, Event*)> ccTouchBeganCallback;
    typedef std::function<void(Touch*, Event*)> ccTouchCallback;

    ccTouchBeganCallback onTouchBegan;
    ccTouchCallback onTouchMoved;
    ccTouchCallback onTouchEnded;
    ccTouchCallback onTouchCancelled;
...
   
};

我们根据此来定义我们的函数,上面规定了处理函数的返回值形参顺序。其实我们也可以使用Lambda表达式来定义处理函数,如:

touchListener->onTouchBegan = [](Touch* touch,Event* event)->bool{
// todo
}

完整的例子,我们修改init方法,让其使用lambda表达式来定义处理函数:

//
// Created by kyun on 20-3-12.
//

#include "TouchScene.h"

USING_NS_CC;


Scene* TouchScene::createScene() {
    auto scene = Scene::create();
    auto layer = TouchScene::create();
    scene->addChild(layer);
    return scene;
}

bool TouchScene::init() {
    if(!Layer::init()){
        return false;
    }
    auto sprite = Sprite::create("logo2.png");
    sprite->setAnchorPoint(Vec2(0.5,0.5));
    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    sprite->setPosition(Vec2(visibleSize.width/2+origin.x,visibleSize.height/2+origin.y));
    
    auto touchListener = EventListenerTouchOneByOne::create();
    touchListener->onTouchBegan = [](Touch* touch,Event* event)->bool{
        auto bounds = event->getCurrentTarget()->getBoundingBox();
        if(bounds.containsPoint(touch->getLocation())){
            std::stringstream touchDetails;
            touchDetails <<
            "Touched at OpenGL coordinates:" <<touch->getLocation().x << "," << touch->getLocation().y << std::endl<<
            "Touched at UI coordinate:"<<touch->getLocationInView().x << "," << touch->getLocationInView().y << std::endl <<
            "Touched at local coordinate:" <<
            event->getCurrentTarget()->convertToNodeSpace(touch->getLocation()).x << "," <<
            event->getCurrentTarget()->convertToNodeSpace(touch->getLocation()).y << std::endl<<
            "Touch moved by:" << touch->getDelta().x << "," << touch->getDelta().y;

            ccMessageBox(touchDetails.str().c_str(),"Touched");
        }
        return true;
    };
    // Add a "touch" event listener to our sprite
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener,sprite);

    this->addChild(sprite,0);
    this->addChild(labelTouchInfo);
    return true;
}

上面的效果就是点sprite后会弹出一个对话框。

  • ccMessageBox()弹窗
  • touch->getLocationInView()返回在屏幕坐标系(原点在屏幕左上角)中的位置
  • touch->getLocation()返回在OpenGL坐标系(原点在屏幕左下角)中的位置

谢谢阅读

上一篇:移动端丨-webkit-overflow-scrolling:touch属性导致页面卡住


下一篇:Web前端笔试整理3