CCFollow dont Follow

Hi,

Im using the HelloCpp for my example and i have added box2d to it and now i want put the CCFollow to work, but when i move my sprite attached in CCFollow, nothing happen.

My code:

## HelloWorldScene.cpp

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();

    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

bool HelloWorld::init()
{
    CCLOG("INIT GAME");

    if ( !CCLayer::init() )
    {
        return false;
    }

    setTouchEnabled(true);    

    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    createBox2DWorld();

    CCSprite *backgroundSprite = CCSprite::create("backgroundGame.png");
    backgroundSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    addChild(backgroundSprite, 0);

    /*
    char1Sprite = CCSprite::create("character1.png");
    char1Sprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    addChild(char1Sprite);

    int num = 3;
    b2Vec2 verts[] = {
        b2Vec2(60.0f / PTM_RATIO, 0.0f / PTM_RATIO),
        b2Vec2(32.0f / PTM_RATIO, 75.0f / PTM_RATIO),
        b2Vec2(0.0f / PTM_RATIO, 0.0f / PTM_RATIO)
    };

    createBox2DBodyForSprite(char1Sprite, num, verts); 
    */

    for(int x = 1; x <= 7; x++)
    {   
        std::string textureName = "character" + Util::intToString(x) + ".png";
        CCSprite *charTexture = CCSprite::create(textureName.c_str());
        CCSize charSize = charTexture->getContentSize();

        PhysicsSprite *charPhysicsSprite = new PhysicsSprite();
        charPhysicsSprite->initWithTexture(charTexture->getTexture(), CCRectMake(0, 0, charSize.width, charSize.height));

        CCPoint p = ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y);

        // Define the dynamic body.
        //Set up a 1m squared box in the physics world
        b2BodyDef bodyDef;
        bodyDef.type = b2_dynamicBody;
        bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);

        b2Body *body = world->CreateBody(&bodyDef);

        b2PolygonShape dynamicBox;
        dynamicBox.SetAsBox(charSize.width/PTM_RATIO/2, charSize.height/PTM_RATIO/2);

        // Define the dynamic body fixture.
        b2FixtureDef fixtureDef;
        fixtureDef.shape = &dynamicBox;    
        fixtureDef.density = 0.5f;
        fixtureDef.friction = 0.3f;
        body->CreateFixture(&fixtureDef);

        charPhysicsSprite->setPhysicsBody(body);

        char1Sprite = charPhysicsSprite;

        addChild(charPhysicsSprite);
    }

    scheduleUpdate();
    schedule( schedule_selector(HelloWorld::updateCamera), 1.0f );

    return true;
}

void HelloWorld::updateCamera(float dt)
{
    CCLOG("UPDATE CAMERA");
    this->stopAllActions();
    //CCFollow* pFollowA = CCFollow::create(char1Sprite, CCRect::CCRect(0.0f, 0.0f, this->getContentSize().width, this->getContentSize().height));

    CCFollow* pFollowA = CCFollow::create(char1Sprite, CCRect::CCRect(0.0f, 0.0f, CCDirector::sharedDirector()->getWinSizeInPixels().width, CCDirector::sharedDirector()->getWinSizeInPixels().height));

    //int w = CCDirector::sharedDirector()->getWinSizeInPixels().width;
    //int h = CCDirector::sharedDirector()->getWinSizeInPixels().height;

    //CCFollow* pFollowA = CCFollow::create(char1Sprite, CCRect::CCRect(0.0f,0.0f, 1000, 1000));
    this->runAction(pFollowA);
}

The box2d objects is moving, but the camera is in the same place and the object go out from screen.

Can anyone help me?

in your update method, if you update the sprite with the body , in the position of the sprite will be update every frame.
so u don’t need to use schedule( schedule_selector(HelloWorld::updateCamera), 1.0f );
you can use scheduleOnce( schedule_selector(HelloWorld::updateCamera), 1.0f ); or initialize the CCFollow once in init().
finally , the CCRect in the CCFollow must be change, the range of the CCRect must bu large than the screen size.

Hi

But the CCRect is 1000x1000px, no? Its not correct? My iPhone 3GS is 480x320px.

I think that this part is OK, no?

I think that it is a bug.

My code:

#include "HelloWorldScene.h"

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();

    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer, 1);

    // return the scene
    return scene;
}

