0

I have a ios 9 spritekit game. I am adding a i-beam or a wrecking ball that should swing from a jointed rope like a pendulum. My game requires gravity and I want the beam to react to gravity and sprites that jump on the beam or hit the beam from below. When I use the following code, the beam eventually slows down and comes to rest without any interaction with other sprites. The top node in the jointed node is fixed (i.e., modeling attachment to a crane or building) I start the beam swinging by applying an impulse on the bottom node in the jointed node. I have set the friction, linear dampening, and angular dampening to 0.

What I need the beam to do prior to interacting with any sprites is to swing back and forth where the maximum height on the left swing and right swing is nearly the same throughout time. I want the beam or wrecking ball to act like its swinging from a frictionless pivot. The beam or ball doesn't go in a full circle, so I cannot use a constant angular velocity.

I tried something similar to: Constant speed orbit around point with SKNode but neither the linear nor angular velocity is constant after the initial impulse as the beam or ball will arc up, slow down, stop at the top of the arc, and then circle back in the other direction.

  let (actionSceneObjectNode, jointArray) = ActionSceneObject.createActionJointedSceneObjectAtPosition(CGPoint(x: positionX, y: positionY), ofType: actionSceneObject.type!, withImage: actionSceneObject.imageName, withActionDirection: actionSceneObject.imageDirection)
     foregroundNode.addChild(actionSceneObjectNode)
     if let bottomNode = actionSceneObjectNode.childNodeWithName("bottomObject") {
     bottomNode.physicsBody?.applyImpulse(CGVector(dx: 50000.0, dy: 0))
  }

  // add the joints
  for joint in jointArray {
     self.physicsWorld.addJoint(joint)
  }

