(原创文章,转载请注明原文出处:http://blog.csdn.net/while0/article/details/79032004)
基于cocos2dx开发游戏,免不了设置节点或精灵的位置,这些位置坐标常常不是一个绝对坐标值,而是相对于其它节点的相对坐标。例如:精灵A与精灵B左对齐,精灵A与精灵B中心对齐等等。
计算这些相对坐标值,每次都需要进行计算,计算时要考虑到精灵的anchorPoint,scale等,比较繁琐,一不留神就搞错了,调试来调试去浪费时间。本文封装了一个很方便的工具类,帮助你计算这些相对坐标。
直接上源码:
GmbsPoint.h (无cpp文件)
#ifndef __GMBSPOINT_H__ #define __GMBSPOINT_H__ #include "cocos2d.h" #include "GmbsGrid.h" NS_CC_BEGIN class GmbsPoint : public Point { public: Node *m_targetNode; GmbsPoint(Node* targetNode = NULL) { m_targetNode = targetNode; if (targetNode) { Point pt = targetNode->getPosition(); x = pt.x; y = pt.y; } } GmbsPoint(Node* targetNode,float xx,float yy) { m_targetNode = targetNode; x = xx; y = yy; } GmbsPoint& reset(Node* targetNode,float xx = 0,float yy = 0) { m_targetNode = targetNode; x = xx; y = yy; return *this; } public: GmbsPoint& leftAlign(Node* baseNode,float leftPadding = 0) { Point baseAnchorPoint(0,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.x -= baseNode->getContentSize().width * baseAnchorPoint.x * getScaleX(baseNode); Point point(basePoint.x + leftPadding,basePoint.y); Point anchorPoint(0,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.x += m_targetNode->getContentSize().width * anchorPoint.x * getScaleX(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); x = point.x; return *this; } GmbsPoint& leftAlign(GmbsGrid& baseGrid,float leftPadding = 0) { return leftAlign(baseGrid.m_ownerNode,leftPadding + baseGrid.origin.x); } GmbsPoint& rightAlign(Node* baseNode,float rightPadding = 0) { Point baseAnchorPoint(0,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.x += baseNode->getContentSize().width * (1 - baseAnchorPoint.x) * getScaleX(baseNode); Point point(basePoint.x - rightPadding,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.x -= m_targetNode->getContentSize().width * (1 - anchorPoint.x) * getScaleX(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); x = point.x; return *this; } GmbsPoint& rightAlign(GmbsGrid& baseGrid,float rightPadding = 0) { Node* baseNode = baseGrid.m_ownerNode; Point baseAnchorPoint(0,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.x += baseGrid.origin.x + baseGrid.size.width - baseNode->getContentSize().width * baseAnchorPoint.x * getScaleX(baseNode); Point point(basePoint.x - rightPadding,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.x -= m_targetNode->getContentSize().width * (1 - anchorPoint.x) * getScaleX(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); x = point.x; return *this; } GmbsPoint& topAlign(Node* baseNode,float topPadding = 0) { Point baseAnchorPoint(0,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.y += baseNode->getContentSize().height * (1 - baseAnchorPoint.y) * getScaleY(baseNode); Point point(basePoint.x,basePoint.y - topPadding); Point anchorPoint(0,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.y -= m_targetNode->getContentSize().height * (1 - anchorPoint.y) * getScaleY(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); y = point.y; return *this; } GmbsPoint& topAlign(GmbsGrid& baseGrid,float topPadding = 0) { Node* baseNode = baseGrid.m_ownerNode; Point baseAnchorPoint(0,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.y += baseGrid.origin.y + baseGrid.size.height - baseNode->getContentSize().height * baseAnchorPoint.y * getScaleY(baseNode); Point point(basePoint.x,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.y -= m_targetNode->getContentSize().height * (1 - anchorPoint.y) * getScaleY(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); y = point.y; return *this; } GmbsPoint& bottomAlign(Node* baseNode,float bottomPadding = 0) { Point baseAnchorPoint(0,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.y -= baseNode->getContentSize().height * baseAnchorPoint.y * getScaleY(baseNode); Point point(basePoint.x,basePoint.y + bottomPadding); Point anchorPoint(0,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.y += m_targetNode->getContentSize().height * anchorPoint.y * getScaleY(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); y = point.y; return *this; } GmbsPoint& bottomAlign(GmbsGrid& baseGrid,float bottomPadding = 0) { return bottomAlign(baseGrid.m_ownerNode,bottomPadding + baseGrid.origin.y); } GmbsPoint& xMiddleAlign(Node* baseNode,float padding = 0) { Point baseAnchorPoint(0,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.x += baseNode->getContentSize().width * (0.5 - baseAnchorPoint.x) * getScaleX(baseNode); Point point(basePoint.x + padding,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.x -= m_targetNode->getContentSize().width * (0.5 - anchorPoint.x) * getScaleX(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); x = point.x; return *this; } GmbsPoint& xMiddleAlign(GmbsGrid& baseGrid,float padding = 0) { Node* baseNode = baseGrid.m_ownerNode; Point baseAnchorPoint(0,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.x += baseGrid.origin.x + baseGrid.size.width/2 - baseNode->getContentSize().width * baseAnchorPoint.x * getScaleX(baseNode); Point point(basePoint.x + padding,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.x -= m_targetNode->getContentSize().width * (0.5 - anchorPoint.x) * getScaleX(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); x = point.x; return *this; } GmbsPoint& yMiddleAlign(Node* baseNode,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.y += baseNode->getContentSize().height * (0.5 - baseAnchorPoint.y) * getScaleY(baseNode); Point point(basePoint.x,basePoint.y + padding); Point anchorPoint(0,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.y -= m_targetNode->getContentSize().height * (0.5 - anchorPoint.y) * getScaleY(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); y = point.y; return *this; } GmbsPoint& yMiddleAlign(GmbsGrid& baseGrid,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.y += baseGrid.origin.y + baseGrid.size.height/2 - baseNode->getContentSize().height * baseAnchorPoint.y * getScaleY(baseNode); Point point(basePoint.x,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.y -= m_targetNode->getContentSize().height * (0.5 - anchorPoint.y) * getScaleY(m_targetNode); point = m_targetNode->getParent()->convertToNodeSpace(point); y = point.y; return *this; } GmbsPoint& rightTo(Node* baseNode,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.x -= baseNode->getContentSize().width * baseAnchorPoint.x * getScaleX(baseNode); Point point(basePoint.x - rightPadding,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.x -= m_targetNode->getContentSize().width * (1 - anchorPoint.x) * getScaleX(m_targetNode);; point = m_targetNode->getParent()->convertToNodeSpace(point); x = point.x; return *this; } GmbsPoint& leftTo(Node* baseNode,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.x += baseNode->getContentSize().width * (1 - baseAnchorPoint.x) * getScaleX(baseNode); Point point(basePoint.x + leftPadding,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.x += m_targetNode->getContentSize().width * anchorPoint.x * getScaleX(m_targetNode);; point = m_targetNode->getParent()->convertToNodeSpace(point); x = point.x; return *this; } GmbsPoint& bottomTo(Node* baseNode,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.y += m_targetNode->getContentSize().height * anchorPoint.y * getScaleY(m_targetNode);; point = m_targetNode->getParent()->convertToNodeSpace(point); y = point.y; return *this; } GmbsPoint& topTo(Node* baseNode,0); Point basePoint = baseNode->getPosition(); Node* baseParent = baseNode->getParent(); if (baseParent != NULL) basePoint = baseParent->convertToWorldSpace(basePoint); if (!baseNode->isIgnoreAnchorPointForPosition()) baseAnchorPoint = baseNode->getAnchorPoint(); basePoint.y -= baseNode->getContentSize().height * baseAnchorPoint.y * getScaleY(baseNode);; Point point(basePoint.x,0); if (!m_targetNode->isIgnoreAnchorPointForPosition()) anchorPoint = m_targetNode->getAnchorPoint(); point.y -= m_targetNode->getContentSize().height * (1 - anchorPoint.y) * getScaleY(m_targetNode);;; point = m_targetNode->getParent()->convertToNodeSpace(point); y = point.y; return *this; } static float getScaleX(Node* node) { float scale = node->getScaleX(); Node* parent = node->getParent(); while (parent != NULL) { scale *= parent->getScaleX(); parent = parent->getParent(); } return scale; } static float getScaleY(Node* node) { float scale = node->getScaleY(); Node* parent = node->getParent(); while (parent != NULL) { scale *= parent->getScaleY(); parent = parent->getParent(); } return scale; } }; NS_CC_END #endifGmbsGrid.h (无cpp文件)
#ifndef __GMBSGRID_H__ #define __GMBSGRID_H__ #include "cocos2d.h" NS_CC_BEGIN class GmbsGrid : public Rect { protected: int m_xNum; int m_yNum; GmbsGrid** m_children; public: Node *m_ownerNode; GmbsGrid(Node* ownerNode,int xNum,int yNum) { m_ownerNode = ownerNode; origin = Point(0,0); size = ownerNode->getContentSize(); m_xNum = xNum; m_yNum = yNum; m_children = (GmbsGrid**)malloc(xNum*yNum*sizeof(GmbsGrid*)); memset(m_children,xNum*yNum*sizeof(GmbsGrid*)); } GmbsGrid(Node* ownerNode,Rect& rect,int yNum) { m_ownerNode = ownerNode; origin = rect.origin; size = rect.size; m_xNum = xNum; m_yNum = yNum; m_children = (GmbsGrid**)malloc(xNum*yNum*sizeof(GmbsGrid*)); memset(m_children,xNum*yNum*sizeof(GmbsGrid*)); } GmbsGrid(Rect& rect,int yNum) { m_ownerNode = NULL; origin = rect.origin; size = rect.size; m_xNum = xNum; m_yNum = yNum; m_children = (GmbsGrid**)malloc(xNum*yNum*sizeof(GmbsGrid*)); memset(m_children,xNum*yNum*sizeof(GmbsGrid*)); } virtual ~GmbsGrid() { release(); } void release() { for (int j = 0; j < m_yNum; j++) { for (int i = 0; i < m_xNum; i++) { if (m_children[j*m_xNum + i] != NULL) { delete m_children[j*m_xNum + i]; m_children[j*m_xNum + i] = NULL; } } } } GmbsGrid& child(int x,int y) { if (m_children[y*m_xNum + x] == NULL) { Rect rect; rect.size.setSize(size.width/m_xNum,size.height/m_yNum); rect.origin.setPoint(origin.x + rect.size.width*x,origin.y + rect.size.height*y); m_children[y*m_xNum + x] = new GmbsGrid(m_ownerNode,rect,1,1); } return *m_children[y*m_xNum + x]; } //counting from up to down GmbsGrid& childUtd(int x,int y) { int yNew = m_yNum - 1 - y; if (m_children[yNew*m_xNum + x] == NULL) { Rect rect; rect.size.setSize(size.width/m_xNum,origin.y + rect.size.height*yNew); m_children[yNew*m_xNum + x] = new GmbsGrid(m_ownerNode,1); } return *m_children[yNew*m_xNum + x]; } void setOwnerNode(Node* ownerNode) { m_ownerNode = ownerNode; } }; NS_CC_END #endif
举例:
1) spriteA与spriteB中心对齐:
GmbsPoint pt(spriteA); pt.xMiddleAlign(spriteB).yMiddleAlign(spriteB); spriteA->setPosition(pt);
2) spriteA与spriteB左对齐且底对齐:
GmbsPoint pt(spriteA); pt.leftAlign(spriteB).bottomAlign(spriteB); spriteA->setPosition(pt);
3) spriteA在spriteB左侧,且相距间隔为10,它们底部对齐:
GmbsPoint pt(spriteA); pt.leftTo(spriteB,10).bottomAlign(spriteB); spriteA->setPosition(pt);