bool HelloWorld::init()
{
    CCLOG("INIT GAME");

    if ( !CCLayer::init() )
    {
        return false;
    }

    setTouchEnabled(true);

    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    createBox2DWorld();

    layerBackground = CCLayer::create();
    CCSprite *backgroundSprite = CCSprite::create("backgroundGame.png");
    backgroundSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    layerBackground->addChild(backgroundSprite, 0);
    addChild(layerBackground, 0);

    /*
    char1Sprite = CCSprite::create("character1.png");
    char1Sprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    addChild(char1Sprite);

    int num = 3;
    b2Vec2 verts[] = {
        b2Vec2(60.0f / PTM_RATIO, 0.0f / PTM_RATIO),
        b2Vec2(32.0f / PTM_RATIO, 75.0f / PTM_RATIO),
        b2Vec2(0.0f / PTM_RATIO, 0.0f / PTM_RATIO)
    };

    createBox2DBodyForSprite(char1Sprite, num, verts); 
    */

    for(int x = 1; x <= 7; x++)
    {   
        //std::string textureName = "character" + Util::intToString(x) + ".png";
        std::string textureName = "object" + Util::intToString(x) + ".png";
        CCSprite *charTexture = CCSprite::create(textureName.c_str());
        CCSize charSize = charTexture->getContentSize();

        PhysicsSprite *charPhysicsSprite = new PhysicsSprite();
        charPhysicsSprite->initWithTexture(charTexture->getTexture(), CCRectMake(0, 0, charSize.width, charSize.height));

        CCPoint p = ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y);

        // Define the dynamic body.
        //Set up a 1m squared box in the physics world
        b2BodyDef bodyDef;
        bodyDef.type = b2_dynamicBody;
        bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);

        b2Body *body = world->CreateBody(&bodyDef);

        b2PolygonShape dynamicBox;
        dynamicBox.SetAsBox(charSize.width/PTM_RATIO/2, charSize.height/PTM_RATIO/2);

        // Define the dynamic body fixture.
        b2FixtureDef fixtureDef;
        fixtureDef.shape = &dynamicBox;    
        fixtureDef.density = 0.5f;
        fixtureDef.friction = 0.2f;
        body->CreateFixture(&fixtureDef);

        charPhysicsSprite->setPhysicsBody(body);

        addChild(charPhysicsSprite);
    }

    addCheckPoints();
    createObjects();
    scheduleUpdate();

    return true;
}

void HelloWorld::createObjects()
{
    // selected and camera object
    //selectedObject = new PhysicsSprite();
    cameraObject   = new PhysicsSprite();

    CCFollow* actionFollow = CCFollow::create(selectedObject, CCRect::CCRect(0.0f, 0.0f, 20000.0f, 20000.0f));
    runAction(actionFollow);
}

void HelloWorld::addCheckPoints()
{
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    std::string textureName = "checkpoint1.png";
    CCSprite *charTexture = CCSprite::create(textureName.c_str());
    CCSize charSize = charTexture->getContentSize();

    selectedObject = new PhysicsSprite();
    selectedObject->initWithTexture(charTexture->getTexture(), CCRectMake(0, 0, charSize.width, charSize.height));

    CCPoint p = ccp(240, 180);

    // Define the dynamic body.
    //Set up a 1m squared box in the physics world
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);

    b2Body *body = world->CreateBody(&bodyDef);

    b2PolygonShape dynamicBox;
    dynamicBox.SetAsBox(charSize.width/PTM_RATIO/2, charSize.height/PTM_RATIO/2);

    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicBox;
    fixtureDef.density = 0.5f;
    fixtureDef.friction = 0.2f;
    body->CreateFixture(&fixtureDef);

    selectedObject->setPhysicsBody(body);

    addChild(selectedObject);
}

