0

I'm trying to move a sprite in a set direction on-screen, using the physicsBody.velocity property. However, the motion is quite "jumpy" (makes the game look like it's lagging). I assume this has something to do with the different time intervals between each call to the update-method. How could I achieve a more "smooth" motion?

Right now this is the code I have in my update-loop to make the sprite move forward:

if (_movingForward) {
  CGFloat forwardVel = _ball.physicsBody.velocity.dx;
  forwardVel += 20.0;
  if (forwardVel > bMaxForwardVelocity) {
    forwardVel = bMaxForwardVelocity;
  }
  _ball.physicsBody.velocity = CGVectorMake(forwardVel, _ball.physicsBody.velocity.dy);
}

As you can see, I'm trying to make the speed pick up, so it doesn't immediately reach it's terminal velocity. This is to make the motion look more natural. However, the lagging is ruining this effect greatly, even when the sprite supposedly is traveling at a set speed.

EDIT 1:

I'm trying to make a platform-style game (like Super Mario etc) where the _ball moves horizontally along the ground when the user taps the screen. The code for moving the ball to the right is included above the edit. The ground is made up of multiple tiles, each 32x32 and positioned right next to each other with no gap in-between.

As per request, here's the code for setting up the _balls physicsBody:

self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:self.size.width/2.0];
self.physicsBody.dynamic = YES;
self.physicsBody.restitution = 0.5f;
self.physicsBody.usesPreciseCollisionDetection = YES;
self.physicsBody.allowsRotation = NO;
self.physicsBody.mass = 0.5f;
self.physicsBody.friction = 0.0f;
self.physicsBody.linearDamping = 0.0f;
self.physicsBody.categoryBitMask = CollisionCategoryBall;

And here's the code for the physicsBody of each individual tile:

tile.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:tile.size];
tile.physicsBody.dynamic = NO;
tile.physicsBody.categoryBitMask = CollisionCategoryGround;

The physicsWorld is set up like this:

self.physicsWorld.gravity = CGVectorMake(0, -4);
self.physicsWorld.contactDelegate = self;

Thanks!

EDIT 2:

This is a side-scrolling game, so the "camera" follows the ball. Here's the code for moving the background layer:

- (void)centerViewOn:(CGPoint)centerOn {
  CGFloat x = Clamp(centerOn.x, (self.size.width / 2.0), (_bgLayer.layerSize.width) - (self.size.width / 2.0));

  _worldNode.position = CGPointMake((int)-x, _worldNode.position.y);
}

The reason for the Clamp is so the "camera" doesn't scroll beyond the bounds of the background. This is when the ball is close to either the start or end of the level. I'm casting the position to an int because without it, small gaps sometimes occur between the tiles. I was told this was because of some inaccuracy or something. However, even without casting the position to int, it's still a bitt "laggy". But because of the gaps between the tiles, it looks even worse.

Aleksander
  • 2,735
  • 5
  • 34
  • 57
  • friction ? linearDamping ? – prototypical Aug 13 '14 at 00:08
  • 1
    http://stackoverflow.com/questions/19286610/constant-movement-in-spritekit/20206522#20206522 – prototypical Aug 13 '14 at 00:14
  • @prototypical I'm not looking for a way to simulate acceleration, I simply included it in my post to explain the code. What I'm looking for is a way to dynamically set the velocity based on the time elapsed between each update loop, so it's not as laggy. I'll have a look at the link you sent though, might contain some useful tips :) – Aleksander Aug 13 '14 at 00:20
  • Well, when you say it's laggy, but you don't specify if there is a framerate issue ? If not, then it's something to do with the physics, correct ? You say there is a lagging effect, even when the sprite is 'supposed to be' moving at a set speed. Seems to me, you need to read that link ;) – prototypical Aug 13 '14 at 01:51
  • My reason for mentioning friction and linear damping is that they can cause this laggy/jumping effect that you speak of. I can't see it, so it's hard for me to say if that is the cause. What is the framerate ? it'd be helpful to know if this is framerate issue or otherwise, right ? – prototypical Aug 13 '14 at 01:54
  • 1
    @prototypical has a point. If the linearDamping or friction properties are set to a nonzero value, they will affect the velocity of the node because the physics are simulated after the update method is called. Hence, the node might be getting a variable velocity in each iteration of the game loop, causing the lag that you describe. – ZeMoon Aug 13 '14 at 05:35
  • @prototypical the game is running at 60fps on my device, but I've been told that the interval between each call to the `update` method (and therefore also the `didSimulatePhysics` and so on), differs each time even at 60fps. I was also told to somehow include a `_dt`-variable and use that to calculate the velocity, but I don't see how I can do that. Both the `friction` and `linearDamping` of the object to move (_ball) is set to `0.0f`. Do I have to set this for the object the `_ball` is sliding across as well? – Aleksander Aug 13 '14 at 15:36
  • What about `affectedByGravity" property ? – prototypical Aug 13 '14 at 21:09
  • @prototypical the `_ball` is affected by gravity. Is that what's making the motion seem "laggy"? The gravity is actually an important part of the game, and don't really wanna replicate all the built-in spritekit behavior, so hopefully that's not it. – Aleksander Aug 13 '14 at 21:32
  • We are playing a bit of coding charades here, it would be ideal to see all the actual code involved. Having gravity and not having gravity are two pretty distinct situations. I have no idea what your expectations are when you set the velocity vector's dx. If there is no gravity it should move in a straight line. But if there is gravity and you are applying unrealistic velocity to an object dropping - that could look laggy or jumpy. Post your code for the physics world and said physics body etc. – prototypical Aug 13 '14 at 21:47
  • Basically I'm trying to make a platform-style game (like Super Mario etc). I want my sprite (`_ball`) to move horizontally on the ground, when the user taps the side of the screen. I'll add some code to my original post :) – Aleksander Aug 13 '14 at 21:55
  • Well, mario has a scrolling level too. Are you scrolling at this point ? – prototypical Aug 13 '14 at 22:07
  • Yes, the level follows the `_ball`. I'll add that code to my original post as well – Aleksander Aug 13 '14 at 22:14
  • yeah, I'm about done here, unless you github this. I just did a quick test with this code making some assumptions based on setup and it is silky smooth. However your tiles and scrolling implementation is not something I am going to go the charades route with. – prototypical Aug 13 '14 at 22:17
  • I really appreciate you trying to help me, and to be honest, I really need it haha. So if you'd just give it one last look, I'd be really thankful. I made a simplified project and added it to dropbox: https://www.dropbox.com/s/6moroer7sty3vzj/Background%20layer%20test%20game.zip If you look closely at the ball, you can see that it's lagging ever so slightly, and this gets really annoying after playing for a few minutes. Again, thanks a million! – Aleksander Aug 13 '14 at 22:30

1 Answers1

0

The issue was with your scrolling code.

change this line :

_worldNode.position = CGPointMake((int)-x, _worldNode.position.y);

to

_worldNode.position = CGPointMake(-x, _worldNode.position.y);

The movement is then silky smooth.

But then you do get those seams. You should solve that in the placement of those tiles. You are likely positioning your _worldNode tiles with float values.

prototypical
  • 6,731
  • 3
  • 24
  • 34
  • I tried doing this in the simplified project I uploaded, and you are right - changing this makes the motion silky smooth. Sadly, when changing this in my original project, the lagging actually got worse - This time it's the background that's lagging, not the actual ball as before. But I guess this is some sort of progress haha. Thanks a million for your help! :) – Aleksander Aug 13 '14 at 23:01