Hi!
I have created a box2d body with its fixture and set the body’s userData to a sprite but while the physics are getting simulated the sprite simply stays at the place where it started…
So my question is - How can I make the sprite be at the exact same position as the physics box I made all the time? I have an idea of that I could set the sprite’s position to be the same as the b2Body’s position every interval of the update function but I just don’t really know if that’s the most efficient way.
Thank you!
Your idea is exactly correct. Every update you set the sprite position to the body’s position using body->getPosition(). You also need to set the rotation of the sprite to the body.
Here’s some code directly from one of my projects.
Vec2 chainPos = Vec2(_chainBody->GetPosition().x * PTM_RATIO, _chainBody->GetPosition().y * PTM_RATIO);
// Only required if the sprite is not a child of the the world
chainPos = chainPos - this->getPosition();
_chainlinkSprite->setPosition(chainPos);
_chainlinkSprite->setRotation(CC_RADIANS_TO_DEGREES(-_chainBodies.at(i)->GetAngle()));;
So if we go through it step by step. First of all you need to get body position from the Box2d world coordinates. Box2D coordinates don’t use pixels they use meters. So you need to convert the position back to pixels by multiplying it with the PTM pixel to meters ratio. You define this yourself when you make a game. 30 is good value to use. You should research how this works.
Secondly you’ll notice the line that subtracts the parent object position from the sprite position. This is because the body position is returned in world coordinates and because this particular sprite is a child of another node. It needs to be in coordinates local to the parent node when you set it’s position. I.e. (0,0) will not be at the bottom left corner it will be at the location of the parent node. You can remove this step if the sprite is a parent of the world (the layer/scene).
Third you set the sprite position to the calculated position of the body in local coordinates to it’s parent. Or world coordinates.
Finally you set the sprite rotation to the angle (rotation) of the body. The body angle is in radians not degrees and also 0-360 is in the other direction so you have to negate the value. Just copy the code above and you’ll be fine.
Finally you need to make sure you’re updating these positions AFTER the world->step() function or you’re sprites will be slightly behind the actual bodies visually. To do this I have my world-step function on the main layer update loop and any child objects such as the one above. When you schedule the update function for the child object you tell it to run with priority 1. Which means it will run after the main update in the layer.
this->scheduleUpdateWithPriority(1);
That should be everything you need.
1 Like
Great! Thank you so much - much appreciated!
1 Like