void HelloWorld::createBox2DWorld()
{
    // create world
    b2Vec2 gravity;
    gravity.Set(0.0f, -10.0f);
    world = new b2World(gravity);
    world->SetAllowSleeping(true);
    world->SetContinuousPhysics(true);    

    // m_debugDraw = new GLESDebugDraw( PTM_RATIO );
    // world->SetDebugDraw(m_debugDraw);

    uint32 flags = 0;
    flags += b2Draw::e_shapeBit;
    //        flags += b2Draw::e_jointBit;
    //        flags += b2Draw::e_aabbBit;
    //        flags += b2Draw::e_pairBit;
    //        flags += b2Draw::e_centerOfMassBit;
    //m_debugDraw->SetFlags(flags);


    // Define the ground body.
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(0, 0); // bottom-left corner

    // Call the body factory which allocates memory for the ground body
    // from a pool and creates the ground box shape (also from a pool).
    // The body is also added to the world.
    b2Body* groundBody = world->CreateBody(&groundBodyDef);

    // Define the ground box shape.
    b2EdgeShape groundBox;

    // bottom
    groundBox.Set(b2Vec2(VisibleRect::leftBottom().x/PTM_RATIO,VisibleRect::leftBottom().y/PTM_RATIO), b2Vec2(VisibleRect::rightBottom().x/PTM_RATIO,VisibleRect::rightBottom().y/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);

    /*
    // top
    groundBox.Set(b2Vec2(VisibleRect::leftTop().x/PTM_RATIO,VisibleRect::leftTop().y/PTM_RATIO), b2Vec2(VisibleRect::rightTop().x/PTM_RATIO,VisibleRect::rightTop().y/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);

    // left
    groundBox.Set(b2Vec2(VisibleRect::leftTop().x/PTM_RATIO,VisibleRect::leftTop().y/PTM_RATIO), b2Vec2(VisibleRect::leftBottom().x/PTM_RATIO,VisibleRect::leftBottom().y/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);

    // right
    groundBox.Set(b2Vec2(VisibleRect::rightBottom().x/PTM_RATIO,VisibleRect::rightBottom().y/PTM_RATIO), b2Vec2(VisibleRect::rightTop().x/PTM_RATIO,VisibleRect::rightTop().y/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);
    */

    // create contact listener
    contactListener = new ContactListener();
    world->SetContactListener(contactListener);   
}


void HelloWorld::updateBox2DWorld(float dt)
{
    CCLOG("BODY2D COUNT: %i", world->GetBodyCount());

    int velocityIterations = 8;
    int positionIterations = 1;
    world->Step(dt, velocityIterations, positionIterations);

    for(b2Body *b = world->GetBodyList(); b; b=b->GetNext()) 
    {
        if (b->GetUserData() != NULL) 
        {   
            CCSprite *entity = (CCSprite*)b->GetUserData();

            CCPoint Pos = entity->getPosition();
            b2Vec2 b2Position = b2Vec2(Pos.x/PTM_RATIO, Pos.y/PTM_RATIO);
            float32 b2Angle = -1 * CC_DEGREES_TO_RADIANS(entity->getRotation());

            b->SetTransform(b2Position, b2Angle);
        }
    }

    std::vectortoDestroy; 
    std::vector::iterator pos;
    for(pos = contactListener->_contacts.begin(); pos != contactListener->_contacts.end(); ++pos) 
    {
        ContactData contact = *pos;

        // Get the box2d bodies for each object
        b2Body *bodyA = contact.fixtureA->GetBody();
        b2Body *bodyB = contact.fixtureB->GetBody();

        if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) 
        {
            //CCSprite *spriteA = (CCSprite*)bodyA->GetUserData();
            //CCSprite *spriteB = (CCSprite*)bodyB->GetUserData();

            //int iTagA = spriteA->getTag();
            //int iTagB = spriteB->getTag();

            // Is sprite A a cat and sprite B a car?  If so, push the cat on a list to be destroyed...
            /*
            if (iTagA == 1 && iTagB == 2)
                toDestroy.push_back(bodyA);
            // Is sprite A a car and sprite B a cat?  If so, push the cat on a list to be destroyed...
            else if (iTagA == 2 && iTagB == 1) 
                toDestroy.push_back(bodyB);


            or


            if (iTagA == GameObjects::TAG_PLAYER && iTagB == GameObjects::TAG_COIN)
            {
                Coin *coin = (Coin*)spriteB;
                GameObjects::points += coin->getPoints();
                updatePoints();

                toDestroy.push_back(bodyB);
            }    
            */
        }        
    }

    // Loop through all of the box2d bodies we wnat to destroy...
    std::vector::iterator pos2;
    for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) 
    {
        b2Body *body = *pos2;     

        // See if there's any user data attached to the Box2D body
        // There should be, since we set it in addBoxBodyForSprite
        if (body->GetUserData() != NULL) 
        {

            // We know that the user data is a sprite since we set
            // it that way, so cast it...
            CCSprite *entity = (CCSprite*)body->GetUserData();
            removeChild(entity, true);

            // Remove the sprite from the scene
            //[_spriteSheet removeChild:sprite cleanup:YES];
            //sprite->removeFromParentAndCleanup(true);
            //m_spriteSheet->removeChild( sprite, true );
        }

        // Destroy the Box2D body as well
        world->DestroyBody(body);
    }

    // If we've destroyed anything, play an amusing and malicious sound effect!  ;]
    if (toDestroy.size() > 0) 
    {
        //CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect( "cat_ouch.wav" );
    } 
}

