cocos2d 精灵怎么设置触摸精灵打开设置

一个简单实例理解cocos2d-x触摸事件中的坐标系_cocos2dx吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:9,003贴子:
一个简单实例理解cocos2d-x触摸事件中的坐标系收藏
有关cocos2d-x的坐标系一直以来都是很复杂的概念,不容易理解,而坐标系用的最多的地方就是触摸事件的处理。 看人家写的代码经常用到
getLocationInView, convertToGL, 还有convertToNodeSpace 这一堆函数都头痛死了,这些函数是干马用的?到底怎么用呢?相信吓坏了一大批新手,网上查不是讲的不甚明了就是原理说的太过复杂不知要领,现在举个简单例子加以说明
首先要理解4个坐标系,这个是省不了的。
(1)OpenGL坐标系Cocos2D-x以OpenGL和OpenGL ES为基础,所以自然用的是OpenGL坐标系。该坐标系原点在屏幕左下角,x轴向右,y轴向上。(2)屏幕坐标系屏幕坐标系使用的是不同的坐标系统,它是windows开发或者几何数学常用的坐标系统,可惜Cocos2d-x处理位置信息时不用这个坐标系。所以从实际问题转换到2dx中经常要碰到屏幕坐标转OpenGL坐标系的问题,屏幕坐标系的原点在屏幕左上角,x轴向右,y轴向下。iOS的屏幕触摸事件是个特例,它的CCTouch传入的位置信息使用的是该坐标系。因此在Cocos2D-x中对触摸事件做出响应前,需要首先把触摸点转化到OpenGL坐标系。这一点在后面的触屏信息中会详细介绍,可以使用CCDirector的convertToGL方法来完成这一转化。①从触摸点获取到在屏幕坐标系中的坐标
// returns the current touch location in screen coordinates
CCPoint CCTouch::getLocationInView() const
②从触摸点获取到在OpenGL坐标系中的坐标
// returns the current touch location in OpenGL coordinates
CCPoint CCTouch::getLocation() const
return CCDirector::sharedDirector()-&convertToGL(m_point);
(3)世界坐标系统世界坐标系也叫作绝对坐标系,是游戏开发中建立的概念,因此,“世界”即是游戏世界。它建立了描述其他坐标系所需要的参考标准。我们能够用世界坐标系来描述其他坐标系的位置。它是Cocos2D-x中一个比较大的概念。Cocos2D-x中的元素是有父子关系的层级结构。通过CCNode设置位置使用的是相对其父节点的本地坐标系,而非世界坐标系。最后在绘制屏幕的时候,Cocos2D-x会把这些元素的本地节点坐标映射成世界坐标系坐标。世界坐标系和OpenGL坐标系方向一致,原点在屏幕左下角,x轴向右,y轴向上。(4)节点坐标系统节点坐标系是和特定节点相关联的坐标系。每个节点都有独立的坐标系。当节点移动或改变方向时,和该节点关联的坐标系(它的子节点)将随之移动或改变方向。这一切都是相对的,相对于基准的,只有在节点坐标系中才有意义。CCNode类的设置位置使用的就是父节点的节点坐标系。它和OpenGL坐标系的方向也是一致的,x轴向右,y轴向上,原点在父节点的左下角。如果父节点是场景树中的顶层节点,那么它使用的节点坐标系就和世界坐标系重合了。实例:
void MyLayer::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) {
// 获取单点
CCTouch *pTouch = (CCTouch*)(pTouches-&anyObject());
for(CCSetIterator iterTouch = pTouches-&begin(); iterTouch != pTouches-&end(); iterTouch++) {
CCTouch *pCurTouch =
(CCTouch*)(*iterTouch);
// 先获取点在视图中的屏幕坐标(左上角为原点)
CCPoint touchLocation = pTouch-&getLocationInView();
// 再把点的坐标转换成OpenGL坐标(左下角为原点)
touchLocation = CCDirector::sharedDirector()-&convertToGL(touchLocation);
// 把OpenGL的坐标转换成CCLayer的本地坐标系,原点为精灵锚点所在
CCPoint local = convertToNodeSpace(touchLocation)
// 大小为100x100,坐标为(0, 0)的矩形
CCRect * rect = CCRectMake(0, 0, 100, 100);
// 判断该触摸点是否在rect矩形内
bool flag = rect.containsPoint(local)
if(flag) {
}可看出最后那个rect几乎就是个常量,它的0,0就是本地坐标系原点,此rect很可能就是精灵的包围盒,把触摸点转换到本地坐标系后如此简单不用再计算它跟着精灵在世界坐标走的具体位置了,这就是坐标转换的妙用.
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或分享给朋友:通用代码: <input id="link4" type="text" class="form_input form_input_s" value="" />复 制flash地址: 复 制html代码: <input type="text" class="form_input form_input_s" id="link3" value="" />复 制分享视频到站外获取收益&&手机扫码分享视频二维码2小时内有效从零开始手把手教你cocos2d-x第4期 ccTouch的单点触摸与精灵拖拽下载至电脑扫码用手机看用或微信扫码在手机上继续观看二维码2小时内有效从零开始手把手教你cocos2d-x第4期 ccTouch的单点触摸与精灵拖拽扫码用手机继续看用或微信扫码在手机上继续观看二维码2小时内有效,扫码后可分享给好友没有优酷APP?立即下载请根据您的设备选择下载版本
药品服务许可证(京)-经营-
节目制作经营许可证京字670号
请使用者仔细阅读优酷、、
Copyright(C)2017 优酷
不良信息举报电话:cocos3.0通过精灵控制精灵的触摸事件的实现
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
sprite = this->getChildByTag(virTag)->getChildByTag(jumpTag);
listener->onTouchBegan = CC_CALLBACK_2(MLayer::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(MLayer::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(MLayer::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, sprite);
//该精灵享有触摸
MLayer::onTouchBegan(Touch* touch, Event*
auto target = static_cast(event->getCurrentTarget());//获取当前的触摸目标(那个跳跃精灵)
Point locationInNode = target->convertToNodeSpace(touch->getLocation());//将本地坐标系转化为精灵坐标系(以精灵的左下角作为坐标原点)
Size s= target->getContentSize();//获取精灵的文本尺寸大小
Rect rect = Rect(0, 0, s.width, s.height);//获取精灵的矩形框(起始点为精灵的左下角)
if (rect.containsPoint(locationInNode))//判断触摸点是否在精灵的矩形框上
auto sprite2 =this->getChildByTag(cmsTag)->getChildByTag(catTag);
sprite2->setScale(0.2f);
void MLayer::onTouchMoved(Touch* touch, Event* event)
auto target = static_cast(event->getCurrentTarget());//获取当前的触摸目标
Point locationInNode = target->convertToNodeSpace(touch->getLocation());//将本地坐标系转化为精灵坐标系(以精灵的左下角作为坐标原点)
Size s = target->getContentSize();//获取精灵的文本尺寸大小
Rect rect = Rect(0, 0, s.width, s.height);//获取精灵的矩形框(起始点为精灵的左下角)
if (rect.containsPoint(locationInNode))//判断触摸点是否在精灵的矩形框上
target->setPosition(target->getPosition() + touch->getDelta());//将捕获的精灵坐标设在移动结束的地方
void MLayer::onTouchEnded(Touch* touch ,Event* event)
auto sprite2 = this->getChildByTag(cmsTag)->getChildByTag(catTag);
sprite2->setScale(0.6f);Cocos2d-x3.0屏蔽下层触摸|皂荚花
有朋自远方来不亦乐乎!
程序不是看出来的,是写出来的!思想不是想出来的,是敲出来的!欢迎加群交流技术问题!
热度:7,070
关于这个问题网上有不少人在搜索,我自己曾经也写过一篇文章,,其中就用到了屏蔽下层触摸这个功能。Cocos2d-x从3.0版本以来,触摸机制有所改变,虽然实现的道理没有变,不过我今天还是写出这篇博客,就当是简单的复习一下3.0的事件分发机制吧,同时把自己在研究的过程中遇到的问题分享出来。这里采用的方法是最简单,最直接的方法,整体的思路是这样的。设置触摸监听器吞噬触摸,然后在回调函数onTouchBegan中返回true,同时确保这个层的触摸优先级大于你要屏蔽的层的优先级。也许这种方法不能满足你得需求,那就请自行研究或者看下其他博客,或者给我留言共同探讨吧。在实现中我们肯定会遇到的就是屏蔽菜单,让菜单变的不可点击,那我就写一个简单的场景,里边加入菜单,然后加入一个层来屏蔽掉下层的触摸。
bool CreateGame::init()
if(!Layer::init())
auto size = Director::getInstance()-&getWinSize();
Vector&MenuItem *& itemV
for(int i=1;i&4;i++)
auto item = MenuItemImage::create(&no_people.png&,&people.png&);
item-&setTag(i);
itemVector.pushBack(item);
auto menu1 = Menu::createWithArray(itemVector);
menu1-&alignItemsHorizontallyWithPadding(10);
menu1-&setPositionY(size.height*0.75);
this-&addChild(menu1);
auto swallowTouch = SwallowTouch::create();
this-&addChild(swallowTouch);
这里在最后添加了一个层,这个层就是用来的,大家要注意添加这个层的位置,这个层是最后添加进来的,也就是说它要显示的话是显示在最前边的,这个和接下来的屏蔽触摸有联系。以下是这个层的init函数。
bool SwallowTouch::init()
if(!LayerColor::initWithColor(Color4B(100,100,100,100)))
auto label = Label::createWithTTF(&touch!&,&fonts/Marker Felt.ttf&,32);
label-&setPosition(Point(350,800));
this-&addChild(label);
auto callback = [](Touch * ,Event *)
auto listener = EventListenerTouchOneByOne::create();
listener-&onTouchBegan =
listener-&setSwallowTouches(true);
_eventDispatcher-&addEventListenerWithSceneGraphPriority(listener,this);
//_eventDispatcher-&addEventListenerWithFixedPriority(listener,-1);
代码很简单,只是添加了一个事件监听器,设置这个事件监听器吞噬掉触摸,在onTouchBegan回调函数中返回了true。最主要的东西是将事件监听器添加到分发器中的代码,这里可以选择俩种方式来做,如果选择的是第一种,第二个参数是要求我们来将这个事件监听器和一个node绑定,什么是和node绑定,就是这个node对触摸的处理是和这个listener一样的,比如触摸的优先级,接受到触摸以后的处理代码,或者说这个listener来处理node接受到得触摸消息。这个时候Listener的优先级就是绑定的node的显示优先级,就是谁显示在场景的前面,谁先接受到触摸消息,所以在主场景的代码中,我们要把创建这个layer的代码放到后边,这样的话才会优先级高,才会首先收到触摸消息。然后来看第二种方法,addEventListenerWithFixedPriority函数的调用没有去绑定一个node,这个时候它的优先级就是通过第二个参数去传递的,我们通过改变这个优先级可以看下最后的效果,如果我设置为-1是可以成功屏蔽下层的菜单点击的,如果设置为0,那么程序运行会报错,如果设置为1,是屏蔽不掉下层的触摸的。这是因为0这个优先级是被占用了得,我们设置优先级不能设置为0,而要想屏蔽菜单的点击功能,必须设置优先级小于0,以下是这三个值的效果。
因为没有绑定那个LayerColor,所以是没有那个灰度的效果的。如果我只是要屏蔽下层按钮的点击,大可以将代码写到一个类中去完成,其实你也看到了,listener的作用就是事件监听,你可以给它绑定一个node,这个时候它的优先级就是node的显示优先级了,如果是手动设置优先级,不要设置为0的优先级就好了,这个时候当触摸分发的时候,会根据优先级关系来决定listener是否能接受的到触摸,写到一个类中的代码如下。
bool CreateGame::init()
if(!Layer::init())
auto size = Director::getInstance()-&getWinSize();
Vector&MenuItem *& itemV
for(int i=1;i&4;i++)
auto item = MenuItemImage::create(&no_people.png&,&people.png&);
item-&setTag(i);
itemVector.pushBack(item);
auto menu1 = Menu::createWithArray(itemVector);
menu1-&alignItemsHorizontallyWithPadding(10);
//设置菜单为不可点击
//menu1-&setEnabled(false);
menu1-&setPositionY(size.height*0.75);
auto item = (MenuItem *)menu1-&getChildByTag(1);
item-&selected();
this-&addChild(menu1);
auto layer = LayerColor::create(Color4B(100,100,100,100));
auto callback = [](Touch * ,Event *)
auto listener = EventListenerTouchOneByOne::create();
listener-&onTouchBegan =
listener-&setSwallowTouches(true);
_eventDispatcher-&addEventListenerWithSceneGraphPriority(listener,layer);
//_eventDispatcher-&addEventListenerWithFixedPriority(listener,-1);
this-&addChild(layer);
最后有一点需要注意的是,如果是固定优先值的监听器添加到一个节点(addEventListenerWithFixedPriority),那当这个节点被移除时必须同时手动移除这个监听器,但是添加显示优先监听器到节点(addEventListenerWithSceneGraphPriority)就不用这么麻烦,监听器和节点是绑定好的,一旦节点的析构函数被调用,监听器也会同时被移除。如果我们屏蔽了触摸,在某个逻辑处需要将这种触摸屏蔽去掉,比如就是做一个弹出对话框,用户点击了关闭按钮就应该将对下层的屏蔽去掉了,那么很显然,如果使用的是固定优先级,只是remove掉这个对话框最后是不能去除屏蔽的,因为事件监听器你并没有去掉啊,当有触摸事件过来的时候照样会分发给它事件的,所以解决办法不用说了吧。
2014年十月 &(8)
2014年九月 &(3)
2014年八月 &(7)
2014年七月 &(14)
2014年六月 &(15)
2014年五月 &(19)
2014年四月 &(14)
2014年三月 &(22)
2014年二月 &(59)
2014年一月 &(16)
小广告-翻墙小插件
文章关键字
Powered byCocos2d-x实例:单点触摸事件 -
发表时间:
为了让大家掌握Cocos2d-x中的事件机制,下面我们以触摸事件为例,使用事件触发器实现单点触摸事件。该实例如图8-3所示,场景中有三个方块精灵,显示顺序如图8-3所示,拖拽它们可以移动它们,事件响应优先级是按照它们的显示顺序。
下面我们再看看具体的程序代码,首先看一下HelloWorldScene.h文件,它的代码如下:
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
typedef enum
kBoxA_Tag = 102
,kBoxB_Tag
,kBoxC_Tag
class HelloWorld : public cocos2d::Layer
static cocos2d::Scene* createScene();
virtual bool init();
virtualvoid onEnter();
virtualvoid onExit();
booltouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
void touchMoved(cocos2d::Touch *touch, cocos2d::Event *event);
void touchEnded(cocos2d::Touch *touch, cocos2d::Event *event);
CREATE_FUNC(HelloWorld);
#endif // __HELLOWORLD_SCENE_H__
上述代码第①~②行是定义个枚举类型SpriteTags,枚举类型SpriteTags中定义了三个常量,这三个常量对应场景中的三个精灵的标签(Tag)属性。代码第③行声明了层声明周期的onEnter()函数,我们将在该函数中注册监听器和初始化设置。第④行代码是声明了层声明周期的onExit()函数,我们将在该函数中注销监听器和释放一些资源。代码第⑤~⑥行是声明单点触摸事件回调函数。
HelloWorldScene的实现代码HelloWorldScene.ccp文件,它的HelloWorld::init()代码如下:
bool HelloWorld::init()
if( !Layer::init() )
SizevisibleSize = Director::getInstance()-getVisibleSize();
Pointorigin = Director::getInstance()-getVisibleOrigin();
//贴图的纹理图片宽高必须是2的n次幂,128x128
autobg = Sprite::create("BackgroundTile.png",
Rect(0,0, visibleSize.width, visibleSize.height));
//贴图的纹理参数,水平重复平铺,垂直重复平铺
Texture2D::TexParamstp = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};
bg-getTexture()-setTexParameters(tp);
bg-setPosition(origin+ Point(visibleSize.width/2, visibleSize.height/2));
addChild(bg,0);
Sprite*boxA = Sprite::create("BoxA2.png");
boxA-setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2) + Point(-120, 120));
addChild(boxA,10, kBoxA_Tag);
Sprite*boxB = Sprite::create("BoxB2.png");
boxB-setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2));
addChild(boxB,20, kBoxB_Tag);
Sprite*boxC = Sprite::create("BoxC2.png");
boxC-setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2) + Point(120, 160));
addChild(boxC,30, kBoxC_Tag);
我们在HelloWorld::init()函数中初始化了场景中的背景和三个方块精灵。代码第①~④行是创建并添加背景,图8-3所示的背景是由一个128x128纹理图片(BackgroundTile.png)反复贴图上,这样可以减少内存消耗,在第①行代码中创建背景精灵对象,注意背景的大小仍然是整个屏幕。第②行代码是设置贴图的纹理的参数,Texture2D::TexParams类型是一个结构体。第③行代码是将参数设置到背景精灵的纹理上。第④行代码是添加背景精灵到当前层。
代码第⑤~⑥行是创建了三个方块精灵,在添加它到当前层的时候我们使用三个参数的addChild(Node* child,int localZOrder,int tag)函数,这样可以通过localZOrder参数指定精灵的显示顺序。
HelloWorldScene.ccp中的HelloWorld::onEnter()代码如下:
void HelloWorld::onEnter()
Layer::onEnter();
log("HelloWorldonEnter");
autolistener = EventListenerTouchOneByOne::create();
listener-setSwallowTouches(true);
listener-onTouchBegan= CC_CALLBACK_2(HelloWorld::touchBegan, this);
listener-onTouchMoved=
CC_CALLBACK_2(HelloWorld::touchMoved,this);
listener-onTouchEnded=
CC_CALLBACK_2(HelloWorld::touchEnded,this);
//添加监听器
EventDispatcher*eventDispatcher = Director::getInstance()-getEventDispatcher();
eventDispatcher-addEventListenerWithSceneGraphPriority(listener,
getChildByTag(kBoxA_Tag));
eventDispatcher-addEventListenerWithSceneGraphPriority(listener-clone(),
getChildByTag(kBoxB_Tag));
eventDispatcher-addEventListenerWithSceneGraphPriority(listener-clone(),
getChildByTag(kBoxC_Tag));
上述代码第①行是创建一个单点触摸事件监听器对象。第②行代码是设置是否吞没事件,如果设置为true,那么在onTouchBegan函数返回 true 时吞没事件,事件不会传递给下一个Node对象。第③行代码是设置监听器的onTouchBegan属性回调函数。第④行代码是设置监听器的onTouchMoved属性回调函数。第⑤行代码是设置监听器的onTouchEnded属性回调函数。
代码第⑥~⑨行是添加监听器,其中第⑦行使用精灵显示优先级添加事件监听器,其中参数getChildByTag(kBoxA_Tag)是通过精灵标签Tag实现获得精灵对象。第⑧行和第⑨行代码是为另外两精灵添加事件监听器,其中listener-&clone()获得listener对象,使用clone()函数是因为每一个事件监听器只能被添加一次,addEventListenerWithSceneGraphPriority和addEventListenerWithFixedPriority会在添加事件监听器时设置一个注册标识,一旦设置了注册标识,该监听器就不能再用于注册其它事件监听了,因此我们需要使用listener-&clone()克隆一个新的监听器对象,把这个新的监听器对象用于注册。
HelloWorldScene.ccp中的触摸事件回调函数代码如下:
bool HelloWorld::touchBegan(Touch*touch, Event* event)
//获取事件所绑定的 target
autotarget = static_cast*(event-getCurrentTarget());
PointlocationInNode = target-convertToNodeSpace(touch-getLocation());

我要回帖

更多关于 cocos 设置精灵大小 的文章

 

随机推荐