/**
CCPointObject用于记录CCParallaxNode孩子节点的ratio和offset属性
**/
class CCPointObject : CCObject
{
//视差速率
CC_SYNTHESIZE(CCPoint, m_tRatio, Ratio)
//在CCParallaxNode中的偏移量
CC_SYNTHESIZE(CCPoint, m_tOffset, Offset)
CC_SYNTHESIZE(CCNode *,m_pChild, Child) // weak ref
static CCPointObject * pointWithCCPoint(CCPoint ratio, CCPoint offset)
{
CCPointObject *pRet = new CCPointObject();
pRet->initWithCCPoint(ratio, offset);
pRet->autorelease();
return pRet;
}
bool initWithCCPoint(CCPoint ratio, CCPoint offset)
{
m_tRatio = ratio;
m_tOffset = offset;
m_pChild = NULL;
return true;
}
};
//CCParallaxNode构造函数
CCParallaxNode::CCParallaxNode()
{
m_pParallaxArray = ccArrayNew(5);
m_tLastPosition = CCPointMake(-100,-100);
}
CCParallaxNode::~CCParallaxNode()
{
if( m_pParallaxArray )
{
ccArrayFree(m_pParallaxArray);
m_pParallaxArray = NULL;
}
}
CCParallaxNode * CCParallaxNode::node()
{
return CCParallaxNode::create();
}
CCParallaxNode * CCParallaxNode::create()
{
CCParallaxNode *pRet = new CCParallaxNode();
pRet->autorelease();
return pRet;
}
void CCParallaxNode::addChild(CCNode * child, unsigned int zOrder, int tag)
{
CC_UNUSED_PARAM(zOrder);
CC_UNUSED_PARAM(child);
CC_UNUSED_PARAM(tag);
CCAssert(0,"ParallaxNode: use addChild:z:parallaxRatio:positionOffset instead");
}
void CCParallaxNode::addChild(CCNode *child, unsigned int z, const CCPoint& ratio, const CCPoint& offset)
{
CCAssert( child != NULL, "Argument must be non-nil");
//记录属性
CCPointObject *obj = CCPointObject::pointWithCCPoint(ratio, offset);
obj->setChild(child);
//扩容处理
ccArrayAppendObjectWithResize(m_pParallaxArray, (CCObject*)obj);
//当CCParallaxNode的位置不是(0,0)时添加孩子,会发生比较诡异的事情
CCPoint pos = m_tPosition;
pos.x = pos.x * ratio.x + offset.x;
pos.y = pos.y * ratio.y + offset.y;
child->setPosition(pos);
CCNode::addChild(child, z, child->getTag());
}
void CCParallaxNode::removeChild(CCNode* child, bool cleanup)
{
//删除属性
for( unsigned int i=0;i < m_pParallaxArray->num;i++)
{
CCPointObject *point = (CCPointObject*)m_pParallaxArray->arr[i];
if( point->getChild()->isEqual(child))
{
ccArrayRemoveObjectAtIndex(m_pParallaxArray, i, true);
break;
}
}
//删除node
CCNode::removeChild(child, cleanup);
}
void CCParallaxNode::removeAllChildrenWithCleanup(bool cleanup)
{
ccArrayRemoveAllObjects(m_pParallaxArray);
CCNode::removeAllChildrenWithCleanup(cleanup);
}
CCPoint CCParallaxNode::absolutePosition()
{
CCPoint ret = m_tPosition;
CCNode *cn = this;
//层层向上计算,获得绝对坐标,至于为什么需要这样,下面有段注释
while (cn->getParent() != NULL)
{
cn = cn->getParent();
ret = ccpAdd( ret, cn->getPosition());
}
return ret;
}
/*
The positions are updated at visit because:
- using a timer is not guaranteed that it will called after all the positions were updated
- overriding "draw" will only precise if the children have a z > 0
*/
void CCParallaxNode::visit()
{
// CCPoint pos = position_;
// CCPoint pos = [self convertToWorldSpace:CCPointZero];
CCPoint pos = this->absolutePosition(); //获得绝对坐标
if( ! CCPoint::CCPointEqualToPoint(pos, m_tLastPosition) ) //dirty处理
{
//计算所有孩子相对于CCParallaxNode的位置,注意当我们移动CCParallaxNode位置时,表现出来的其实是孩子位置的改变,这种变化是本类的核心设计。
for(unsigned int i=0; i < m_pParallaxArray->num; i++ )
{
//
CCPointObject *point = (CCPointObject*)m_pParallaxArray->arr[i];
//例如CCParallaxNode绝对位置为100,表现出来的是孩子位置为-100,CCParallaxNode的移动我们不能感知,但孩子的位置却发生了变化。
//简单点就是类似于一个摄像头场景的移动,摄像头未动,风景变了
//如果ratio为1,则postion == offset
//如果ratio为(0,1),则position < offset,移动速度慢
//如果ratio为(1,xx),则postion > offset,移动速度快
float x = -pos.x + pos.x * point->getRatio().x + point->getOffset().x;
//同x
float y = -pos.y + pos.y * point->getRatio().y + point->getOffset().y;
//孩子的位置是通过上面两行计算出来的,因此手动设置其postion不会有任何作用
point->getChild()->setPosition(ccp(x,y));
}
//更新上一个位置
m_tLastPosition = pos;
}
CCNode::visit();
}
cocos2d-x庖丁解牛(1):CCParallaxNode源码分析
最新推荐文章于 2018-10-15 23:53:32 发布