1,retina的问题
bool CCDirector::enableRetinaDisplay(bool bEnable); 用于开启retina模式,返回bool值表示是否开启成功。
cocos2d-1.0.1-x-0.11.0和cocos2d-1.0.1-x-0.12.0两个版本的该函数在win32下会返回不同的值,原因见第4条。
在支持retina设备下(目前是ip4/itouch4或以上),CCDirector中的m_fScaleFactor(大概是这么写)会被设置为2,否则为1。
这个值用于确定渲染时元素的尺寸,比如480x320px的图片,开启retina之后,在ip4屏幕上将占一半大小(此时屏幕分辨率为960x640),
retina未开启时,将占住整个屏幕(此时屏幕分辨率为480x320),其实屏幕还是那块屏幕,硬件并没有变化,只是元素被绘制成不同尺寸了。
CC_CONTENT_SCALE_FACTOR()这个宏可以直接获取当前的m_fScaleFactor。
2,如何让程序界面适配iphone(480x320),iphone-retina(960x640),ipad(1024x768)
实际项目中经常会遇到的问题,一套资源应用于多个型号。目前的解决方式是,美术按1024x768的场景出背景图,场景元素等资源。
获取设备分辨率
if(width >= 1024){ //ipad
资源不做裁剪和缩放直接使用;
}else{ //iphone or iphone-retina
背景图上下切去43个像素高的部分,切除后背景图宽高比等于屏幕宽高比,可进行下面的等比缩放
float fScale = width/1024; //裁剪后的背景图 和其他元素的缩放比例
对各种元素按照fScale应用缩放(特别注意:以像素为单位的位置坐标也应一并缩放)。。。 。。。
}
这个建议是陶小胖提出来的,适合一套资源适配多个型号,因为本身就是HD的资源,HD屏幕完全没问题,只是应用在非retina型号时,资源偏大,浪费了。但没办法,前提是没有时间出多套资源。
3,point和pixel的问题
void CCNode::setPosition(CCPoint &pos); void CCNode::setPositionInPixels(CCPoint &pos);
void CCNode::setContentSize(CCSize &size); void CCNode::setContentSizeInPixels(CCSize &size);
... ...
可以看到cocos2d中有一些这种前面同名后缀不同的函数,一般都是和元素的尺寸,位置相关的操作。
其实它们执行效果同与不同由CC_CONTENT_SCALE_FACTOR()决定(见第1条),缩放因子为1时,它们的效果是一样的,缩放因子为2时(retina模式),pixels的值是point的两倍,举个栗子:
retina未开启(分辨率480x320):
pSprite->setPosition(ccp(480, 320)); 会把pSprite设置到屏幕的右上角(距离左下角原点480x320像素的位置)
pSprite->setPositionInPixels(ccp(480, 320)); 会把pSprite设置到屏幕的右上角(距离左下角原点480x320像素的位置)
实际是把pSprite都设置到了距离屏幕左下原点480x320像素的位置
retina开启(分辨率960x640):
pSprite->setPosition(ccp(480, 320)); 会把pSprite设置到屏幕的右上角(距离左下角原点960x640像素的位置)
pSprite->setPositionInPixels(ccp(480, 320)); 会把pSprite设置到屏幕的正中(距离左下角原点480x320像素的位置)
可以很清楚的看出 xxxInPixels(...)是直接按照像素尺寸进行的操作,可以说是最直观的操作
而不带InPixels的操作是对“point”的操作,框架会认为传入的参数是基于point的,自动将pixels的值在point基础上乘以CC_CONTENT_SCALE_FACTOR()
实际项目中,因为美术出图都是按像素来标注尺寸和位置,比如这个元素距背景左下角多少个像素等等,所以程序需要直接操作像素,
再举个栗子: 一个魔鬼的图片,美术告诉我应该在背景上距左下角200x30像素的位置,那么就应该pDemon->setPositionInPixels(ccp(200,30));,如果pDemon->setPosition(ccp(200,30));,非retina模式下到没问题,一旦开启retina,pDemon就会跑到400x60的位置去了。
总结一下设置和尺寸需要注意的函数
CCDirector::getWinSize(); CCDirector::getWinSizeInPixels();
CCNode::set/getPosition(); CCNode::set/getPositionInPixels();
CCNode::set/getContentSize(); CCNode::set/getContentSizeInPixels();
CCSprite::spriteWithFile(char* pszFileName, CCRect & rect);
这个是截图时用,一定注意:这里的rect是point的尺寸,而不是pixels的!
各种移动以及和位置相关action,如 CCMoveTo::actionWithDuration(float fDur, CCPoint & posDst);
这里面传入的参数都应为point的值。举个花生:
需要pDemon移动到300x100像素的位置,就应该这么写
CCMoveTo::actionWithDuration(1.0f, ccp(300/CC_CONTENT_SCALE_FACTOR(), 100/CC_CONTENT_SCALE_FACTOR()));
retina模式时,传入的实际参数就是150x50了,框架会再乘以CC_CONTENT_SCALE_FACTOR()转化为像素坐标(吃饱了撑得吧
)
怎么CCMoveTo不支持直接传入像素坐标呢?!
4,enableRetinaDisplay在不同版本下的问题
今天遇到个有趣问题,陶小胖在win32+vs2010环境下,开启retina后按道理 CCDirector::getWinSizeInPixels();应该返回960x640(前面win32窗口大小设置的是480x320),但实际却返回480x320,似乎没起作用。而同样的代码在我的机器上,却能返回960x640,调试一番,找出原因所在: 我用的是cocos2d-1.0.1-x-0.11.0版本,他用的是cocos2d-1.0.1-x-0.12.0版,两者在bool CCDirector::enableRetinaDisplay(bool bEnable); 内部实现有点不同,0.12.0版本多加了一个判断,当环境是win32时,会直接返回retina不可开启,而0.11.0版本没有判断是否win32,让vs下也能模拟retina的效果,不知道为什么新的版本反而要取消win32下的模拟,有知道的达人请告之!!
解决方法:要么换到0.11.0版本,要么把判断win32的那句代码注释掉(准确的说不是判断win32,是win32平台下,就会自动调用适合win32的EGLView)。自作多情有木有!!
荷兰死得憋屈有木有!俄罗斯死得憋屈有木有!
5,CCPointExtension.h里有各种对CCPoint操作的宏,比如乘法,减法等