1
votes

I use the code listed below as an experiment of SpriteKit. What I do is applying the same amount of force as a gravity effects to it but with anti-parallel vector (mass of body is set to 1.0). The function is executed on each frame via update function. I expect the object not to move at all as applyForce and gravity compensate each other.

-(void)didMoveToView:(SKView *)view {

  self.anchorPoint = CGPointMake(0.5, 0.5);

  SKShapeNode *node = [SKShapeNode shapeNodeWithRect:CGRectMake(0,0,WIDTH, HEIGHT)];
  node.position = CGPointMake(30, 280);
  node.strokeColor = [SKColor whiteColor];
  node.fillColor = [SKColor purpleColor];
  node.name = @"node";

  CGSize sz = node.frame.size;
  node.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sz center:[GameScene Center]];
  node.physicsBody.restitution = 0.3;
  node.physicsBody.mass = 1.0;
  node.physicsBody.affectedByGravity = YES;

  self.figure = node;

  [self addChild:node];

  self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
}


-(void)update:(CFTimeInterval)currentTime {

  [self.figure.physicsBody applyForce:CGVectorMake(
                                                 - self.physicsWorld.gravity.dx,
                                                 - self.physicsWorld.gravity.dy)];

However, the object falls down like it's effected by gravity only. I've checked the mass with a log it's always exactly 1.0

After some experiments, I've found out there is some magic number about it. It is 150. If use next update method the object is rested:

-(void)update:(CFTimeInterval)currentTime {

[self.figure.physicsBody applyForce:CGVectorMake(
                                                 - self.physicsWorld.gravity.dx,
                                                 -150 * self.physicsWorld.gravity.dy)];

And, another moment here, the mass is automatically calculated to be 1.0 if the body has dimensions 150*150. Anyway that wouldn't help. The behavior is same as we directly set the mass equal one.

If anyone knows what's going on here, please help!

2

2 Answers

2
votes

Let's say, there is 150 to 1 ratio of points to meters in SpriteKit. If we create a body of size 150*150 then the mass would be exactly one. Ok, that's good, we have a body of mass equals 1.0, we don't change it ourselves. BUT, next we again apply the force opposite to gravity and with the same magnitude. In this case the body will fall again. No good.

Alright, 150 / 1 is point-to-meter, and we need to multiply the force by 150 to balance the forces. We might start thinking "Hmm, there must be some clue in it". May be the gravity vector (0, -9.8) affects not kilos not meters but points! Alright then, let us have body of 150*150 points. To balance the forces we'll need (theoretically):

on one hand the force of gravity: 9.8 Newtons (kilo * meter) / sec ^ 2)

on another hand we applyForce: (1.0 kilo) * 9.8 * (150 points) / (sec^2)

So, here we miss the 150. Anyway,this seems to be little bit stupid, but applyForce is measured in ((points * kilo) / sec ^ 2), but the gravity acceleration is in Newtons ((kilo * meter)/ sec ^ 2) (despite the fact it's described as meters per second in documentation. Meters per second! Acceleration!). Multiply it by mass and get the force.

1
votes

You found the magic number :D

150 is the "pixel-to-meter" ratio in Sprite-kit. A particularly good explanation can be found here: look at the second answer by mitchellallison. When you access the gravity vector in your update: method you have keep this ratio in mind.