Cocos2d-x的UI树|(1)

2015年03月22日 15:30 0 点赞 0 评论 更新于 2025-11-21 18:09

游戏由各种UI元素构成,每个UI元素的核心属性为位置和样式。本节课将从Cocos2d-x源码角度,详细介绍如何确定一个UI元素的位置。

课程笔记 – UI元素

锚点相关函数

在Cocos2d-x中,Node类提供了一系列与锚点相关的函数,以下是部分关键函数的源码及解释:

// 获取锚点在本地坐标系中的非归一化位置
const Vec2& Node::getAnchorPointInPoints() const
{
return _anchorPointInPoints;
}

// 获取锚点在本地坐标系中的归一化位置
const Vec2& Node::getAnchorPoint() const
{
return _anchorPoint;
}

// 设置锚点在本地坐标系中的归一化位置
void Node::setAnchorPoint(const Vec2& point)
{
#if CC_USE_PHYSICS
if (_physicsBody != nullptr && !point.equals(Vec2::ANCHOR_MIDDLE))
{
CCLOG("Node warning: This node has a physics body, the anchor must be in the middle, you can't change this to other value.");
return;
}
#endif
if (!point.equals(_anchorPoint))
{
_anchorPoint = point;
_anchorPointInPoints = Vec2(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y);
_transformUpdated = _transformDirty = _inverseDirty = true;
}
}

锚点(AnchorPoint)的概念可以理解为将精灵抽象成一个点,这个点位于精灵上。例如,调用setAnchorPoint(0.5, 0.5),意味着将精灵的中心位置作为锚点。当调用setPosition方法设置精灵位置时,实际上是以该锚点所在位置为基准进行放置。若调用setAnchorPoint(0, 0),则将精灵的左下角作为锚点,setPosition设置的就是左下角的位置,精灵也会相应显示。

Node类概述

UI元素通常指spritelabellayerscene等常见元素,它们都继承自Node类。Node类的主要作用是提供一系列通用函数,用于对UI元素进行各种操作,包括但不限于:

  • 设置UI元素的位置
  • 根据坐标系对UI元素进行坐标计算
  • 确定UI元素的深度值
  • 设置UI元素的缩放因子
  • 获取UI元素的尺寸
  • 设置UI元素的可见性、运行状态、事件监听器、动作、调度器、颜色、Camera等
  • 绘制UI元素
  • 对子UI元素进行操作
  • 处理与父UI元素的关系
  • 获取UI元素的scene、碰撞矩阵绘制元素
  • 查询OpenGL ES状态
  • 操作用户数据

位置的确定

UI元素的位置由以下三个因素共同确定:

  1. 确定UI元素的锚点:锚点的作用是在设置UI位置时,将其放置在父UI元素坐标系的某个点上。
  2. 确定UI元素的父UI元素:明确当前UI元素所属的父元素。
  3. 确定锚点在父UI元素中的位置:即把UI元素的锚点放置在父UI元素的具体位置。

当这三个因素确定后,从开发者的角度来看,UI元素的位置基本就确定了。如果父UI、祖父UI(如果存在)等在layer上的位置已经确定,那么UI元素的最终位置也就确定了。

Node类的位置相关函数

  • setAnchorPoint:用于设置Node的锚点在本地坐标系中的位置,传入的参数为归一化坐标。getAnchorPointsetAnchorPoint相对应,用于获取锚点的归一化位置。
  • getAnchorPointInPoints:获取Node的锚点在本地坐标系中的非归一化位置。
  • setPosition:设置Node的锚点在其父UI元素本地坐标系中的位置,传入参数为位置坐标。getPositionsetPosition相对应。
  • setNormalizedPosition:设置Node的锚点在其父UI元素本地坐标系中的归一化位置,传入参数为归一化坐标。getNormalizedPositionsetNormalizedPosition相对应。
  • setPosition3D:除了设置位置的xy值,还会设置_positionZ_globalZOrder_globalZOrder用于排序和为事件分发器提供位置信息。getPosition3DsetPosition3D相对应。
  • ignoreAnchorPointForPosition:这是一个内部函数,仅适用于scenelayer。其作用是在设置scenelayer的位置时,将锚点按照(0, 0)进行设置。其他类使用该函数会报错。

坐标系

Cocos2d-x拥有一个世界坐标系,该坐标系等同于OpenGL ES坐标系。但开发者在实际开发中接触最多的是本地坐标系,每个父UI元素都有自己独立的本地坐标系,子UI元素在设置坐标时,都是相对于其父UI元素的坐标系进行的。

Node类的坐标系转换函数

  • getNodeToParentTransform:获取一个Mat4矩阵,用于将Node本地坐标系中的坐标转换为父UI元素坐标系中的坐标。例如,若Node的锚点为(0.5, 0.5)position设置为(100, 100)contentsize(50, 50),那么在Node本地坐标系中(0, 0)的点,在其父UI元素坐标系中的坐标为(100 - 50 * 0.5, 100 - 50 * 0.5) = (75, 75)setNodeToParentTransformgetNodeToParentTransform相对应。getNodeToParentAffineTransformgetNodeToParentTransform类似,区别在于前者返回的是仿射变换,在有限维情况下,每个仿射变换由一个矩阵A和一个向量b组成。
  • getParentToNodeTransform:获取一个Mat4矩阵,用于将父UI元素坐标系中的坐标转换为Node本地坐标系中的坐标。getParentToNodeAffineTransform返回的是仿射变换。
  • getNodeToWorldTransform:获取一个Mat4矩阵,用于将Node本地坐标系中的坐标转换为世界坐标系中的坐标。getNodeToWorldAffineTransform返回的是仿射变换。
  • getWorldToNodeTransform:获取一个Mat4矩阵,用于将世界坐标系中的坐标转换为Node本地坐标系中的坐标。getWorldToNodeAffineTransform返回的是仿射变换。
  • convertToNodeSpace:借助getWorldToNodeTransform得到的Mat4矩阵,将世界坐标转换为Node本地坐标系中的本地坐标。反之,convertToWorldSpace则借助getNodeToWorldTransform得到的Mat4矩阵,将Node本地坐标系中的本地坐标转换为世界坐标。
  • convertToNodeSpaceAR:将世界坐标转换为以Node锚点为原点的坐标系中的坐标。反之,convertToWorldSpaceAR将以Node锚点为原点的坐标系中的某一点坐标转换为世界坐标。

作者信息

menghao

menghao

共发布了 3994 篇文章