/**
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源碼分析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.