[RESOLVED] Cocos2d-x 3.x Question about Physics Body and Physics World

Hi all,

I’m a new user of cocos2d-x and i have begun to use the 3.0 and now 3.1 version of the framework.
I ve began to use cocos2d-x physics integrated API but i’ve a question about the way to add a physics body to the physics world.

I’ve studied the cocos2d-x source code and it seems that when the Node::setPhysicsBody(newBody) function is called on a node, the newBody is only added to the previous attached body’s world if this one exist.
If the node hadn’t a previous body, the new one is not added to any world!

In deed, the only way to add a new body ‘B’ to the world ‘W’ attached to a scene ‘S’ is to add a child ‘C’ containing a node or a parent of a node attached to ‘B’ to the scene ‘S’.
At this time all bodies attached to ‘C’ and it’s children will be added to ‘W’.

Would’nt be better if on a call to Node::setPhysicsBody() the body were automatically attached to the world of the scene containing the node?

I need in my little game to dynamically add sprites with physics bodies.
The only way to add theses bodies to the scene’s world is to (and i know it’s so much ugly) remove and readd the first child of the current scene each time to ensure the Scene::addChildToPhysicsWorld function is called!!

So, what is your opinion about it?

Have you looked at: http://www.cocos2d-x.org/wiki/Physics

Yes i have but in this wiki the node with physics body is added directly to the scene, which is a huge restriction of the global use of nodes (i mean if we have to add all nodes directly to the scene, why bothering to have a generic parent/child pattern?)

Well, i’m not really asking for help, i’m just suggesting that the Physics api design should be enhance.

The use case is the following : if we add a node with a physics body to a node which is a child of a scene (not the scene directly) then the body of the new added node will not be attached to the physics world of the scene (well it’s not a question i’m pretty sure of this behavior after looking on the physics source code).

To me with the current design, if we want to do that we have to re-add a node directly to the scene to trigger the Scene::addChildToPhysicsWorld function. And this is of course an ugly hack because we have to call a function in order to achieve a goal by side effect…

@klems of course you can set a body to a node not direct added to scene( see PhysicsTest->PhysicsPositionRotationTest ).
If you have problem with the relationship between PhysicsWorld and Scene, you can see the discussion here: https://github.com/cocos2d/cocos2d-x/pull/5493

Thanks boyu0, my point is not about the relation between Scene and PhysicsWorld (the topic you link is far more complex to me :))
Moreover i don’t say that it’s not possible to add a physics body to a node which is not directly the scene but in this case you have to call scene->addChild after the creation of bodies to add them to the physics world and that’s a limitation to me.
What if i want to create and add bodies to a layer AFTER the layer has been added to the scene??

The example PhysicsTest->PhysicsPositionRotationTest only works because the physics bodies are created BEFORE the layer is added to the scene, let’s perform a small analysis of this code.
The function calls are perform this way :

scene->addChild(layer) which means Node::addChild(layer) and THEN Scene::addChildToPhysicsWorld() (which is THE triger function to add bodies to world)
In Node::addChild(layer) the function layer->onEnter() is called and it’s in this function the bodies are created and added to layer’s child nodes.

So in this example the bodies are created before the layer is added to the scene and that’s why these bodies are correctly attached to the world.

But what if i want to dynamically create some bodies in the layer::update function? i will have to triger the scene->addChild() function to make these new created bodies attached to the world, which demonstrate i think a pattern issue.

Hmm, if I understood correctly, I think what your said is also can work.
You can see the code in Node::addChild():

#if CC_USE_PHYSICS
    // Recursive add children with which have physics body.
    for (Node* node = this; node != nullptr; node = node->getParent())
    {
        Scene* scene = dynamic_cast<Scene*>(node);
        if (scene != nullptr && scene->getPhysicsWorld() != nullptr)
        {
            scene->addChildToPhysicsWorld(child);
            break;
        }
    }
#endif

So if you add a child to a node, it will find the scene the node belongs to, and add this child to this scene.
See PhysicsTest->PhysicsDemoSlice, it remove and add body at onTouchEnded.
Have you test the issue you said? If you find some bugs in it, you can submit you code here, then we will fix it.

Ok, my bad, i didn’t see this part.
So there is the remaining constraint, the first call to Node::setPhysicsBody must be peformed before the parent Node::addChild function (well this is logical :)).
That’s why that didn’t work in my code, the first thing i performed after sprite creation was to add it to it’s parent and then i’ve attached the physics body.
I didn’t paid attention to this, my apologies!

So finally it’s not a pattern issue at all, it’s all my fault, and i’m felling really dumb right now :smiley:

@klems
I noticed that, it’s a bug, and I sent a PR for this bug: https://github.com/cocos2d/cocos2d-x/pull/6969
Thanks~