Weird physics behaviour on animated body

Weird physics behaviour on animated body
0

#1

Hello,
I’ve stucked on a problem with physics ( I don’t know which one engine I use since I use standart functions ).
I’ve shortened the code only to specific lines since everything else is automated creation.

When I comment line that’ve marked - everything is fine.

THE PROBLEM IS: I’ve created edgebox on screen and two bodies, one with animation and one without it.
Animated one starts flying offscreen by itself, when I disable gravity - it collides very strangely with object.
Second body behaviours like in tests, it’s just bounces off and stops.
What am I doing wrong? How do I get proper physic body on an animated sprite. Second one (maskBlock) works perfectly fine.

Scene* HelloWorld::createScene()
{
    auto scene = Scene::createWithPhysics();
    auto layer = create();
    layer->setPhysicsWorld(scene->getPhysicsWorld());

    scene->addChild(layer);

    return scene;
}

bool HelloWorld::init()
{
    Sprite* sprite = Sprite::create("maskPlayer.png");


    idle = Animate::create(AnimationCache::getInstance()->getAnimation("Idle")); // animation is loaded fine, tested it before physics
    idle->setDuration(0.80f);
    idle->retain(); // also why do I need retain it? It crashes without retain.

    currAction = sprite->runAction(RepeatForever::create(idle)); <- WHEN I COMMENT THIS LINE EVERYTHING IS FINE
    currState = Idle;

auto physBody = PhysicsBody::createBox(Size(32.0f, 32.0f));
sprite->setPhysicsBody(physBody);
sprite->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height - 200));
this->addChild(sprite);

    auto wallNode = Node::create();
    auto wallBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);
    wallNode->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
    wallNode->setPhysicsBody(wallBody);
    this->addChild(wallNode);

    auto maskBlock = Sprite::create("maskBlock.png");
    auto maskBody = PhysicsBody::createBox(maskBlock->getContentSize());
    maskBlock->setPosition(Vec2(origin.x + visibleSize.width / 2 + 100, origin.y + visibleSize.height - 100));
    maskBlock->setPhysicsBody(maskBody);
    this->addChild(maskBlock);

    this->scheduleUpdate();

    return true;
}

void HelloWorld::update(float dt) //it's empty
 {
 }
}

#2

so I’ve figured out that if I remove first animation - it’s perfectly fine, I’ve tried delaying it by ScheduleOnce but still get weird consequences. Very strange.

UPDATE: Fixed by setting first frame after initializing sprite. (Dunno how to mark topic fixed)

sprite->setSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(“sprPlayerIdle1-0-0.png”));


#3

You need retain in a case where you aren’t adding the node as a child of another node that’s in connected to the SceneGraph

The reason is precisely because of how cocos2d-x manages memory.
All Node objecst are derived from Ref, and any Ref derived object will be added to a pool,
if it is currently added as a child than cocos2d-x knows that this Node is still playing a role
and isn’t ready for cleanup. However if it isn’t cocos2d-x was designed to automatically cleanup the memory
hence make it invalid.

There is one exception to this rule, if you call retain than you are explicitly telling cocos2d-x to retain that object even though it may seem useless for now because you will use it later on.

Hope I explained it well :slight_smile: