Two Box2D Sprite Geometries Travel Different Distances With Same Impulse - ios

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);

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));

Related

sceneKit dynamic physic body fall through floor

I have a cube with dynamic physical body and a plane with kinematic physic body.When I place a cube above plane, it will fall onto plane and a bounce is expected.
The PROBLEM is: when the cube is small or light, it just go through plane.For instance, cube has 0.1*0.1*0.1 work fine but 0.05*0.05*0.05 sucks.In this case I still get physical body contacting notification.
this is my code for creating geometry:
//cube
//when dimension is 0.1 everything is fine
float dimension = 0.05;
SCNBox *cube = [SCNBox boxWithWidth:dimension height:dimension length:dimension chamferRadius:0];
cube.materials = #[material];
SCNNode *node = [SCNNode nodeWithGeometry:cube];
node.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:nil];
node.physicsBody.mass = 1;
node.physicsBody.categoryBitMask = phsicBodyCategoryCube;
node.physicsBody.collisionBitMask = phsicBodyCategoryPlane;
node.physicsBody.contactTestBitMask = phsicBodyCategoryPlane;
//plane
self.planeGeometry = [SCNBox boxWithWidth:100 height:0.01 length:100 chamferRadius:0
plane.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeKinematic
shape: [SCNPhysicsShape shapeWithGeometry:self.planeGeometry options:nil]];
plane.physicsBody.categoryBitMask = phsicBodyCategoryPlane;
plane.physicsBody.collisionBitMask = phsicBodyCategoryCube;
plane.physicsBody.contactTestBitMask = phsicBodyCategoryCube;
I’m surprised you’re getting collisions at all. See the SCNPhysicsBodyType docs – the kinematic type is for bodies that you move (by setting their position, etc) to cause collisions, but that aren’t themselves affected by other bodies colliding with them.
If you set the floor’s type to static, you’ll probably see better results. A static body doesn’t move (either as a result of physics interactions, or by you setting its position), so the physics engine can more accurately check for other bodies colliding with it.
edit: Other things to look into:
Use a SCNPlane rather than a SCNBox for your floor. (Note that you can create physics bodies with shapes different from their visible geometry, if that helps.) I'm not sure about SceneKit's, but it's easier for a lot of physics engines to check "has some object passed this infinite boundary since the last frame?" than "is some object inside this finite region on this frame?"
Enable precise collision detection for your moving objects.
Finally I found this is all about SceneKit's physical simulation. If the cube falls too fast, It will make a large penetration with plane In physical simulation steps. In this case sceneKit just let it fall through plane instead of collision. When I change cube's velocity to a small value It collided with plane.
My solution is to give cube a upward velocity when large over-penetration happens, which is the 30% of fall velocity. The trick is adjusting cube's velocity until a collision happens.
Works only for spherical physics shapes
For this issue SCNPhysicsBody has special attribute: continuousCollisionDetectionThreshold
For example, in a game involving projectiles and targets, a small
projectile may pass through a target if it moves farther than the
target's thickness within one time step. By setting the projectile's
continuousCollisionDetectionThreshold to match its diameter, you
ensure that SceneKit always detects collisions between the projectile
and other objects.

Move along uneven physics body with Sprite Kit

