1.解决方案 先直接给出解决方案,再慢慢解释,当然这个解决方案也不是完全完美的。 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 //如果是横屏游戏: glview-setdesignresolutionsize( 960 , 640 , resolutionpolicy::fixed_height); //一张960x640
1.解决方案
先直接给出解决方案,再慢慢解释,当然这个解决方案也不是完全完美的。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//如果是横屏游戏:
glview->setdesignresolutionsize(960,640, resolutionpolicy::fixed_height);
//一张960x640的背景显示
auto visiblesize = director::getinstance()->getvisiblesize();
auto bg = sprite::create(bg.png);
this->addchild(bg);
bg->setposition(visiblesize.width / 2, visiblesize.height / 2);
//bg->setposition(visiblesize.width / 2, 320);//等价上面的
bg->setscalex(visiblesize.width / 960);
//右上角显示一个精灵
auto spr = sprite::create(test.png);
this->addchild(spr);
spr->setposition(visiblesize.width - 50, visiblesize.height - 50);
//因为是固定高度,所以visiblesize.height永远都是640,所以下面的写法也是可以的
//spr->setposition(visiblesize.width - 50, 590);
//如果是竖屏游戏:
glview->setdesignresolutionsize(640,960, resolutionpolicy::fixed_width);
美术出图都按照960x640规格出图。
2.开始测试各种适配方式
屏幕适配其实应该从opengles开始讲的,这里跳过了,感兴趣的可以看这篇文章了解一二《android 中使用opengl es进行2d开发(绘制第一个三角形番外篇)》
glview->setdesignresolutionsize(960, 640);先不管第三个参数。setdesignresolutionsize是什么意思呢?就是设置一个固定大小的区域来进行程序布局和美术设计。再通过opengles进行投射到具体手机屏幕上去,是无视具体手机屏幕大小的。比如手机屏幕分辨率是480x320,opengles会自动缩小一倍进行投射。手机屏幕分辨率是1920x1280,opengles会自动放大一倍进行投射。程序和美术这块都不需要改:一套程序坐标,一套美术资源。
比如背景图片,只需要一张960x640的就ok了,把它放在(480,320)的中心位置就ok了。
一个精灵假设要放在右上角的位置,把它放在(960,640)的位置就ok了。也根本不需要考虑cocos2d中的visiblesize什么的。
现实中,手机分辨率不可能都是960x640的倍数。而我们又要全屏显示,就有了第三个参数来规定具体投射的方式。
cocos2d的resolutionpolicy现在总共有5种:
?
1
2
3
4
5
6
7
8
enumclass resolutionpolicy
{
exact_fit,
no_border,
show_all,
fixed_height,
fixed_width
};
2.1 exact_fit
exact_fit是会完全投射到屏幕全屏的。这样对程序和美术来说是最完美的,但是会有拉伸的现象。
上面这张是960x540的原图,4个角我加上了参照物,总的是一张图片。
假设目标手机分辨率是1136x500(现实是不存在的),使用exact_fit就是下面的效果:
其实对于背景的拉伸,还是可以接受的,主要的问题是:精灵也会被拉伸,还有拉伸区域是不可控制的。
exact_fit适用场景:个人小项目,轻微拉伸不影响游戏的展示的游戏。但公司大项目这个基本不可用。
使用exact_fit的时候,visiblesize不管手机分辨率是多少,visiblesize永远都是960x640。
2.2 show_all
先来解释下show_all.它不会拉伸,但是左右或者上下会有黑边,没有全屏的感觉。
1136x640
1024x768
show_all 能不能用呢?几乎不能用。虽然它的visiblesize也都是960x640。但是黑边的问题,苹果那边是通过不的。这里的黑边是不能用东西来覆盖的。
2.3 no_border
no_border 顾名思义就是没有黑边,且保持宽高比。这样的结果就是,会有部分被裁剪掉。
1136x640
手机分辨率比较长的时候,上下不够,会被裁掉,注意看背景下面的参考物。
visiblesize width:960
visiblesize height:540.8450927734375 //不到640
1024x768
ipad分辨率比较高的时候,左右不够,会被裁掉,注意看背景左边的参考物。
visiblesize width:853.3333129882812 //不到960
visiblesize height:640
使用no_border会导致visible一直变化,且会被裁掉。
2.4 fixed_height
fixed_height和fixed_width是类似的,就讲个fixed_height。fixed_height和fixed_width是较高cocos2d版本才有的。这个解决方案是固定一个方向上的值,且固定比例。这样会导致部分覆盖不到或者部分被裁掉,要程序进行动态适配。
1136x640
图7
visiblesize width:1136 //会根据手机屏幕分辨率进行变化
visiblesize height:640 //永远固定是640
1024x768
visiblesize width:854 //会根据手机屏幕分辨率进行变化
visiblesize height:640 //永远固定是640
图7虽然这里的效果看起来跟show_all的一样,但是是完全不一样的,通过看visiblesize就知道了。这里的黑边我们是可以通过手动拉伸背景来覆盖的。有人就问了,拉伸背景不就跟exact_fit的一样了?不一样的!exact_fit是拉伸整个区域,场景放置的精灵也是会被拉伸的。fixed_height就不会拉伸精灵了。
精灵放置的位置就有讲究了,在纵向,完全可以使用魔鬼数字,320肯定是垂直居中的。横向就要斟酌了,比如要把一个精灵放在右上角就要考虑visiblesize了。
setposition(visiblesize.width - 50, 640 - 50);
下面是简单拉伸背景的效果,加上一个精灵。
?
1
2
3
4
5
6
7
8
9
10
var visiblesize = cc.director.getinstance().getvisiblesize();
var scalerate = visiblesize.width / 960;
var bg = cc.sprite.create(res/bg.jpg);
this.addchild(bg);
bg.setposition(visiblesize.width / 2, visiblesize.height / 2);
bg.setscalex(scalerate);
var sp = cc.sprite.create(res/menu1.png);
this.addchild(sp);
sp.setposition(100* scalerate,320);
1136x640
1024x768
其他安卓的分辨率就不列出来了。
3.讲讲资源适配
我们知道一套图片你想要同时适配960x640, 2048x1536或者将来的iphone6 plus 1920x1080,是很困难的。主要的问题是,如果你都是一套960x640的图片,那么在高分辨率下就不清楚了。如果你是一套1920x1280的图,那么在低分辨率的手机上运行比较卡。上面例子都是使用了960x640的分辨率作为设计分辨率,可以考虑将来手机分辨率就都比较高的时候上升点,比如上升到1248x832。
还有个问题是屏幕高宽比的问题,ipad是1024/768 即1.33 这个比例都比960/640 的1.5的要低,而iphone5,iphone6的屏幕高宽比例上升到1.775。在加上android的屏幕高宽比。可以考虑未来使用1.6的比例。比如1248x780作为设计分辨率。然后ipad上要格外小心要特殊处理,横向,个别ui要进行缩小适配。
没有两全其美的做法,要不准备2套资源,这样游戏包会比较大。现在一般都准备一套低分辨率的资源,其实在高分辨上看起来也不会太差。当然如果你的游戏是ipad游戏,那就要好好斟酌。