void HelloWorld::createBox2DBodyForSprite(CCSprite *entity, int iNumVerts, b2Vec2 verts[])
{ 
    if(world==NULL)
    {
        return;
    }

    CCPoint pos = entity->getPosition();
    CCSize size = entity->getContentSize();

    b2BodyDef spriteBodyDef;
    spriteBodyDef.type = b2_dynamicBody;
    spriteBodyDef.position.Set(pos.x/PTM_RATIO, pos.y/PTM_RATIO);
    spriteBodyDef.userData = entity;
    b2Body *spriteBody = world->CreateBody(&spriteBodyDef);

    b2PolygonShape spriteShape;

    if( iNumVerts!=0 )
    {
        spriteShape.Set(verts, iNumVerts);
        b2FixtureDef spriteShapeDef;
        spriteShapeDef.shape = &spriteShape;
        spriteShapeDef.density = 10.0;
        spriteShapeDef.isSensor = false;

        spriteBody->CreateFixture(&spriteShapeDef);
    }
    else
    {
        // No Vertice supplied so just make a box round the sprite
        b2BodyDef spriteBodyDef;
        spriteBodyDef.type = b2_dynamicBody;
        spriteBodyDef.position.Set( pos.x/PTM_RATIO, pos.y/PTM_RATIO );
        spriteBodyDef.userData = entity;
        b2Body *spriteBody = world->CreateBody( &spriteBodyDef );

        b2PolygonShape spriteShape;
        spriteShape.SetAsBox( size.width/PTM_RATIO/2, size.height/PTM_RATIO/2 );
        b2FixtureDef spriteShapeDef;
        spriteShapeDef.shape = &spriteShape;
        spriteShapeDef.density = 10.0;
        spriteShapeDef.isSensor = true; // isSensor true when you want to know when objects will collide without triggering a box2d collision response
        spriteBody->CreateFixture( &spriteShapeDef );
    }
}

void HelloWorld::update(float dt)
{
    CCLOG("UPDATE GAME");

    updateBox2DWorld(dt);
    updateCamera(dt);    
}

void HelloWorld::updateCamera(float dt)
{
    CCLOG("UPDATE CAMERA");

    if (selectedObject)
    {
        //cameraObject->setPosition(selectedObject->getBodyPosition());
        selectedObject->setPosition(selectedObject->getBodyPosition());        
    }

    /*
    CCFollow* actionFollow = CCFollow::create(selectedObject, CCRect::CCRect(0.0f, 0.0f, 20000.0f, 20000.0f));
    runAction(actionFollow);
    */

    /*
    stopAllActions();

    CCPoint position = CCPoint(selectedObject->getPhysicsBody()->GetPosition().x * PTM_RATIO, selectedObject->getPhysicsBody()->GetPosition().y * PTM_RATIO);

    CCNode *node = CCNode::create();
    node->setPosition(position);

    CCFollow* pFollowA = CCFollow::create(node, CCRect::CCRect(0.0f, 0.0f, 2000, CCDirector::sharedDirector()->getWinSizeInPixels().height));
    runAction(pFollowA);
    */
    /*

     // Bullet is moving.
     if (m_bulletBody && m_bulletJoint == NULL)
     {
     b2Vec2 position = m_bulletBody->GetPosition();
     CCPoint myPosition = this->getPosition();
     CCSize screenSize = CCDirector::sharedDirector()->getWinSize();

     // Move the camera.
     if (position.x > screenSize.width / 2.0f / PTM_RATIO)
     {
     myPosition.x = -MIN(screenSize.width * 2.0f - screenSize.width, position.x * PTM_RATIO - screenSize.width / 2.0f);
     this->setPosition(myPosition);

     */

    //b2Vec2 myPositionB = char1Sprite->getPhysicsBody()->GetPosition();
    //CCPoint myPosition = CCPoint(myPositionB.x * PTM_RATIO, myPositionB.y * PTM_RATIO);
    //setPosition(myPosition);
}

The camera doesnt follow the “selectedObject” :frowning:

Has you tried some sample code in your HelloWorld ??
Such as
@

CCSprite *hero = CCSprite::create(“CloseNormal.png”);
hero~~>setPosition;
addChild;
hero~~>runAction(
CCSequence::create(
CCMoveTo::create(1.0f, ccp(480*2, 320*2))
, CCMoveTo::create(1.0f, CCPointZero)
, NULL
) // sequence
);
CCRect rect;
rect.origin = CCPointZero;
rect.size = CCSizeMake(480*2, 320*2);
runAction(CCFollow::create(hero, rect));

@

void HelloWorld::createObjects()
{
    // selected and camera object
    //selectedObject = new PhysicsSprite();  <------------------------>
    cameraObject   = new PhysicsSprite();



    CCFollow* actionFollow = CCFollow::create(selectedObject /* selectedObject has not INIT */
                                             , CCRect::CCRect(0.0f, 0.0f, 20000.0f, 20000.0f));
    runAction(actionFollow);
}

It is initialize on method “addCheckPoints”, because this, it is comment on “createObjects”, it is already created.

The problem is that CCFollow dont follow the object and PhysicSprite doesnt update the sprite X/Y, becuase this, i have the code on update that update the X/Y of PhysicSprite, but with this, it doenst work too.