day02 坐标体系,游戏优化,定时器,Touch
Day02
1,坐标体系
OperGL坐标 以左下角为原点,向右是X,向上是Y,cocos2d-x默认坐标体系与之一样
屏幕坐标系 屏幕坐标系使用的是不同的坐标系统,原点在屏幕左上角,x轴向右,y轴向下,iOS的屏幕触摸事件CCTouch传入的位置信息使用的是该坐标系。因此在Cocos2D-x中对触摸事件做出响应前,需要首先把触摸点转化到OpenGL坐标系。
世界坐标 世界坐标系也叫作绝对坐标系,是游戏开发中建立的概念,因此,“世界”即是游戏世界. 世界坐标系和OpenGL坐标系方向一致,原点在屏幕左下角,x轴向右,y轴向上。
节点坐标 又名本地坐标,每个精灵都有这自己的本地坐标. 节点坐标系是和特定节点相关联的坐标系,每个节点都有独立的坐标系。当节点移动或者改变方向的时候,和该节点相关联的坐标系(子节点)会随之一起移动或改变方向。
坐标转换函数
CCPoint p1 = sprite2->convertToNodeSpace(sprite1->getPosition());
CCPoint p2 = sprite2->convertToWorldSpace(sprite1->getPosition());
p1就是sprite1锚点相对于sprite2原点来说在sprite2坐标系中的位置
p2就是sprite1锚点相对于sprite2原点来说在上图坐标系中的位置
本人的理解:
convertToNodeSpace是指以sprite2的原点作为坐标系原点,sprite1的锚点距离sprite2原点的坐标.
convertToWorldSpace就是sprite1锚点相对于sprite2原点来说在上图坐标系中的位置,这句话可以理解为 将sprite1锚点原来距离原点的坐标位置等同换成距离sprite2原点位置,通俗地讲,原来sprite1距离父节点(X, Y),那么现在就距离sprite2的原点(X, Y).再求出此时sprite1锚点的世界坐标位置
小技巧: 针对本地坐标系就用减法,针对世界坐标系就用加法
setTouchEnabled(true);打开触摸开关
setTouchMode(kCCTouchesOneByOne);选择触摸模式(此时为单点)
在layer的初始化中设置
setColor(ccRED);
setTextureRect(CCRectMake(0, 0, 250, 150));当精灵创建为空时,可画出一片大小为250,150的红色区域.
CCMoveBy *move1 = CCMoveBy::create(2, ccp(100, 0)); 移动,类似于CCJumpBy
CCSequence *sq = CCSequence::create(move1, move2, NULL); 作为动作队列
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);为setTouchEnabled(true)设置事件,参数二为IOS的兼容而保留的.
转换坐标体系:
pTouch->getLocation() 获取当前触摸的坐标,体系为operGL
pTouch->getLocationInView(); 同上,不同的是体系为屏幕坐标
转换坐标系,由于是关联于整个屏幕,所有要由导演来转,代码如下
CCDirector::sharedDirector()->convertToUI(pGL); //转成operGL
CCDirector::sharedDirector()->convertToUI(pUI); //转成屏幕坐标
2.游戏的优化
主要使用类CCSpriteBatchNode
操作步骤为
一.在layer的init()中,创建CCSpriteBatchNode的实例,并加截plist的大图片,一般格式为.png,
二.由层(layer)来addChild,然后就可以在ccTouchBegan创建大量小精灵,
三.由BatchNode来addChild大量精灵
它的原理为,当在触摸事件一次性创建大量小精灵时,可以减少渲染次数,由BatchNode统一渲染,估计低层的实现在BatchNode->addChild(spr),最后由layer来addChild已经渲染好的结果,即layer->addChild(BatchNode).另外,BatchNode与Sprite属于同一级别.
小宏函数CCRANDOM_0_1(),产生一个0~1之间的随机数
3.Schedule游戏定时器
主要流程模型如下图
applicationDifFinshLaunching()完成一开始精灵的放置,触摸开关,也就是自定义中init()里做的事,当applicationDifFinshLaunching()返回后,执行while(1)大循环,其中mainLoop里完成绘图功能,遍历节点,完成定时功能,内存清理工作.. mainLoop返回后再进行消息循环.
定时器有三种方式
第一种, scheduleUpdate();最原始的计时器,每0.016秒执行一次相对应的执行函数为 void update(float t) override;该函数重写了父类函数
第二种, scheduleOnce
typedef void (CCObject::*SEL_SCHEDULE)(float);
scheduleOnce(SEL_SCHEDULE(&T06Schedule::myUpdate), 2);
这种方式只执行一次,延时2秒
其中第一个参数为回调函数(类型为SEL_SCHEDULE),第二个参数表示延时.代码含意为将T06Schedule::myUpdate类成员函数指针强转为CCObject::*SEL_SCHEDULE,类成员函数指针,该转换成功的前提是双方的参数相同(由于SEL_SCHEDULE类型包含一个参数float,所以, T06Schedule::myUpdate也应包含一float参数,参数传递的是延时的时间),只是所属的类不同.
第三种Schedule
该函数有以下几个重载函数
void CCNode::schedule(SEL_SCHEDULE selector)
void CCNode::schedule(SEL_SCHEDULE selector, float interval)
void CCNode::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay)
不管那一种,最后都是调用
m_pScheduler->scheduleSelector(selector, this, interval , repeat, delay, !m_bRunning);
参数说明
selector:回调函数,同
interval:时间间隔
repeat:重复次数, kCCRepeatForever永久重复
delay:从开始到第一次调用时的时间间隔.
Cocos2d-x里类成员函数里的小精灵相互传递方式
Spr-> setTag(xx) 将spr精灵挂在渲染树上,该渲染树为map模型(key-value),而xx对应key
CCSprite *spr = (CCSprite *)getChildByTag(xx); 取出该精灵,取出map模型里key为xx的value
getChildByTag返回的是CCNode *类型,注意类型转换
4.Touch
只有Layer及以下级别的才可以有触摸开关之类的操作函数
setTouchEnabled(true); 设置开关
setTouchMode(kCCTouchesOneByOne); 触摸模式
有四个父函数,分别表示不同触摸状态,
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
ccTouchBegan:鼠标按下(触摸开始),即被调用.返回表示消息是否向下传递.Shovel->boundingBox().containsPoint(pt), boundingBox()表示精灵缩放之后的大小,代码意思表示,Shovel 缩放后的大小是否包含(containsPoint)点pt. boundingBox()返回的是一个矩形,包含大小,及坐标. Shovel->getContentSize()获得实际大小,无视缩放.返回的是CCSize类型
ccTouchMoved:触摸滑动的时候触发,每一帧执行一次,一般用pTouch->getDelta()返回前后两帧的坐标差距,便于精灵移动.但注意移动边界限制.代码模版
ccTouchEnded:当手指离开屏幕时触发.
ccTouchCancelled:当触摸中断时触发,主要保存好游戏现状
参数说明
pTouch:用于获取点击或移动时的屏幕坐标, ,获取的坐标为世界坐标,属于OperGL坐标
pEvent:为苹果兼容而设定.目前用不上
5.touch优先级
CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
pDispatcher->addTargetedDelegate(this, m_nTouchPriority, true);
参数说明
This:当前层
m_nTouchPriority:优先级,数字越小,优先级越高
true:吞噬消息,不再往后传递
浙公网安备 33010602011771号