1
votes

I've created a box2d body that is attached to a second box2d body with a weld joint. The first box2d sprite associated with the body is in the shape of a stick. The second box2d body is a person that throws the first box2d body. The first box2d body is initialized as a polygon shape with a specified density, friction, and restitution. Depending on the game state, the first box2d body may get changed to a different sprite (but the box2d body remains the same). The new sprite is in the shape of a box. When the change to a new sprite is made, the original weld joint is destroyed and the new sprite is substituted. A new weld joint is created to reattach the box2d body to the second box2d body (i.e. reattached to the person). In addition, the box2d fixture of the first body is changed to have more friction and less restitution because I don't want the second type of sprite to bounce and slide as much as the first type of sprite.

In each case, I have an impulse that I apply to the first box2d body when I programmatically break the weld joint. With the second sprite (the box), the distance traveled after applying the impulse is much farther than the first sprite (the stick). I don't understand why there is such a difference since I've only changed the "look" of what is being thrown. The density and mass is the same. When I step through the code, the linear velocity appears to be the same in the box2d structure. There is apparently something in the physics that I don't understand.

My goal is to have both sprite types travel to the same location if given the same impulse. Is it possible to enable each sprite type behave the same? Please provide some guidance to achieve my goal.

Below is the code where I remove the old sprite and reattach the new sprite (note that "attachedBody" is the box2D body that was previously defined with the old sprite):

b2WeldJoint *myJoint;

// break the existing joint
// Destroy joint so the attachedBody will be free from the player
world->DestroyJoint(myJoint);

// Substitute the existing sprite with a new sprite. Also transform the position of the new sprite so that it is still touching the players hand
Box2DSprite *sprite = (Box2DSprite *) attachedBody->GetUserData();
[sprite setDisplayFrame: [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: @"newSprite.png"] ];
attachedBody->SetTransform(teamA.foreArmBody->GetWorldPoint(b2Vec2(65.0/100.0, -25.0/100.0)), -40.0f); // move new sprite to the players hand. Rotate the angle by 40.

// Make this new sprite stick when it lands
attachedBody->GetFixtureList()->SetFriction(8.0);
attachedBody->GetFixtureList()->SetRestitution(0.0);

// Create a new weld joint with the players hand and the new sprite
b2WeldJointDef weldJointDef;
weldJointDef.Initialize(attachedBody, teamA.foreArmBody, teamA.foreArmBody->GetWorldPoint(b2Vec2(6.0/100.0, -10.0/100.0)));
weldJointDef.collideConnected = false;

myJoint = (b2WeldJoint*)world->CreateJoint(&weldJointDef);
1
Presumably, the fixtures on these two bodies are set so that they don't collide with each other right? And you are sure that the mass is the same, even with a different shape? The description is a bit hard to follow, but you should be able to figure out what causes it by the process of elimination. For example, you mention that some things (friction, restitution etc) are different between the two. Gradually remove all the differences and somewhere along the way, it should become apparent which is the factor that causes the change.iforce2d
Have you checked the mass of the two bodies (that are going different distances) as Box2D is seeing it? Using the body.GetMass() function, is the mass the same with the two different second bodies? ALSO: Where are you applying the force? If it is not the center of mass (but its position, which is not necessarily the same), then the impulse may have some of its energy converted to rotational momentum instead of linear momentum. Do the bodies spin when you apply the impulse?FuzzyBunnySlippers

1 Answers

0
votes

After digging deeper to answer the above comments, I found that I was not comparing apples and oranges. My problem is that in one case, the first body (the stick) had zero velocity when I applied the impulse. When I substituted the sprite of the first body with a new sprite and then gave it the same impulse, the body had a non-zero initial velocity. Therefore it travelled much farther. My solution is simple. I just need to set the velocity to zero before applying the impulse to cause the two different sprites to travel the same distance. For example:

attachedBody->SetLinearVelocity(b2Vec2(0,0));