Reputation: 51
My main character, which is a SKSpriteNode with physicsBody, is shaking when moving or jumping.
I am moving my character by changing is character.physicsBody.velocity.dx
's (in order to simulate acceleration or deceleration), and I use applyImpulse
to make him jump.
Code :
To move :
[self.physicsBody setVelocity:CGVectorMake(self.physicsBody.velocity.dx - 30, self.physicsBody.velocity.dy)];
To jump :
if (!isJumping)
{
[self.physicsBody applyImpulse:CGVectorMake(0.0f, 6.0f)];
}
In addition, I use a method i found on internet to change the camera position on the map, so as to follow the character :
- (void)setViewpointCenter:(CGPoint)position
{
NSInteger x = MAX(position.x, self.size.width / 2);
NSInteger y = MAX(position.y, self.size.height / 2);
x = MIN(x, (self.map.mapSize.width * self.map.tileSize.width) - self.size.width / 2);
y = MIN(y, (self.map.mapSize.height * self.map.tileSize.height) - self.size.height / 2);
CGPoint actualPosition = CGPointMake(x, y);
CGPoint centerOfView = CGPointMake(self.size.width/2, self.size.height/2);
CGPoint viewPoint = CGPointSubtract(centerOfView, actualPosition);
self.map.position = viewPoint;
}
Result ?
Here it is (recorded with QuickTime from iPhone 5). You can easily see the trouble on this video and how much this is breaking my head (and my game that I've just started to develop).
Indeed, there is often (not each time, sometimes it is perfect) like a ghost and he becomes blurred. I don't understand nothing, i do not find any solution.
I tried this on simulator and on my device, same effect.
I can post more code if you want, and can tell you everything, and I hope someone will find where I did something wrong !
Thanx in advance !
Paul
Edit 1 :
Thank you for comments !
I have 8 draws shown on the screen, 145 nodes and no real problem is appearing with physics !
To move my character to the left, i just run :
-(void)moveToLeft {
if (isJumping && isOnRightSide)
{
[self.physicsBody setVelocity:CGVectorMake(-self.physicsBody.velocity.dx / 2.0, self.physicsBody.velocity.dy)];
}
[self setIsOnRightSide:NO];
[self setIsStopping:NO];
[self setIsRunning:YES];
[self.physicsBody setVelocity:CGVectorMake(self.physicsBody.velocity.dx - 30, self.physicsBody.velocity.dy)];
}
And to the right :
-(void)moveToRight
{
if (isJumping && !isOnRightSide)
{
[self.physicsBody setVelocity:CGVectorMake(self.physicsBody.velocity.dx / 2.0, self.physicsBody.velocity.dy)];
}
[self setIsStopping:NO];
[self setIsOnRightSide:YES];
[self setIsRunning:YES];
[self.physicsBody setVelocity:CGVectorMake(self.physicsBody.velocity.dx + 30, self.physicsBody.velocity.dy)];
}
And then :
if (_isStopping)
{
if (isOnRightSide)
{
int ralentissement = MIN(self.physicsBody.velocity.dx, 10);
[self.physicsBody setVelocity:CGVectorMake(self.physicsBody.velocity.dx - ralentissement, self.physicsBody.velocity.dy)];
}
else
{
int ralentissement = MAX(self.physicsBody.velocity.dx, -10);
[self.physicsBody setVelocity:CGVectorMake(self.physicsBody.velocity.dx - ralentissement, self.physicsBody.velocity.dy)];
}
if (abs(self.physicsBody.velocity.dx) < 1)
{
isRunning = NO;
_isStopping = NO;
if (self.hasActions)
[self removeAllActions];
[self.physicsBody setVelocity:CGVectorMake(0, self.physicsBody.velocity.dy)];
}
}
if (isOnRightSide && isRunning && self.physicsBody.velocity.dx < 150 && !_isStopping)
{
[self.physicsBody setVelocity:CGVectorMake(self.physicsBody.velocity.dx + 10, self.physicsBody.velocity.dy)];
}
else if (!isOnRightSide && isRunning && self.physicsBody.velocity.dx > -150 && !_isStopping)
{
[self.physicsBody setVelocity:CGVectorMake(self.physicsBody.velocity.dx - 10, self.physicsBody.velocity.dy)];
}
if (abs(self.physicsBody.velocity.dx) > 150)
{
if (isOnRightSide)
[self.physicsBody setVelocity:CGVectorMake(150, self.physicsBody.velocity.dy)];
else
[self.physicsBody setVelocity:CGVectorMake(-150, self.physicsBody.velocity.dy)];
}
Is there a better solution to apply force constantly with acceleration and deceleration ?
I checked all my images, they all have same sizes!
I turned off the camera function and indeed, shakes stopped! So this function must be the wrong part, I have found it on raywenderlich, and I have no idea of how I could replace it. Do you know how ? Thanks!
Edit 2 :
So, I tried to move the call of my camera movement method to didFinishUpdate, and it works really better ! This shaking feeling disappeared and I can now play without that bad experience.
BUT there is still one thing happening when the character jump (which is done thanks to applyForce
method) : when he is going up, he still seems to go down sometimes, just 1 pixel here or there. It's very special and I don't know if a real issue of Sprite Kit or if it's my texture which are too big or anything else. I tried to look at the animation with physics body drawn and in fact there are some vertical shaking (more exactly, the rectangle colored in blue seems to be blinking).
Have you some ideas about that last issue ?
The horizontal movement are now perfect, thanks you all for your help.
Upvotes: 3
Views: 603
Reputation: 8130
i had this same problem (also following ray's tutorials) .. You're making the camera animate by following your character which looks really cool, but it causes the stuttering. the world is moving one way, and the character is moving the opposite direction, you get a treadmill kinda thing going and that causes the character to stutter. in ray's current book he does:
override func didSimulatePhysics() {
let target = getCenterPointWithTarget(player.position)
worldNode.position += (target - worldNode.position) * 0.1
I'm sure this is pretty similar to what you're doing right?? this is making it so the worldNode is constantly trying to catch up to the players movements. It gives the camera that elastic feeling.
try just going
worldNode.position = getCenterPointWithTarget(player.position)
If this fixed it, then we've narrowed it down further. The problem here is you lost that cool camera easing effect.
The thing is that I don't know where you are making your changes to the players movements.. I don't know if these are just one time methods that you call, or they run in your update loop.
I'll just give you an example of how I'm doing it in my game:
in Update:
// update ship position
ship.update(self.delta)
i move the screen in didFinishUpdate so I make sure this is the last thing that happens. Hopefully this stops any stuttering.
didFinishUpdate
override func didFinishUpdate() {
// move BG Nodes
self.moveBGNodes()
}
moveBGNodes method
func moveBGNodes(){
// method that calculates camera position (stops camera at screen edges)
let target = self.pointToCenterViewOn(ship.position)
// ease gameworld into ship's position
gameLayer.position += (target - gameLayer.position) * 0.1
Upvotes: 1