总结cocos2d-x屏幕适配
在阅读了两篇转载文章并在 hellocpp 中进行实验后,我对 cocos2d-x 的屏幕适配进行了总结。屏幕适配主要分为两大类,下面将分别介绍竖版游戏和横版游戏的适配方法。
竖版游戏
1. 初始化设置
首先需要设置解释器的大小,正常情况下,解释器的大小应与设计分辨率的大小一致。示例代码如下:
eglView.init("HelloCpp", 640, 960);
eglView.setFrameSize(640, 960);
这里设计分辨率为 640 * 960。
2. 分辨率策略
采用 kResolutionFixedWidth 策略,该策略会保持传入的设计分辨率宽度不变,根据屏幕分辨率修正设计分辨率的高度。示例代码如下:
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(640, 960, kResolutionFixedWidth);
3. 屏幕缩放因子
屏幕缩放因子的计算公式为 setContentScaleFactor(最大资源宽度 / 设计分辨率宽度)。示例代码如下:
Director::getInstance()->setContentScaleFactor(largeResource.size.width / designResolutionSize.width);
若要让图片在宽度上全显示在屏幕上,高度按宽度的比例等比缩放,可使用以下代码:
Director::getInstance()->setContentScaleFactor(640 / designResolutionSize.width);
4. 精灵位置设置
精灵的位置应该是相对位置,可采用百分比形式设置。示例代码如下:
sprite->setPosition(Point(Screen.width * sprite.x / ResolutionSize.width, Screen.height * sprite.y / ResolutionSize.height));
此外,还有一种相对于一个固定控件的方法,目前待研究。
5. 测试相关注意事项
游戏底图的高度需要按照分辨率最大的设置高度一致。目前最大的一款大概是 480 * 854,长宽比为 1.779,设计宽度为 640,算出来最大高度大概是 1138.666,所以底图的最大高度就是 1138.666。
开始时尝试过不改变画布大小的方法,即按照 640 * 960 来设置,然后将底图换成较大的,再设置 layout(层容器的 setSize),但设置时它只在向上的方向上缩放,导致整体图像不能居中,出现问题。有人说通过设置锚点来解决,这是不可行的,因为锚点是贴图中调整位置的点,对于像 layer 这样的东西设置锚点是没有用的。
6. 在 cocostudio 界面下的实现方法
注意事项
Panel是画布也就是层容器,这里要设置画布大小为 640 * 1139(保持宽度,高度会跟着宽度来等比缩放)。ImageView也就是图片控件大小同画布大小(640 * 1139),这就是底图,有底图就设置底图,没有就弄成透明的背景,所有的控件都要建在这个控件上,因为在图片控件建立的控件,原点是该图片的中心点,x 轴向右,y 轴向上。cityback底板:底板上不能建立控件,因为后续要对底板进行拉伸,如果底板上有子节点,子节点也会拉伸,图标拉伸后会出现问题。- 其他的图标建在
ImageView上,可按照 640 * 960 的效果图添加控件(1139 - 960 / 2,上下都要留出这样的大小,也就是居中)。如果是一块不想改变的控件区,就弄一个层容器来处理,调整位置时调整层容器,里面的东西无需调整。
载入文件
载入 cocostudio 的 .ExportJson 或 json 文件。.ExportJson 导出的是大图,即资源拼合成一张图,然后通过 *.plist 定位到了大图的位置,通过 Rect 来取出相应的图片,可提升渲染速度;json 是小图,没有拼合的。cocostudio 导入模板时,选择 json。
640 * 960 下的布局居中显示
local VisibleSize = CCDirector:sharedDirector():getVisibleSize()
local layoutw, layouth = layout:getContentSize()
local VisibleOriginPoint = CCDirector:sharedDirector():getVisibleOrigin()
layout:setPosition(VisibleOriginPoint.x / 2, VisibleOriginPoint.y / 2 + VisibleSize.height / 2 - layouth / 2)
-- VisibleOriginPoint 当前屏幕的原点坐标,这种分辨策略是 0
这样在 640 * 960 下就没有任何问题了。
480 * 854 下的效果及调整
在 480 854 下查看效果,鉴于这个高宽比,会显示出 640 1139 的大小(也就是上下都有一截黑边,然后图标全都在中间)。接下来需要调整位置和缩放一些底板,以保证图标等没有问题,只拉伸底板。
调整位置原理
在高度上乘以一个大于 1 的比例,比如 1.2,坐标(100, 100)会变为(100, 120),坐标(100, -100)会变为(100, -120),都是向两边进行放大;在高度上乘以一个小于 1 的比例,比如 0.8,坐标(100, 100)会变为(100, 80),坐标(100, -100)会变为(100, -80),都向中间进行缩进,从而实现所有东西的居中对齐。
调整位置函数(只调整高度,因为宽度被保持)
function adjustPosition(layout, nameTabel)
local VisibleSize = CCDirector:sharedDirector():getVisibleSize()
local DesignResolutionSize = CCEGLView:sharedOpenGLView():getDesignResolutionSize()
local scaley = VisibleSize.height / 960
for k, v in pairs(nameTabel) do
local widget = layout:getChildByName(v)
widget:setTouchEnabled(true)
local widgetx, widgety = widget:getPosition()
widget:setPosition(widgetx, widgety * scaley)
CCLuaLog("widgetx, widgety*scaley = " .. widgetx .. " " .. widgety * scaley)
end
end
缩放底板函数
function adjustBackScaleY(layout, nameTabel)
local VisibleSize = CCDirector:sharedDirector():getVisibleSize()
local DesignResolutionSize = CCEGLView:sharedOpenGLView():getDesignResolutionSize()
local scaley = VisibleSize.height / 960
for k, v in pairs(nameTabel) do
local widget = layout:getChildByName(v)
widget:setTouchEnabled(true)
widget:setScaleY(scaley)
-- local widgetx, widgety = widget:getPosition()
-- widget:setPosition(widgetx, widgety*scaley)
-- CCLuaLog("widgetx, widgety*scaley = " .. widgetx .. " " .. widgety*scaley)
end
end
同一行上的可以用一个层容器包含起来,调整位置时,只需要调整这个层容器即可,不过也可以逐个调整。
如果不想改变在 960 640 的图标的间隔,可以建一个 640 960 大小的层容器,把除了底板和需要向下对齐的东西放在里面。因为层容器建在图片上,层容器的调整方向与预期不符,所以函数需要做如下调整:
function adjustLayoutPosition(layout, nameTabel)
local VisibleSize = CCDirector:sharedDirector():getVisibleSize()
local DesignResolutionSize = CCEGLView:sharedOpenGLView():getDesignResolutionSize()
local scaley = VisibleSize.height / 960
for k, v in pairs(nameTabel) do
local widget = layout:getChildByName(v)
widget:setTouchEnabled(true)
local widgetx, widgety = widget:getPosition()
widget:setPosition(widgetx, widgety / scaley)
CCLuaLog("widgetx, widgety*scaley = " .. widgetx .. " " .. widgety / scaley)
end
end
最后在 480 * 854 下可得到相应的适配效果。不过,这种方法比较复杂,效果也不太理想。
横版游戏
1. 分辨率策略
采用 kResolutionFixedHeight 策略,该策略会保持传入的设计分辨率高度不变,根据屏幕分辨率修正设计分辨率的宽度。示例代码如下:
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(640, 960, kResolutionFixedHeight);
2. 屏幕缩放因子
屏幕缩放因子的计算公式为 setContentScaleFactor(最大资源高度 / 设计分辨率高度)。示例代码如下:
Director::getInstance()->setContentScaleFactor(largeResource.size.height / designResolutionSize.height);
若要让图片在高度上全显示在屏幕上,宽度按高度的比例等比缩放,可使用以下代码:
Director::getInstance()->setContentScaleFactor(960 / designResolutionSize.height);
3. 精灵位置设置
精灵的位置应该是相对位置,可采用百分比形式设置。示例代码如下:
sprite->setPosition(Point(Screen.width * sprite.x / ResolutionSize.width, Screen.height * sprite.y / ResolutionSize.height));
综上所述,以上就是 cocos2d-x 中竖版游戏和横版游戏的屏幕适配方法,不同的方法适用于不同的场景,开发者可根据实际需求进行选择和调整。