6

I am trying to keep my SKSpriteNodes moving at a constant speed forever, even after collisions. I have set gravity to 0, friction to 0, and linear and angular dampening to zero, but the Sprites still slowly slow down to zero velocity. How can I keep them moving?

Based on the answer below, this is what I have tried: EDIT This code below works! I just had to check if the nodes were going slower than the limit and speed them up.

[self enumerateChildNodesWithName:kBallName usingBlock:^(SKNode *node, BOOL *stop)
    {
        SKSpriteNode *ball = (SKSpriteNode *)node;
        if (ball.physicsBody.velocity.dx < 0) {
            if (ball.physicsBody.velocity.dx > -50)
                ball.physicsBody.velocity = CGVectorMake(-50, ball.physicsBody.velocity.dy);
        }
        if (ball.physicsBody.velocity.dx > 0) {
            if (ball.physicsBody.velocity.dx < 50)
               ball.physicsBody.velocity = CGVectorMake(50, ball.physicsBody.velocity.dy);
        }
        if (ball.physicsBody.velocity.dy < 0) {
            if (ball.physicsBody.velocity.dy > -50)
                ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, -50);
        }
        if (ball.physicsBody.velocity.dy > 0) {
            if (ball.physicsBody.velocity.dy > 50)
                ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, 50);
        }
    }];
Siriss
  • 3,737
  • 4
  • 32
  • 65
  • 1
    How do you get them moving in the first place? – sangony Mar 10 '15 at 20:43
  • I just apply an impulse when I create them. What code should I post? I figured it would mostly just be generic Sprite creation code, but I can put it in if needed. – Siriss Mar 10 '15 at 22:36

2 Answers2

3

If you apply an impulse to a node's physics body it is only applied once. Think of kicking a ball. Applying a force on the other hand is like a continuos push, like an engine moving a car. Keep in mind that if you continue to apply force, your node will get faster and faster so you will have to assign a speed limit at some point. You can do that with something like this:

if(myNode.physicsBody.velocity.dx > 300)
    myNode.physicsBody.velocity = CGVectorMake(300, myNode.physicsBody.velocity.dy);

That will limit your "moving right" speed to 300.

Another option is to move your node manually by changing it's position. You can do that by using something like myNode.position = CGPointMake(myNode.position.x+1, myNode.position.y);. That will move your node to the right by 1 every time the code is run.

sangony
  • 11,636
  • 4
  • 39
  • 55
  • Thanks! would you apply the speed limit in update (or similar)? Just enumerate the nodes I want to keep moving and then slow them down? – Siriss Mar 11 '15 at 01:17
  • @Siriss - Yes. You would do all that in the update method. Exactly how depends on your code and how it is structured. – sangony Mar 11 '15 at 01:34
  • @Siriss - Try setting the restitution property to 1.0 on all your moving nodes. – sangony Mar 18 '15 at 17:27
  • After reading the docs, applyForce is only for one game cycle. I had to keep speeding them up. – Siriss Mar 18 '15 at 20:32
  • Thank you a lot, i wonder why i can stop my ball from rolling, -forceApply was called in renderer(updateAtTime) function, and continuously apllied force and moving ball forever – Mr.Fingers Feb 13 '20 at 19:03
0

Set the restitution property of your nodes to 1.0. Restitution is how much of a node's energy is retained after a collision.

https://developer.apple.com/library/mac//documentation/SpriteKit/Reference/SKPhysicsBody_Ref/index.html#//apple_ref/occ/instp/SKPhysicsBody/restitution

Example:

marble_node.physicsBody?.restitution = 1.0  

The default restitution is 0.2. Changing it to 1.0 will keep things very bouncy!

user13428
  • 86
  • 2