How to make a force that doesn't accelerate objects constantly SpriteKit Swift

245 Views Asked by At

So I want to make a force that moves a physics object in the scene without accelerating them constantly. Just like in geometry dash. So when I use gravity it is like falling , but I don't want it to accelerate like that.

Hope you understood, this was a bit tricky to explain. Thank you

2

There are 2 best solutions below

1
On BEST ANSWER

In SKPhysicsBody terminology this is the difference between a force (constantly applied) and an impulse (instantaneously applied):

You can choose to apply either a force or an impulse:

  • A force is applied for a length of time based on the amount of simulation time that passes between when you apply the force and when the next frame of the simulation is processed. So, to apply a continuous force to an body, you need to make the appropriate method calls each time a new frame is processed. Forces are usually used for continuous effects

  • An impulse makes an instantaneous change to the body’s velocity that is independent of the amount of simulation time that has passed. Impulses are usually used for immediate changes to a body’s velocity.

(From 'Making Physics Bodies Move' from Apple documentation of SKPhysicsBody.)

So to apply an impulse to your body and thus avoid constant acceleration, use the method applyImpulse.

0
On

In your game scene, add a new jump() method that is called from touchesBegan. Use touchesBegan and touchesEnded to set a bool that tracks when you are touching the screen. You can use the didBegin method of your scene to keep track of when the player lands on the ground (or collides with obstacles, etc).

Something like this:

class GameScene: SKScene, SKPhysicsContactDelegate {
    var person = SKSpriteNode()
    var isJumping = Bool()
    var isTouching = Bool()

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        isTouching = true
        jump()
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        isTouching = false
    }

    func jump(){
        if isTouching == true {
            if isJumping == false {
                person.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 600))
                isJumping = true
            }
        }
    }

    func didBegin(_ contact: SKPhysicsContact) {
        let bodyA = contact.bodyA.node
        let bodyB = contact.bodyB.node

        // Collided with ground
        if bodyA?.physicsBody?.categoryBitMask == 2 && bodyB?.physicsBody?.categoryBitMask == 1 {
            isJumping = false
            jump()
        }
    }
}