cocos2d-x庖丁解牛(1):CCParallaxNode源码分析

26 篇文章 0 订阅
15 篇文章 0 订阅

/**
 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();
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值