Cocos2dx学习笔记(3)——锚点

新的知识到来了,什么是锚点呢?灵魂画师先哥哥登场<( ̄︶ ̄)>

本文仅供个人记录和复习,不用于其他用途

什么是锚点

当我们插入一张图片时,我们需要调整它的位置。假如一张空白的画布是背景,那么当我们插入一张图片时,我们如何确定图片的位置呢?图片可以看做一个精灵,也就是一个节点。那么对于一个节点的位置很好判断,那就是以背景画布建立坐标系。一般来说,父节点的坐标原点默认为(0, 0),也就是说,对于一个960*640的游戏窗口,左下角为(0, 0),右上角为(960, 640)。如果要将图片(也就是子节点)插入到画布上,那么就是设定坐标为(480, 320)。

但问题是,我们只能确保代表图片元素的这个节点是位于最中间的,我们并不能确保整张图片看起来是位于画布最中间,因为图片本身也有大小。那么这里就涉及到一个问题,图片的哪一个点代表整张图片的位置?这个点呢,也被称作锚点。

示例图

如上图所示,空白代表着背景画布,我们插入的图片是一个蓝色的矩形。如果我们想让矩形看起来位于背景画布的中央,那么我们就应该将锚点设置为矩形的最中央。那么这样一来,只要锚点位于背景中央,自然就代表了矩形位于背景中央。再者,如果将锚点设为矩形左下角,那么当我们设置图片位置为(480, 320)时,矩形其实并没有像我们所想的那样位于画布中间,而是矩形左下角位于(480, 320)这个位置,这样看起来矩形就处于画布的右上部分。值得一提的是,锚点的范围是从(0, 0)到(1, 1),同时默认锚点值为(0.5, 0.5)。另外,层的锚点默认忽略,各节点的默认位置为(0, 0)。

具体代码

1
2
3
4
5
6
7
8
9
10
class T01LayerAnchorPoint: public CCLayer
{
public:
static T01LayerAnchorPoint *create();
bool init();
static CCScene *scene();
CCSprite *spr;
};

最基本的类的构架,这里的static T01LayerAnchorPoint *create()可以直接用CREATE_FUNC(T01LayerAnchorPoint)代替。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
T01LayerAnchorPoint *T01LayerAnchorPoint::create()
{
T01LayerAnchorPoint *pRet = new T01LayerAnchorPoint();
if (pRet && pRet->init())
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = nullptr;
}
return pRet;
}

CREATE_FUNC(T01LayerAnchorPoint)大致就是上面这样,用于类的初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool T01LayerAnchorPoint::init()
{
if (!CCLayer::init())
{
return false;
}
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
spr = CCSprite::create("anchor3.png");
// 设置锚点,范围为0-1,为比例
spr->setAnchorPoint(ccp(0, 0));
// 忽略锚点,true将锚点设置为(0, 0),false为不忽略锚点
spr->ignoreAnchorPointForPosition(false);
// 以锚点为中心缩放,2倍
spr->setScale(2.0f);
spr->setPosition(ccp(winSize.width / 2, winSize.height / 2));
addChild(spr);
return true;
}

至于这里的init()方法就要涉及到锚点的设置以及一些位置的调整。winSizespr不用多说,至于setAnchorPoint()方法便是用于设定锚点,与setPostion()一样要传入ccp()。其他的注释已经很清楚,不再多说。

1
2
3
4
5
6
7
8
9
10
11
12
CCScene *T01LayerAnchorPoint::scene()
{
CCScene *scene = CCScene::create();
T01LayerAnchorPoint *layer = T01LayerAnchorPoint::create();
// 层的锚点默认为忽略,这里设置为不忽略
layer->ignoreAnchorPointForPosition(false);
scene->addChild(layer);
return scene;
}

至于scene()方法,没有什么很特别的地方。ignoreAnchorPointForPosition()方法是用来忽略锚点的,如果传入参数true,那么也就是将层的锚点设置为(0, 0)。

事实上,仔细分析上述代码,我们建立了一个场景、一个层、一个精灵。我们将精灵。对于层来说,我们一般忽略它的锚点,也就是将层的锚点设置为左下角,让它和场景重合。至于精灵,一般来讲都是不忽略的,默认为(0.5, 0.5),方便我们调整精灵在层中的位置。我们将精灵的锚点设置为左下角(1, 1),位置设置为正中央。如果层的锚点忽略,那么我们看到的精灵应该是位于正中央的。由于我们不忽略层的锚点,那么层的锚点将是默认的(0.5, 0.5)。这样一来,我们应该会看到下图所示的样子。

示例图

当然,场景和层中我们并没有插入图片之类的东西,所以看到的应该是一片黑色。唯一看到的就是位于左下角的精灵了。其实很好理解,场景默认忽略锚点,所以锚点为(0, 0),位置也是(0, 0)。至于层则被我们设置成了不忽略锚点,因此层的锚点为(0.5, 0.5)。由于锚点的位置位于(0, 0),那么层的中央就相应的移动到了(0, 0)的位置,不再是与场景重合。至于精灵我们就可以根据场景与层的关系来判断。抛开场景,精灵的锚点为左下角(0, 0),位置为层的正中央。因此,看起来就是处在窗口的左下角,但实际上是处在层的右上部。

这里写图片描述

如果不是很清楚,看看上图就应该明白了。场景的大小就是窗口的大小,也就是红线所圈出的范围。超出窗口的部分我们都是看不到的。虽然我们将精灵左下角设置为锚点,并且位置设置成窗口的中央。如果层的锚点没变,那么一切都如我们所想。不过,位置是相对的。我们对于一个节点的位置讨论,都是相对与它的参考物,也就是父节点来讨论的。只要按照一层层的顺序来理解,那么很容易便能判断对象相对应的位置。

锚点与缩放

缩放是根据锚点的位置来的。例如,锚点的位置位于中心,那么物体便从中心向四周开始延展。如果位于左下角,那么便从左下角开始向着x轴正向和y轴正向延展。总而言之,就是锚点的位置不变,物体根据锚点的位置进行拉伸。