Scaling a pendulum made with SKSpriteNodes

社会主义新天地 提交于 2019-12-11 04:05:55

问题


I've got a working clock with a pendulum, but the swinging arm does not scale correctly. Here's what it looks like before scaling...

And then, after scaling...

The clock face scales down, and so does the swing arm (the green line), but it looks like it scales around it's center point not the fulcrum at the center of the face. I can fix that scaling by setting the swing's anchorPoint so it scales toward one end rather than the center...

swing.anchorPoint = CGPointMake(0, 0.5);

but doing that causes the pendulum to not swing. (I think because physics forces are applied to swing's anchorPoint which, if I move it to one end, is at the pin anchor which is fixed).

How can I get the arm to scale towards 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];

回答1:


The reason why the scaling is weird is because of how you do your anchor point. Imagine a rubber band with a thumbtack in it. The anchor point is where the thumbtack is. Now to scale. Just grab the rubber band and pull. When the thumbtack is the middle, you will find it easy to stretch both sides evenly (this is what you are doing on the y axis). When you place it on the left of the rubber band, you will only be able to scale the right side (This is what you want to be doing)

Now with PhysicsBody, you need to adjust the bodies anchor point based on the sprites anchor point. 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 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];



回答2:


In Swift 3 example of this:

    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)


来源:https://stackoverflow.com/questions/45259118/scaling-a-pendulum-made-with-skspritenodes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!