Function

  class func createActionJointedSceneObjectAtPosition(position: CGPoint, ofType type: ActionSceneObjectType, withImage imageName: String, withActionDirection actionDirection: DirectionValue) -> (ActionSceneObjectNode, [SKPhysicsJoint]) {
    let node = ActionSceneObjectNode()
    node.position = position
    node.name = SceneObjectType.Action.rawValue
    node.actionType = type
    node.actionDirection = actionDirection

    var jointArray = [SKPhysicsJoint]()

    var sprite: SKSpriteNode

    ////////
    // adapted from https://stackoverflow.com/questions/20811931/how-to-create-a-rope-in-spritekit

    let countJointElements:Int = 3

    let texture = SKTexture(imageNamed: "Rope.png")
    //let textureSize = CGSize(width: texture.size().width*SceneObjectSizeScale.ActionSceneObject, height: texture.size().height*SceneObjectSizeScale.ActionSceneObject)

    let topAnchor = SKSpriteNode(texture: texture, size: texture.size())
    topAnchor.name = "topAnchor"
    //topAnchor.position = CGPointMake(position.x, position.y) // the node holds the joint start position
    topAnchor.physicsBody = SKPhysicsBody(rectangleOfSize: texture.size())
    topAnchor.physicsBody?.categoryBitMask = PhysicsCategoryBitmask.None
    topAnchor.physicsBody?.affectedByGravity = false
    topAnchor.physicsBody?.friction = 0.0
    topAnchor.physicsBody?.restitution = 1.0
    topAnchor.physicsBody?.linearDamping = 0.0
    topAnchor.physicsBody?.angularDamping = 0.0
    topAnchor.physicsBody?.mass = 10.0
    node.addChild(topAnchor)

    // by default, the joints build top to bottom
    for index in 0 ..< countJointElements {

        let item = SKSpriteNode(texture: texture, size: texture.size())
        item.name = "ropeitem_" + String(index)
        item.position = CGPointMake(0, 0 - CGFloat(index+1) * item.size.height)
        item.physicsBody = SKPhysicsBody(rectangleOfSize: texture.size())
        item.physicsBody?.categoryBitMask = PhysicsCategoryBitmask.None
        item.physicsBody?.affectedByGravity = true
        item.physicsBody?.friction = 0.0
        item.physicsBody?.restitution = 1.0
        item.physicsBody?.linearDamping = 0.0
        item.physicsBody?.angularDamping = 0.0
        item.physicsBody?.mass = 10.0
        node.addChild(item)

        var bodyA = SKPhysicsBody()

        if (index == 0)
        {
            bodyA = topAnchor.physicsBody!;
        }
        else
        {
            let nameString = "ropeitem_" + String(index - 1)
            let nodeItem = node.childNodeWithName(nameString) as! SKSpriteNode
            bodyA = nodeItem.physicsBody!
        }

        // needs to in terms of the physics world - the item position in the node is already negative
        let joint = SKPhysicsJointPin.jointWithBodyA(bodyA, bodyB: item.physicsBody!, anchor: CGPointMake(position.x, position.y + item.position.y + item.size.height/2))
        jointArray.append(joint)
    }

    let nameString = NSString(format: "ropeitem_%d", countJointElements - 1)
    let lastLinkItem = node.childNodeWithName(nameString as String)

    let bottomObject = SKSpriteNode(imageNamed: "I-Beam.png")
    bottomObject.name = "bottomObject"
    bottomObject.setScale(SceneObjectSizeScale.Platform)
    bottomObject.position = CGPointMake(0, 0 + lastLinkItem!.position.y - lastLinkItem!.frame.size.height/2.0 - bottomObject.frame.size.height/2.0)
    bottomObject.physicsBody = SKPhysicsBody(rectangleOfSize: bottomObject.size)
    bottomObject.physicsBody?.categoryBitMask = PhysicsCategoryBitmask.Platform
    bottomObject.physicsBody?.affectedByGravity = true
    bottomObject.physicsBody?.friction = 0.0
    //bottomObject.physicsBody?.restitution = 1.0
    bottomObject.physicsBody?.linearDamping = 0.0
    bottomObject.physicsBody?.angularDamping = 0.0
    bottomObject.physicsBody?.mass = 500.0
    node.addChild(bottomObject)

    let jointLast = SKPhysicsJointFixed.jointWithBodyA(lastLinkItem!.physicsBody!, bodyB: bottomObject.physicsBody!, anchor: CGPointMake(position.x, position.y + bottomObject.position.y + bottomObject.frame.size.height/2.0))

    jointArray.append(jointLast)

    ///////
    ///////
    sprite = SKSpriteNode(imageNamed: imageName)
    //sprite.setScale(SceneObjectSizeScale.ActionSceneObject)
    node.sprite = sprite

    //node.addChild(sprite)

    node.physicsBody = SKPhysicsBody(texture: texture, size: sprite.size)
    node.physicsBody!.categoryBitMask = PhysicsCategoryBitmask.None

    switch actionDirection {
    case .Left:
        node.sprite.zRotation = CGFloat(M_PI_2)
    case .Right:
        node.sprite.zRotation = CGFloat(-M_PI_2)
    case .Down:
        node.sprite.zRotation = CGFloat(M_PI)
    case .Up, .Unknown:
        break
    }

    node.physicsBody?.dynamic = true
    node.physicsBody?.restitution = 0.0 // bounciness
    node.physicsBody?.categoryBitMask = PhysicsCategoryBitmask.ActionSceneObject
    node.physicsBody?.collisionBitMask = 0

    return (node, jointArray)
}
Community
  • 1
  • 1
Jacksonsox
  • 1,114
  • 15
  • 25
  • Possible duplicate of [Constant speed orbit around point with SKNode](http://stackoverflow.com/questions/28786940/constant-speed-orbit-around-point-with-sknode) –  May 21 '16 at 19:43
  • Thanks for the link. The way my original question looked, the question did appear to be a duplicate. I have adjusted the question to explain the difference from the commented possible duplicate. – Jacksonsox May 24 '16 at 01:33

0 Answers0