Node's Position Doesn't Stay Synced With the One on the Screen After Bouncing Due to Collision

So I got one dynamic object on the world, and it’s moving because I’ve set it some velocity. However, when I try to get its position, I get the accurate one for as long as it doesn’t collide with static objects and bounces.

I think the physics engine changing the velocity puts the position out of sync. According to what I can see from the rendered graphics, the object is moving properly and nothing wrong can be seen. It’s just that when I fetch the position of the object through the API, I get a value which is quite different from the actual position of the object as per the render.

To debug this, I created a trail (series of points) which is formed right where the API tells me the object is (using getPosition method). The points of the trail is created every step in the game (called 60 times a second). Here’s part of the code responsible for the trail:

auto organismPosition = organism.getNode()->getParent()->convertToWorldSpaceAR(organism.getNode()->getPosition());

auto trail = DrawNode::create();
trail->drawPoint(organismPosition, 5, Color4F::MAGENTA);

this->addChild(trail);

The trail follows the object perfectly, until object hits a static object and bounces. I’m putting a link to a video which shows how it looks like:

https://drive.google.com/file/d/1JQYrkbbyY07kSHcFvPTW9BObyX3JPUfe/view?usp=sharing

In this video, the object did change velocity seconds before the collision because of a scheduled call of a function which randomly changes the velocity slightly.

You can check out the entire project here: https://github.com/nahiyan/darwin/tree/master/simulations/Organism

I’m using the default physics engine that comes with cocos2d-x (v4).

Can anyone suggest me why this is happening? Let me know if you need more information to understand the problem better.

Interesting. I like the way you are debugging this. Hmmm…

When I printed the positions to the screen, I knew that something looked out of place. However, I noticed the pattern only when I drew the trail. I badly need to fetch the position - for ray tracing, and redrawing (to change color of the antennae of the organisms). This kind of problem is really strange. I’m using the default physics engine that comes with cocos2d-x (v4).

Is there a need to use that conversion? The node is clearly working in the scene, since it’s still visible, so the coordinates being used to draw it are correct. The only difference is your usage of the convertToWorldSpaceAR. Have you checked the position of the node without the conversion?

EDIT: Never mind! Yes, you do need convertToWorldSpaceAR if you want to draw using DrawNode. This is a really strange problem.

1 Like

The issue is that you’ve created the object to be placed at a specific position, but you’ve passed that position as the object offset instead:

Organism::Organism(const Vec2 &position)
{
    this->node = DrawNode::create();
...
    this->node->drawDot(position, 20, Color4F::GREEN);
    this->node->drawLine(position + Vec2(0, 20), position + Vec2(40, 100), Color4F::RED);
    this->node->drawLine(position + Vec2(0, 20), position + Vec2(-40, 100), Color4F::RED);

    auto physicsBody = PhysicsBody::createCircle(20, PhysicsMaterial(0.1f, 1.0f, 0.0f), position);
...
}

static PhysicsBody* createCircle(float radius, const PhysicsMaterial& material = PHYSICSBODY_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO);

Where

@param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates.

Also, you do not need to use convertToWorldSpaceAR at all, since the node position is correct. The position shouldn’t be used when drawing with DrawNode either, since they’ll end up at the incorrect offsets as well.

So, to fix it:

Organism::Organism(const Vec2 &position)
{
    this->node = DrawNode::create();
    
    // remove the position from these calls
    this->node->drawDot(Vec2(0,0), 20, Color4F::GREEN);
    this->node->drawLine(Vec2(0, 20), Vec2(40, 100), Color4F::RED);
    this->node->drawLine(Vec2(0, 20), Vec2(-40, 100), Color4F::RED);

    auto physicsBody = PhysicsBody::createCircle(20, PhysicsMaterial(0.1f, 1.0f, 0.0f));  // remove the last parameter, since it's an offset
    physicsBody->setDynamic(true);
    physicsBody->setGravityEnable(false);
    physicsBody->setCategoryBitmask(1);
    physicsBody->setCollisionBitmask(6);
    physicsBody->setContactTestBitmask(2);

    this->node->addComponent(physicsBody);
    this->node->setPosition(position);  // add this

    this->foodIntersection = false;
}

and…

void MainScene::update(float delta)
{
...
    for (auto organism : this->organismList)
    {
        auto organismPosition = organism.getNode()->getPosition();

        auto trail = DrawNode::create();
        trail->drawPoint(organismPosition, 5, Color4F::MAGENTA);

        this->addChild(trail);
...
}
1 Like

Good news! I fixed it. It was the anchor point of the physics body which caused the issue. I realized it when I set an angular velocity. Still it was a weird problem.

I’ve set the position of the DrawNode to the place where I wanted the object to be. Then I’ve drawn the dot and lines of the object at (0, 0), along with the position of the physics body set at that point. Before I did draw the stuff and place the physics object in the desired position, whilst the DrawNode's position was (0, 0).

And you were right actually. I didn’t need to use convertToWorldSpaceAR. This is how I retrieve the position of the object now:

auto organismPosition = organism.getNode()->getParent()->convertToWorldSpace(organism.getNode()->getPosition());

Thank you all for your help. I wish someone else can learn from my mistakes! This is my 4th day of using cocos2d-x.

This is the actual solution. Thank you.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.