多分辨率适配(下)
五.多分辨率自适应的实现
首先我们要设置我们的适配模式为kResolutionFixedHeight:
1
|
pEGLView->setDesignResolutionSize(960,720,kResolutionFixedHeight);
|
假定我们的游戏为分辨率(960,720)的横版游戏,至于为什么是960×720,最后再告诉大家,这里且让小弟卖个关子!
1.背景层
对于背景层来说这个问题So Easy,我们只用准备一张比设计分辨率长很多(或高很多,取决于你游戏的方向,另一个方向的尺寸和设计尺寸相同!)的图片即可!
这里我们随便找张素材:
大家在hellocpp工程中的HelloWorld::init函数末尾加入如下代码:
1
2
3
|
CCSprite*pSprite=CCSprite::create("background.jpg");
pSprite->setPosition(ccp(visibleSize.width/2+origin.x,visibleSize.height/2+origin.y));
this->addChild(pSprite,0);
|
下图是的main.cpp中设置的窗口大小为标准960×720和其他分辨率下的效果:
哈哈哈,看我们的设计区域是不是都被完整的显示出来了呢?大家可以用(上)文章中提到的分辨率挨个试一遍,都是没有问题的!(Yes,妈妈再也不用担心我的多分辨率适配了!)
2.游戏内容
关于这部分的内容,太多太复杂,真的不好讲啊!我简单讲来一下,要有什么不懂得,请在评论中说明或者@justbilt私信给我,我会在第一时间回复的!我们需要一个节点(CCNode),用来将游戏的所有内容都添加到上面,再将这个节点添加到屏幕的中心! 这个节点可以是CCLayer,CCNode,或者CCTMXTiledMap都行!这里要注意以下几点:
1).选择根节点
如果根节点选择的是CCLayer,CCNode之类的,要去设置它们的setContentSize(designResolutionSize);
1
2
3
4
5
|
CCNode*pGameRoot=CCNode::create();
pGameRoot->setAnchorPoint(ccp(0.5f,0.5f));
pGameRoot->setPosition(ccp(visibleSize.width/2+origin.x,visibleSize.height/2+origin.y));
pGameRoot->setContentSize(designResolutionSize);
addChild(pGameRoot);
|
如果根节点是自身CCTMXTiledMap(注:这里我们地图的内容不要超过设计尺寸),就不用进行上边的操作了!
2).坐标设置
游戏中尽量不要用绝对坐标(其实绝对坐标木任何问题),让我们加入几个精灵试试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//右上角
CCSprite*pHero=CCSprite::create("hero.png");
pHero->setPosition(ccp(pGameRoot->getContentSize().width,pGameRoot->getContentSize().height));
pGameRoot->addChild(pHero);
//左下角
pHero=CCSprite::create("hero.png");
pHero->setPosition(ccp(0,0));
pGameRoot->addChild(pHero);
//右下
pHero=CCSprite::create("hero.png");
pHero->setPosition(ccp(pGameRoot->getContentSize().width,0));
pGameRoot->addChild(pHero);
//左上
pHero=CCSprite::create("hero.png");
pHero->setPosition(ccp(0,pGameRoot->getContentSize().height));
pGameRoot->addChild(pHero);
//中心
pHero=CCSprite::create("hero.png");
pHero->setPosition(ccp(pGameRoot->getContentSize().width/2,pGameRoot->getContentSize().height/2));
pGameRoot->addChild(pHero);
|
让我们看下效果:
游戏中的我们尽量使用相对坐标,可以通过以下几种方式求得:
①.相对于父亲的尺寸比例
②.相对于另一个精灵的坐标的偏移
③.相对于屏幕的尺寸的比例
这样日后修改起来了会很方便!
哈哈哈,大家可以把上段代码中的pGameRoot->getContentSize().width,pGameRoot->getContentSize().height换成960×720的绝对坐标试下,结果是没有任何问题的!
3).介绍几个坐标转换的函数
1
|
CCPoint CCDirector::convertToGL(constCCPoint&obPoint);
|
将UI坐标(左上角为原点)转化为OpenGL(左下角为原点)坐标,CCTouch中的坐标为UI坐标,我们使用时要转换为OpenGL坐标
1
|
CCPoint CCDirector::convertToUI(constCCPoint&obPoint);
|
将OpenGL坐标转化为UI坐标,主要用在设置CCTouch的触点(讲触摸的那篇文章有提到)!
1
2
3
|
CCPoint CCNode::convertToNodeSpace(constCCPoint&worldPoint);
CCPoint CCNode::convertToWorldSpace(constCCPoint&nodePoint);
|
世界坐标空间和Node空间的转化,请看下图:
如图,我们用中间的小人getPosition()得到的是相对与父亲的坐标(即红框),如果我们想得到它相对于原点的坐标,就可以这样:
1
|
CCPoint worldpos=pHero->convertToWorldSpace(pHero->getPosition());
|
如下图:
假如我们在红色圆圈位置点击,想判断落点在哪一格,但是我们从pTouch->getLocation();得到的坐标是相对于原点的,这样我们要减去红框(pGameRoot)的左下角坐标才行,很麻烦的,我们可以这个样子做:
1
2
|
CCPoint touchPoint=pTouch->getLocation();
CCPoint touchInGameRoot=pGameRoot->convertToNodeSpace(touchPoint);
|
哈哈哈,这样子是不是很简单?这样子touchInGameRoot就是以pGameRoot左下角的偏移量了!
游戏内容部分就讲到这里!
3.UI层
UI层的实现相对来说比较简单,目前来说大概有两种实现方式:
①.根据”米”来设设置UI控件的位置.
②.根据屏幕的%来这设置UI控件的位置.
1).让我们直接上代码吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
CCMenuItemImage*pItem=CCMenuItemImage::create("red.png","blue.png");
pItem->setPosition(ccp(visibleSize.width*0.0f,visibleSize.height*0.0f));
CCMenuItemImage*pItem1=CCMenuItemImage::create("red.png","blue.png");
pItem1->setPosition(ccp(visibleSize.width*1.0f,visibleSize.height*0.0f));
CCMenuItemImage*pItem2=CCMenuItemImage::create("red.png","blue.png");
pItem2->setPosition(ccp(visibleSize.width*0.0f,visibleSize.height*1.0f));
CCMenuItemImage*pItem3=CCMenuItemImage::create("red.png","blue.png");
pItem3->setPosition(ccp(visibleSize.width*1.0f,visibleSize.height*1.0f));
CCMenuItemImage*pItem4=CCMenuItemImage::create("red.png","blue.png");
pItem4->setPosition(ccp(visibleSize.width*0.5f,visibleSize.height*0.5f));
CCMenu*pMenu=CCMenu::create(pItem,pItem1,pItem2,pItem3,pItem4,NULL);
pMenu->setPosition(CCPointZero);
this->addChild(pMenu,1);
|
这个是按照比例去设置UI位置的,下面是效果图,大家注意不同分辨率下红色圆饼的位置:
关于如何用”米”子来布局的实现,大家去这里看http://dualface.github.io/blog/2012/08/17/cocos2d-x-2-dot-0-multi-resolution/,这个不是我要讲的重点,毕竟手写坐标的人不会很多,我们主要讲如何在编辑器中实现UI布局的自适应!
2).在cocosbuilder中如何实现自适应
如果你用过cocosbuilder的话,你一定对下图不陌生:
这个是我们设置物体坐标的一个界面,功能介绍我引用K.C的文章中的一段话:
他讲的非常好,我就不赘述了,我们一般情况下只会使用第一个,当时为了适配多分辨率,我们不能这么做了!在这里我们还是有两种做法来实现,一个是相对布局,一个是%比,但是我推荐将两种方案结合起来.
①.相对位置负责四个角落的位置,即:左下,左上,右下.右上!
②.而中间的几个位置就只能交给%,即:上,下,左,右,中!
这里我们要注意几点(都是血淋淋的坑啊):
①.对于CCMenu,CCNode,CCSprite都能够实用上边的两个方法来设置坐标,唯独CCMenuItem不行,只能使用绝对坐标,这点大家一定要注意.那么对于下面的情况该怎么办呢:
我的解决方案是给”每一堆”按钮都添加一个CCMenu,然后CCMenuItem按照相对位置来,上图中我就使用了3个CCMenu!
②.对于要”扎堆”的控件(即控件间的相对位置保持不变),一定要加入到一个公共的父亲上!
③.灵活使用AnchorPoint属性!
六.设计尺寸的设定
之前文章中有提到设置游戏的分辨率为(960,720),那么为什么呢?
首先我们来考虑选择什么样的宽高比,宽高比越小,画面就越方,比如ipad(4:3=1.33)的宽高比就比iphone(3:2=1.5)的小,所以ipad的屏幕更方一些!因此我们设计游戏是应该按照最小的宽高比去设计,这样在大的宽高比的机型上都能够看到完整的画面,从表1中可知宽高比最小的是4:3!
下面我们来考虑分辨率,分辨率要符合大多数设备的要求,经过分析960的宽是最符合要求的,转为4:3就是960×720!.
(全文完)