5

I'm trying to make a simple forever bouncing ball with new sprite kit on ios 7. I set gravity:

 scene.physicsWorld.gravity=CGVectorMake(0, -9);

And for the ball body I set:

ball.physicsBody=[SKPhysicsBody bodyWithCircleOfRadius:17];
ball.physicsBody.mass=1;
ball.physicsBody.restitution=1;
ball.physicsBody.linearDamping=0;
ball.physicsBody.angularDamping=0;

Ball here is just SKSpriteNode. but i have one problem: every time it bounce back its position become a little bit higher and higher. And in a few minutes ball is almost at the top of the screen. Can anyone help with this issue. I just wanna make ball bounce back to the same position every time (for example middle of the screen). Thanks.

Alexander
  • 83
  • 1
  • 7
  • Try making the vector (0,9) instead of (0,-9) and tell me what happens – erdekhayser Sep 28 '13 at 18:34
  • the same problem but ball now bounce from the top of the screen (like if the ground is on the top) – Alexander Sep 28 '13 at 19:15
  • That's what I thought would happen. You are saying that every bounce, the ball bounces higher? – erdekhayser Sep 28 '13 at 20:09
  • Exactly. but i wanna make it bounces to the same height. Like infinite bouncing. – Alexander Sep 28 '13 at 20:45
  • do you have other bodies and if so, what are their friction and restitution values set to? Do you apply any forces to the ball or otherwise change velocity? – CodeSmile Sep 28 '13 at 21:49
  • no I don't have another bodies and i don't apply any forces to ball and do not change its velocity. I just add ball as a child to the scene in the init method and it starts bounce, but has this strange behaviour. – Alexander Sep 29 '13 at 06:25
  • actualy I have one another body assigned to the scene : self.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromRect:scene.frame]; and I don't change its properties. – Alexander Sep 29 '13 at 06:26

2 Answers2

15

There are probably two issues in play here:

  1. Two bodies are involved in the collision when the ball bounces -- the ball and the edge loop that it bounces off of. For no energy to be lost in the collision, you probably want zero friction and restitution on both bodies.

  2. Even if you do that, though, many physics engines (including SpriteKit's) have trouble with situations like this because of floating point rounding errors. I've found that when I want a body to keep a constant speed after a collision, it's best to force it to -- use a didEndContact: or didSimulatePhysics handler to reset the moving body's velocity so it's going the same speed it was before the collision (but in the opposite direction).

If you just have a ball bouncing up and down, that velocity reset is easy: just negate the vertical component of the velocity vector:

ball.physicsBody.velocity = CGVectorMake(0, -ball.physicsBody.velocity.dy);

If you're bouncing off an angled surface, it's slightly more complicated: normalize the velocity vector (i.e. scale it so its magnitude is 1.0) to get the direction after the collision, then scale that to make it the speed you want. When I'm doing that kind of vector math, I like to convert the vectors to GLKVector2 so I can use the fast math functions from the GLKit framework:

GLKVector2 velocity = GLKVector2Make(ball.physicsBody.velocity.dx, ball.physicsBody.velocity.dy);
GLKVector2 direction = GLKVector2Normalize(velocity);
GLKVector2 newVelocity = GLKVector2MultiplyScalar(direction, newSpeed);
ball.physicsBody.velocity = CGVectorMake(newVelocity.x, newVelocity.y);
GeneCode
  • 7,545
  • 8
  • 50
  • 85
rickster
  • 124,678
  • 26
  • 272
  • 326
  • thanks! Now I also think that a lot of physics engines has the same problem because of floating point rounding errors, like you mentioned. – Alexander Sep 30 '13 at 20:07
  • So at the first time i've tried to make restriction to the ball in the didSimulatePhysics method, for example if ball has y position higher then 305 I changed it to 300 but i think it's not the right way to do. So i decided to follow your advise and just set ball's velosity after collision to negative but with the same value as it was before, and it works. – Alexander Sep 30 '13 at 20:18
  • Actually, for me worked restitution set to 1 on the ball and to 0 on paddle. – Mariusz Aug 26 '14 at 10:15
0

it's strange but if i set:

 ball.physicsBody.linearDamping=0.02f;

It seems that ball don't change its bounce height.

Alexander
  • 83
  • 1
  • 7