***************************************转载请注明出处:http://blog.youkuaiyun.com/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。。