How to rotate sprites around a joint
Asked Answered
C

1

8

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?

Cynde answered 31/5, 2017 at 21:12 Comment(0)
F
0

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.

Fogged answered 1/6, 2017 at 1:9 Comment(4)
how am I now suppose to create and add joints? In the code in my question I did it in the following way let hookAndRightArmJoint = SKPhysicsJointPin.joint(withBodyA: hook.physicsBody!, bodyB: rightArm.physicsBody!, anchor: CGPoint(x: hook.position.x, y: rightArm.frame.maxY)) self.physicsWorld.add(hookAndRightArmJoint) I am not sure how this is to be done now.Cynde
I added the armsParent in the following way var armsParent = SKNode() armsParent.position = hook.position armsParent.zPosition = 10 addChild(armsParent) and also run the following SKAction on it armsParent.run(SKAction.rotate(byAngle: CGFloat(Double(60).degreesToRadians), duration: 0.5)) but it didn't rotate.Cynde
I finally got it working, by making a new sprite and adding arms and hands as children. But this has brought another problem. The hands can't rotate independently in both directions any longer. I was opening the hands using the following code at first, but it's not working now. rightHand.run(SKAction.rotate(byAngle: CGFloat(Double(30).degreesToRadians), duration: 0.5)) leftHand.run(SKAction.rotate(byAngle: CGFloat(Double(-30).degreesToRadians), duration: 0.5))Cynde
Check out my answer to a suspiciously similar question here. Looks like you guys might be working on the same class project! But the rotatePendulum... function I wrote might be exactly what you are looking for.Fogged

© 2022 - 2024 — McMap. All rights reserved.