user6361496
user6361496

Reputation:

Spritekit & Swift 3 - Change ball node speed after collision

I use the didBegin(contact) together with bitmasks to determine what node is colliding with what. I set my initial ball speed using the applyImpulse(). My code for this is:

                    let minAngle : UInt32 = 181
                    let maxAngle : UInt32 = 359
                    let randomAngle = arc4random_uniform(maxAngle - minAngle) + minAngle
                    let dx:CGFloat = 3 * cos(CGFloat(randomAngle))
                    let dy:CGFloat = 3 * sin(CGFloat(randomAngle))
                    ball.physicsBody?.applyImpulse(CGVector(dx: dx, dy: dy))

My didBegin(contact) method code is:

func didBegin(_ contact: SKPhysicsContact) {
    var firstBody = SKPhysicsBody()
    var secondBody = SKPhysicsBody()
    let ballNode = self.childNode(withName: ballName)

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    if firstBody.categoryBitMask == ballBitmask && secondBody.categoryBitMask == drainBitmask {
        endGame()
        Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(GameScene.showLeaderboard), userInfo: nil, repeats: false)

    } else if firstBody.categoryBitMask == ballBitmask && secondBody.categoryBitMask == target1Bitmask {
        score += 20
        self.vc.scoreLabel.text = "Score: \(score)"



    } else if firstBody.categoryBitMask == ballBitmask && secondBody.categoryBitMask == target2Bitmask {
        score += 10
        self.vc.scoreLabel.text = "Score: \(score)"


    } else if firstBody.categoryBitMask == ballBitmask && secondBody.categoryBitMask == target3Bitmask {
        score += 30
        self.vc.scoreLabel.text = "Score: \(score)"


    }

However when my ball collides with either target 1,2 or 3 the ball speed must be changed. For example when the ball collides with target 1 I need the ball speed to double. For what I understand when you applyImpulse to a ball the dx and dy values represent both the direction and speed so how can I double the ball speed whilst still keeping the realistic bounce effect which happens in collision? FYI the speed that must be doubled is the ball speed in the moment of the collision.

EDIT - EXTENSION

extension CGVector {
var speed: CGFloat {
    return hypot(dx, dy)
}

static func > (lhs: CGVector, rhs: CGVector) -> Bool {
    return lhs.speed > rhs.speed
}

static func < (lhs: CGVector, rhs: CGVector) -> Bool {
    return lhs.speed < rhs.speed
}

static func * (vector: CGVector, scalar: CGFloat) -> CGVector {

    return CGVector(dx: vector.dx * scalar, dy: vector.dy * scalar)
}

}

Thanks

Upvotes: 2

Views: 588

Answers (1)

Confused
Confused

Reputation: 6278

In the SpriteKit gameloop there are many "udpate" style functions you can put code into.

You can leave your physics behaving as it normally does, just let it do its thing.

Then, in a later update, after the physics is done - eg. didSimulatePhysics() which is called right after the system calculates all the physics do the required modifications to the ball's speed.

In didSimulatePhysics you can have some flags that look at what was the event that just took place. In the case of having just hit ball target 1, you can now double the velocity of the ball, and this will be calculated before the ball is rendered.

If the ball hit target 2, maybe halve the velocity, etc.

Upvotes: 1

Related Questions