How to rotate sprites around a joint

若如初见. 提交于 2020-02-11 14:02:29

问题


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:

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:

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


回答1:


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.



来源:https://stackoverflow.com/questions/44294768/how-to-rotate-sprites-around-a-joint

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