zoukankan      html  css  js  c++  java
  • Cocos2d-x 3.0 屏幕触摸及消息分发机制

    ***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************



    题外话:

    唉。

    开学了!    好烦。

    这就已经大三了,

    两年前的这时候,我还是懵懂的大一小学弟,

    两年后。就要奔上社会就业了。

    光阴似箭。日月如梭呀~



    正文:

    好久没做cocos2d-x了,这次练习一下。屏幕触摸及消息分发机制。

    这里,我用的是cocos2d-x 3.0版本号来进行练习的,环境是 VS2012+WIN7


    首先。新建一个项目,并向场景增加一个精灵。

    新建项目: cocos  new -p xxx(包名)  -l xxx(语言)  -d xxx(保存路径)

    选择一个精灵,放到resource文件夹下,并在VS2012中增加资源项。



    然后。建立一个新的精灵。加入到当前场景Hello World

    auto sprite_2 = Sprite::create("player.png");
    sprite_2->setPosition(Point(visibleSize.width/2+origin.x,visibleSize.height/2+origin.y));
    // 图片略大,缩小一下
    sprite_2->setScale(0.4f);
    this->addChild(sprite_2);

    这样。已经增加了一个精灵,接下来要做的就是触摸事件的处理。


    我们要实现触摸一个位置,让精灵跟着移动到该位置。步骤为:

    ——定义监听事件的侦听对象

    ——定义侦听对象的回调方法

    ——在事件分发器上注冊


    由于点击一个位置,用OneByOne这个单点触摸就可以。

    首先。定义监听事件的侦听对象:

    auto listener=EventListenerTouchOneByOne::create();


    然后。定义回调方法。

    我们精灵所在的scene类继承自Layer类,Layer类中。有触摸的虚函数,

    因此,我们仅仅须要复制过来,进行覆盖就能够定制回调函数了。

    先到Layer类中,找到onTouchBegan,onTouchMoved,onTouchEnded



    然后,拷贝到HelloWorldScene.h中声明,并在.cpp中定义



    先进行一些简单的定义,然后在文件里,要制定回调方法,从下图可知:


    CC_CALLBACK_2有两个參数,_selector_ and _target_

    _selector_:选择哪个函数进行回调?   ——显然是当前类中的对应函数啦

    _target_:由哪个对象触发?——就是当前的场景

    所以,最后应该是:

    // 定义监听对象的回调方法
    listener->onTouchBegan=CC_CALLBACK_2(HelloWorld::onTouchBegan,this);
    listener->onTouchMoved=CC_CALLBACK_2(HelloWorld::onTouchMoved,this);
    listener->onTouchEnded=CC_CALLBACK_2(HelloWorld::onTouchEnded,this);

    (PS:为虾米用CC_CALLBACK_2?

    点击进入它的定义。能够看到:

    // new callbacks based on C++11
    #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
    #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
    #define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
    #define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)

    CC_CALLBACK_..  这个事实上都是在用std::bind来进行的操作。

    白话来说,就是实现了一个对象和一个方法的绑定执行。

    要注意的是,后面的_几,并非代表有几个參数,而是有几个占位符。

    更加具体内容,能够看这个→  std::bind与CC_CALLBACK不得不说的故事  )


    *****这里也体现出了cocos2d-x 2.x和3.x的小差别:

    在2.x中。须要注冊一个事件侦听。

    而在3.x中。则须要定义一个侦听器的对象。然后定义回调方法。最后还要将侦听和事件分发器绑定。


    如今来向事件分发器加入:

    _eventDispatcher

    注冊一个侦听事件,主要有以下几种:









    我们用的是最后一种。基于场景图的优先级的。

    // 在事件分发器中注冊
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);

    两个參数,第一个表示侦听对象,第二个表示在哪个节点进行。


    说了这么多了。我们来试一试,到眼下为止。是否正确。

    也就是检測一下,我们的点击动作是否能被获取并分发。


    在,HelloWorld::onTouchBegan中,设置在控制台输出所点击的坐标:

    bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
    {
    	log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);
    	return true;
    }

    log就是打印功能。

    %lf,输出的坐标为 double型,

    getLocation是得到OpenGL坐标系(左下角为0,0点)

    getLocationInView是得到当前屏幕坐标系(左上角为0,0点)


    OK,搞定。执行!

    有错误!




    将Layer里onTouchBegan复制过来,没有给他们加命名空间,

    能够直接在HelloWorldScene.h中加一句:

    using namespace cocos2d;    

    或者 USING_NS_CC;

    再或者。不嫌麻烦。就在对应Touch和Event前加cocos2d::

     bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event); 
     void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event); 
     void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event); 

    好了,如今执行一下吧~



    恩,点击鼠标。输出对应的位置坐标。


    我们能够继续做下去了!

    我们的目标是。点击屏幕,然后让我们指定的精灵移动到该位置。

    如今,我们能够获取到点击屏幕的位置了,怎样让指定的精灵移动到该位置呢?

    要想指定精灵。那就要用到Tag,给精灵做一个标记,setTag

    sprite_2->setTag(33);

    我给它定义了一个编号33(当然,依照心情。随便设置的。)


    编号设置了,如今,让用户触摸这个点以后,得到这个精灵,便于后面进行对应操作。

    bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
    {
    	log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);
    	// 新建一个精灵。通过编号得到这个精灵
    	auto sprite=this->getChildByTag(33);
    	sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));
    	return true;
    }

    如今,我们能够通过点击某个点。我们的精灵的中心就会在该点了,

    接下来。能够做一些动作了。不要立即出现,让它移动过去。


    这个,能够通过之前学习的  runAction中的MoveTo来解决:

    bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
    {
    	log("the location is: %lf,%lf !",touch->getLocationInView().x,touch->getLocationInView().y);
    	// 新建一个精灵。通过编号得到这个精灵
    	auto sprite=this->getChildByTag(33);
    //	sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));
    	sprite->runAction(MoveTo::create(0.5,Point(touch->getLocation().x,touch->getLocation().y)));
    	return true;
    }

    完毕了,~(*^__^*) ~


    如今。来个更加难一点的。怎样进行拖动?

    事实上,也不难的,就是在onTouchMoved中,获取这个精灵,并setPosition。当然之前onTouchBegan的对应都要删除。

    void HelloWorld::onTouchMoved(Touch *touch, Event *unused_event)
    {
    	auto sprite=this->getChildByTag(33);
    	sprite->setPosition(Point(touch->getLocation().x,touch->getLocation().y));
    }

    OK,执行一下,耍一耍吧。



    恩,这次就到这里了。

    这次做的是。通过点击屏幕让 角色 移动到该位置,能够直接出现。也能够移动过去,还能够拖动。

    过程例如以下:

    1.创建一个所须要操作的精灵于场景中

    2.创建监听事件的侦听对象

    3.定义对象的回调函数

    4.在事件分发器中进行注冊

    5.更改onTouchBegan,onTouchMoved内对应内容,来实现目的。


    End。。




    ***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************

  • 相关阅读:
    (双指针 二分) leetcode 167. Two Sum II
    (双指针) leetcode 485. Max Consecutive Ones
    (双指针) leetcode 27. Remove Element
    (String) leetcode 67. Add Binary
    (数组) leetcode 66. Plus One
    (N叉树 BFS) leetcode429. N-ary Tree Level Order Traversal
    (N叉树 递归) leetcode 590. N-ary Tree Postorder Traversal
    (N叉树 递归) leetcode589. N-ary Tree Preorder Traversal
    (N叉树 DFS 递归 BFS) leetcode 559. Maximum Depth of N-ary Tree
    (BST 递归) leetcode98. Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6792361.html
Copyright © 2011-2022 走看看