Search code examples
iosswiftxcodesprite-kitskspritenode

SpriteKit/Swift - Binary Operator '>' cannot be applied to two 'CGVector' operands


In my game I need to compare the 2 speeds upon a collision. Both speeds are in the CGVector(dx: , dy:) format. However Swift 3 doesn't let me use the '>' and '<' operands to compare them. How can I solve this? Code is as follows:

func didBegin(_ contact: SKPhysicsContact) {
    var firstBody = SKPhysicsBody()
    var secondBody = SKPhysicsBody()
    let ballNode = self.childNode(withName: ballName)
    let defaultSpeedX:CGFloat = 100
    let defaultSpeedY:CGFloat = -100
    let maxSpeed = CGVector(dx: defaultSpeedX * 3, dy: defaultSpeedY * 3)
    let minSpeed = CGVector(dx: defaultSpeedX / 2 , dy: defaultSpeedY / 2)

    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()

    } else if firstBody.categoryBitMask == ballBitmask && secondBody.categoryBitMask == target1Bitmask {
        score += 20
        self.vc.scoreLabel.text = "Score: \(score)"
        let currentSpeedX = ballNode?.physicsBody?.velocity.dx
        let currentSpeedY = ballNode?.physicsBody?.velocity.dy
        let speedDouble = CGVector(dx: currentSpeedX! * 2, dy: currentSpeedY! * 2)

        if ballNode?.physicsBody?.velocity == maxSpeed {

            ballNode?.physicsBody?.velocity = maxSpeed

        } else if speedDouble < maxSpeed {

            ballNode?.physicsBody?.velocity = speedDouble

        } else if speedDouble > maxSpeed {

            ballNode?.physicsBody?.velocity = maxSpeed

        }

Thanks


Solution

  • The "speed" of the vector is actually the hypotenuse of the triangle your vector describes. Try this:

    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
        }
    }
    
    let aaa = CGVector(dx: 10, dy: 10)
    let bbb = CGVector(dx: 13, dy: 12)
    
    print(aaa > bbb)
    

    With this extension in place, you'll find your existing code, } else if speedDouble < maxSpeed {, will compile.

    How does it work? Well, your speed as a vector is defined with two components - a horizontal speed, dx, and a vertical speed, dy. If you imagine dx and dy as the two side of a right angled triangle, the length of the vector is the hypotenuse (remember Pythagorus) - that's what hypot returns.

    With the extension above, the < and > operators now compare a CGVector object's speed (which you could happily rename length).