Scaling the pendulum with SKSpriteNodes

I have a working clock with a pendulum, but the swinging arm does not scale correctly. This is how it looks before scaling ...

enter image description here

And then, after scaling ...

enter image description here

The face with the clock shrinks, as does the swinging arm (green line), but it looks like it scales the center point around it, rather than the fulcrum in the center of the face. I can fix this scaling by setting swing anchorPoint

so that it scales towards one end, not center ...

swing.anchorPoint = CGPointMake(0, 0.5);

      

but this results in the pendulum not swinging. (I think because physical forces are applied to swing anchorPoint

, which, if I move it to one end, is at a fixed anchor, which is fixed).

How can I raise my arm to the fulcrum and still allow it to swing?

Here's the code ...

// in my SKScene
ClockFace *face = [ClockFace face]; // just an SKNode subclass
face.name = @"face";
face.position = CGPointMake(150, 150);
[self addChild:face];

// add the pendulum
SKSpriteNode *fulcrum = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(5, 5)];
[face addChild:fulcrum];
fulcrum.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:fulcrum.frame.size];
fulcrum.physicsBody.dynamic = NO;

SKSpriteNode *swing = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(190, 2)];
[face addChild:swing];
swing.position = CGPointMake(95, 0);
swing.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:swing.frame.size];

SKPhysicsJointPin *pinJoint = [SKPhysicsJointPin jointWithBodyA:fulcrum.physicsBody bodyB:swing.physicsBody anchor:face.position];
[self.physicsWorld addJoint:pinJoint];

      

+2


source to share


2 answers


The reason the scaling is strange is due to the way you snapping. Imagine a rubber band with a lettering. The anchor point is where the pointer is. Now scale. Just take a rubber band and pull. When the pointer is in the middle, it will be easy for you to stretch both sides evenly (this is what you do on the y-axis). When you place it to the left of the rubber band, you will only be able to scale the right side (this is what you want to do)

Now with the PhysicsBody, you need to adjust the body anchor point based on the point of the anchor sprites. To do this, you need to do some math:

let centerPoint = CGPointMake(sprite.size.width / 2 - (sprite.size.width * sprite.anchorPoint.x), sprite.size.height / 2 - (sprite.size.height * sprite.anchorPoint.y))
 sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size, center: centerPoint)

      



Using centerPoint allows you to move to where the center of your body is.

// in my SKScene
ClockFace *face = [ClockFace face]; // just an SKNode subclass
face.name = @"face";
face.position = CGPointMake(150, 150);
[self addChild:face];

// add the pendulum
SKSpriteNode *fulcrum = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(5, 5)];
[face addChild:fulcrum];
fulcrum.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:fulcrum.frame.size];
fulcrum.physicsBody.dynamic = NO;

SKSpriteNode *swing = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(190, 2)];
[face addChild:swing];
swing.anchorPoint = CGPointMake(0,0.5);
CGPoint *centerPoint = CGPointMake(swing.size.width / 2 - (swing.size.width * swing.anchorPoint.x), swing.size.height / 2 - (swing.size.height * swing.anchorPoint.y));

swing.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:swing.frame.size center:centerPoint];

SKPhysicsJointPin *pinJoint = [SKPhysicsJointPin jointWithBodyA:fulcrum.physicsBody bodyB:swing.physicsBody anchor:face.position];
[self.physicsWorld addJoint:pinJoint];

      

+1


source


In the Swift 3 example:

enter image description here



    let nodeSize = CGSize(width: 10, height: 10)
    let node = SKSpriteNode(color: .red, size: nodeSize)
    node.physicsBody = SKPhysicsBody(rectangleOf: nodeSize)
    node.physicsBody?.isDynamic = false
    self.addChild(node)

    let node2Size = CGSize(width: 60, height: 8)
    let node2 = SKSpriteNode(color: .green, size: node2Size)
    node2.position = CGPoint(x: 5, y: 0)
    node2.anchorPoint = CGPoint(x: 0.0, y: 0.5) // <- New Line
    node2.physicsBody = SKPhysicsBody(rectangleOf: node2Size)
    node2.physicsBody?.mass = 1.0
    self.addChild(node2)

    // Scale Line
    node2.run(SKAction.repeatForever(SKAction.sequence([
        SKAction.scale(to: 0.2, duration: 1.0),
        SKAction.scale(to: 1.5, duration: 0.5),
        ])))
// Anchor Point
        let a = SKPhysicsJointPin.joint(withBodyA: node.physicsBody! , bodyB: node2.physicsBody!, anchor: CGPoint(x: 0.0, y: 0.0))
            self.physicsWorld.add(a)

      

+3


source







All Articles