0
votes

I'm trying to make a game where you control a platform by moving it left and right while trying to balance falling objects on top of it. However, it seems like the platform moves independently of the items that fall on top of it. For example, if a block falls on top of my platform, when I move the platform left or right, the block stays still and only the platform moves underneath it. This makes it impossible to stack anything since the blocks are not moving with the platform. I'm not sure what SpriteKit physics properties I need to use to simulate balancing. I tried fiddling with restitution for bounciness when the blocks collide with the platform, and friction property to see if that helps the blocks "stick" to the platform, but that doesn't seem to help either.

My platform wasn't dynamic, so I tried setting

platform.physicsBody!.isDynamic = true
platform.physicsBody!.affectedByGravity = false
platform.physicsBody!.allowsRotation = false

Which seems to help? but the platform still moves around when it collides with the blocks which I can't have.

EDIT:

This is how I'm moving the platform. The user moves the platforms parent by dragging it around with your finger. Since this moves the platforms parent, the platform moves with it.

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
         if let touch = touches.first {
              let location = touch.locationInNode(self)
              platformParent.position.x = location.x
         }
    }
2
Try this - once the falling block has finally settled, make it a child of the platform. Then it should move with the platform but still be subjected to the effects of other blocks falling in top of it. Alternatively, if when it settles on the platform it is 'stuck', use an SKPhysicsJoint to stick it in place. - Steve Ives

2 Answers

0
votes

You need to have the platform dynamic, so what you need to solve is how to keep it in place. There are many options with the correct one depending on your use case. Try looking at these:

  • Create a position constraint: SKConstraint.positionY
  • Create a sliding joint between the platform and a solid reference object: SKPhysicsJointSliding
  • Dramatically increase the mass of the platform relative to the objects falling on it
  • Correct the position of the platform, either manually each frame (helps if the mass allows it to keep relatively stationary) or using something like a spring joint
0
votes

Friction will prevent the blocks from sliding off the platform or other blocks (when stacked). Friction occurs when the friction coefficient property of a physics body is non-zero, a normal force exists (in this case F = mass x gravity), and at least one of the bodies is moved with a force or setting its velocity property. Friction will NOT work if you move the platform or blocks with an moveTo or moveBy action. The following is an example implementation of how to use friction in SpriteKit.

enter image description here

First, set the gravity property of the world. This is a default setting.

physicsWorld.gravity = CGVector(dx:0, dy:-9.8) 

Then, set the friction coefficient of the platform. Do the same for each block.

platform.physicsBody?.friction = 1.0

Set the mass property of the blocks to limit their weight.

block.physicsBody?.mass = 0.0001

Constraint the platform to prevent it from moving vertically from the weight of the blocks.

let range = SKRange(constantValue: -self.size.height * 0.45)
let constraint = SKConstraint.positionY(range)

platform.constraints = [constraint]

Lastly, move the platform side-to-side using physics:

var moveTo:CGPoint?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let point = touch.location(in:self)
        moveTo = point
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let point = touch.location(in:self)
        moveTo = point
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    moveTo = nil
    platform.physicsBody?.velocity = CGVector.zero
}

override func update(_ currentTime: TimeInterval) {
    if let moveTo = moveTo {
        let dx = moveTo.x - platform.position.x
        let vector = CGVector(dx: 2*dx, dy: 0)
        platform.physicsBody?.velocity = vector
    }
}