Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.9k views
in Technique[技术] by (71.8m points)

swift - How to rotate sprites around a joint

I need to make the arms and hands rotate around the center of the hook, as shown in the image below without them separating or changing their shape (no changes in the angles between arms and hands just rotation at A), as in the image below:

enter image description here

I tried rotating the arms but this made them separate and change form. You can check out my code below:

let hookCategoryName = "hook"
let leftArmCategoryName = "leftArm"
let rightArmCategoryName = "rightArm"
let leftHandCategoryName = "leftHand"
let rightHandCategoryName = "rightHand"

let hookCategory             : UInt32 = 0x1 << 0
let leftArmCategory            : UInt32 = 0x1 << 1
let rightArmCategory           : UInt32 = 0x1 << 2
let leftHandCategory           : UInt32 = 0x1 << 3
let rightHandCategory          : UInt32 = 0x1 << 4

extension Int {
  var degreesToRadians: Double { return Double(self) * .pi / 180 }
}
extension FloatingPoint {
  var degreesToRadians: Self { return self * .pi / 180 }
  var radiansToDegrees: Self { return self * 180 / .pi }
}

class GameScene: SKScene, SKPhysicsContactDelegate {

var hook = SKSpriteNode(imageNamed: "hook")
var leftArm = SKSpriteNode(imageNamed: "arm")
var rightArm = SKSpriteNode(imageNamed: "arm")
var leftHand = SKSpriteNode(imageNamed: "leftHand")
var rightHand = SKSpriteNode(imageNamed: "rightHand")

override func didMove(to view: SKView) {

    self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
    self.physicsWorld.contactDelegate = self

    var yellowBg = SKSpriteNode(imageNamed: "yellowBg")
    yellowBg.position = CGPoint(x: frame.midX, y: frame.midY)
    yellowBg.zPosition = 2
    addChild(yellowBg)

    hook.position = CGPoint(x: frame.midX, y: frame.midY + frame.midY/2)
    hook.zPosition = 5
    hook.name = hookCategoryName
    hook.physicsBody = SKPhysicsBody(rectangleOf: hook.frame.size)
    hook.physicsBody?.categoryBitMask = hookCategory
    hook.physicsBody?.isDynamic = false
    addChild(hook)

    rightArm.anchorPoint = CGPoint(x: 0.5, y: 1)
    rightArm.position = hook.position
    rightArm.zPosition = 5
    rightArm.name = rightArmCategoryName
    rightArm.physicsBody = SKPhysicsBody(rectangleOf: rightArm.frame.size)
    rightArm.physicsBody?.categoryBitMask = rightArmCategory

    rightArm.physicsBody!.isDynamic = true
    addChild(rightArm)

    leftArm.anchorPoint = CGPoint(x: 0.5, y: 1)
    leftArm.position = hook.position
    leftArm.zPosition = 5
    leftArm.name = leftArmCategoryName
    leftArm.physicsBody = SKPhysicsBody(rectangleOf: leftArm.frame.size)
    leftArm.physicsBody?.categoryBitMask = leftArmCategory
    leftArm.physicsBody!.isDynamic = true

    addChild(leftArm)

    // leftHand
    leftHand.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    leftHand.position = CGPoint(x: leftArm.frame.minX - 22, y: leftArm.frame.minY + 7) //CGPoint(x: armLeft.position.x, y: armLeft.position.y)
    leftHand.zPosition = 5
    leftHand.name = leftHandCategoryName
    leftHand.physicsBody = SKPhysicsBody(rectangleOf: leftHand.frame.size)
    leftHand.physicsBody?.categoryBitMask = leftHandCategory

    leftHand.zRotation = CGFloat(Double(-30).degreesToRadians)//CGFloat(-Double.pi/6)
    //armLeft.physicsBody?.categoryBitMask = armCategory
    leftHand.physicsBody!.isDynamic = true

    addChild(leftHand)

    // rightHand
    rightHand.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    rightHand.position = CGPoint(x: rightArm.frame.minX + 30, y: rightArm.frame.minY + 7) //CGPoint(x: armLeft.position.x, y: armLeft.position.y)
    rightHand.zPosition = 5
    rightHand.name = rightHandCategoryName

    rightHand.physicsBody = SKPhysicsBody(rectangleOf: rightHand.frame.size)
    rightHand.physicsBody?.categoryBitMask = rightHandCategory
    rightHand.zRotation = CGFloat(Double(30).degreesToRadians)//CGFloat(-Double.pi/6)
    //armLeft.physicsBody?.categoryBitMask = armCategory
    rightHand.physicsBody!.isDynamic = true

    addChild(rightHand)


    leftArm.zRotation = CGFloat(Double(-45).degreesToRadians)
    rightArm.zRotation = CGFloat(Double(45).degreesToRadians)

    rightHand.physicsBody?.contactTestBitMask = rightHandCategory
    leftHand.physicsBody?.contactTestBitMask = leftHandCategory
    rightHand.physicsBody?.collisionBitMask = rightHandCategory
    leftHand.physicsBody?.collisionBitMask = leftHandCategory


    let hookAndRightArmJoint = SKPhysicsJointPin.joint(withBodyA: hook.physicsBody!, bodyB: rightArm.physicsBody!, anchor: CGPoint(x: hook.position.x, y: self.rightArm.frame.maxY))
    self.physicsWorld.add(hookAndRightArmJoint)

    let hookAndLeftArmJoint = SKPhysicsJointPin.joint(withBodyA: hook.physicsBody!, bodyB: leftArm.physicsBody!, anchor: CGPoint(x: hook.position.x, y: self.leftArm.frame.maxY))
    self.physicsWorld.add(hookAndLeftArmJoint)


    let armsFixedJoint = SKPhysicsJointFixed.joint(withBodyA: leftArm.physicsBody!, bodyB: rightArm.physicsBody!, anchor: CGPoint.zero)
    self.physicsWorld.add(armsFixedJoint)

    //left arm and hand joint
    let leftArmAndHandJoint = SKPhysicsJointPin.joint(withBodyA: leftArm.physicsBody!, bodyB: leftHand.physicsBody!, anchor: CGPoint(x: self.leftArm.frame.minX, y: self.leftArm.frame.minY)/*CGPoint(x: armLeft.position.x, y: self.armLeft.frame.minY)*/)
    self.physicsWorld.add(leftArmAndHandJoint)

    //right arm and hand joint
    let rightArmAndHandJoint = SKPhysicsJointPin.joint(withBodyA: rightArm.physicsBody!, bodyB: rightHand.physicsBody!, anchor: CGPoint(x: self.rightArm.frame.maxX, y: self.rightArm.frame.minY)/*CGPoint(x: armLeft.position.x, y: self.armLeft.frame.minY)*/)
    self.physicsWorld.add(rightArmAndHandJoint)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    hook.run(SKAction.rotate(byAngle: CGFloat(Double(60).degreesToRadians), duration: 0.5))

}
}  

Also rotating the hook has no effect on the arms and hands as seen in the image below when the above code is run:

enter image description here

How can I get the rotation in the image first image?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can make the arms and hands children of a common parent node. You could create a blank SKNode for just this purpose like so:

let armsParent = SKNode()

Then instead of adding the arms and hands as children to the scene directly, add them as children of armsParent like so:

armsParent.addChild(leftArm)
armsParent.addChild(rightArm) // same for hands...

Then you can simply rotate armsParent with an SKAction to achieve what you want.

OR, to make it even simpler, you could just add the arms and hands as children to hook directly like this:

hook.addChild(leftArm) // same for other arm and hands...

Since the arms and hands are children of hook or armParent their positions will now be determined relative to their parent. So you might have to change all your .position = initialization code to accommodate this.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...