I have a physics body that is uneven but not dynamic (the terrain) and a physics body (character) that is dynamic and is on top of the terrain, and I want this character to move along the terrain simulating kind of a "walking" action where it will keep going up the terrain but it won't fall back (or move back) like a ball because of gravity, and to set a maximum tilt so that it does not tip over.
My attempt was to add a force in the direction I want the character to move but this is causing the character to fall back due to gravity, and I don't want to disable gravity because then character won't fall down when going down the terrain.
Thank you very much
this is why using a physics engine for a platforming game is very difficult and not always a great approach..
you can try sprite.physicsBody.allowsRotation = false
might help
Create SKAction to move your character to destination point or dx and dy. Run that SKAction from your character node with the runAction. Like
SKAction.moveByX(...
When the action is finished, gravity will bring the character down.
If the movement is slow, play with the character's physicsBody friction and/or mass.
You can also change the the character's physicsBody.velocity = CGVectorMake(
And your terrain will be better with edgeLoop physicsBody which won't be dynamic.
And with uneven you mean inclined but smooth? If not smooth and with edges, your character may get held up at an edge depending on center of gravity of character and if you are allowing rotation.

Implementing bodyWithBodies in Sprite Kit

I am using Apple's Sprite Kit to create a game, and currently I have drawn an SKShapeNode object that looks similar to the following:
My actual sprite has rounded edges, but for simplicity, I am trying to get everything working with this shape first. I am able to draw the sprite perfectly fine. However, I am having trouble creating a physics body to cover the sprite. I want the sprite to recognize collisions anywhere along its surface, so I want a physics body that covers only the dark gray area. Also, I want the sprite to respond to forces and impulses, so I need a volume-based physics body.
My first idea was to simply use the same CGPathRef that I used to create the image for the sprite, and pass it to the bodyWithPolygonFromPath method to create a corresponding physics body. I have come to find this will not work, as my shape is not convex.
So, now I am thinking I should be able to use bodyWithBodies to create a physics body shaped appropriately. I want to create three rectangular physics bodies (one to cover the left of the gray area, one to cover the top, and one to cover the right), and use those to create one physics body whose area covers the gray area of my sprite by using this:
mySprite.physicsbody = [SKPhysicsBody bodyWithBodies:#[body1, body2, body3]];
However, the main problem I am having is correctly positioning the individual bodies that go into the array, which is passed to the bodyWithBodies method. By using the above method, I obviously have no way of controlling where these physics bodies are being placed in relation to each other. The result is all three physics bodies stacking on top of each other in the center of mySprite.
How exactly are you supposed to position the physics bodies in the array relative to each other before passing them to the bodyWithBodies method?

SpriteKit - drawing circles containing other circles with physics body

I am new to Objective-C and I am trying to make a simple spriteKit game which contains a circle and a ball inside it. I want to move the ball around in this circle as well on the iPhone movement. So far I have created the circle and am able to put the ball on the screen.
My problem is that I am not sure the ball is actually inside the circle or on top of it. When I attach a physics body on the ball, it drops out of the screen and does not stop on the circle's bottom edge. I am using SKShapeNode for both the circle and ball.
Please help me to provide the right documentation to go through or a little piece of code that can resolve this.
You need to assign appropriate physics bodies to your nodes. See Simulating Physics in the Sprite Kit Programming Guide.
From your description, it sounds like you need to create the outter circle's physics body with the bodyWithEdgeLoopFromPath: method (and provide a path representing the circle). Note that an edge loop physics body is not dynamic and can only collide with volume-based bodies.
The inner balls physics body can be created with bodyWithCircleOfRadius:.

Zooming out of my world: Joints and their positions are not adjusted

Here is my setup:
SKScene with a node called world
to this world, I attach another node: vehicle
to this vehicle, I attach three nodes that make up the vehicle; a body and two wheels
the wheels are attached to the body via SKPhysicsJointPin specifying their anchors
Now, everything is fine until I zoom out of my world:
[_world runAction:[SKAction scaleTo:0.5 duration:0.75]];
My vehicle suddenly lifts off the wheels. It appears as if the same distances as in the not-zoomed-in-world are kept. All parts of the vehicle are properly scaled- except the distances to its parts.
Do I have to apply the zoom to my joints as well? Or do I need to reset the anchor of my joints?
Thanks for your help!
Physics don't scale. Changing a node's scale is a purely visual effect, it does not alter physics in any way.
Even if you manually update physics positions synchronized with a node's scale you'll find that you can't scale each body's shape without removing the previous body and replacing it with a corresponding body of the same shape, just scaled. During a scale action you would have to through away and create new bodies every frame, which will probably cause a serious framerate issue.

Resources