Operator precedence in Swift
The SKActions to move all take a duration argument. To ensure that the rate of the move remains the same even if the distance is different, the duration must be computed:
That's an awful lot of code to write for such a simple operation! To alleviate this, I extended CGVector to include a 'magnitude' variable:
The constant-rate move action could then be created much more simply:
SKAction.moveBy(myVector, duration: NSTimeInterval(myVector.magnitude/1_000))
All seemed to be going well, but I soon noticed a bug in the magnitude:
My assumption had been that I had extended the exponentiation operator to work with CGFloats. However, the Swift Language Reference states that ^ is actually the bitwise XOR operator and has the same precedence as the addition operator. So the expression (dx^2 + dy^2) was actually parsed from left to right, resulting in the equivalent of (((dx^2) + dy)^2)! So dx was squared twice.
The solution? Rather than trying to make the bitwise XOR work as an exponentiation operator, I could just use the power function directly:
Update: Another alternative that was suggested to me was to just use dx * dx instead of pow(dx, 2).
SKAction.moveBy(myVector, duration: NSTimeInterval(sqrt(myVector.dx*myVector.dx + myVector.dy*myVector.dy)/1_000))
That's an awful lot of code to write for such a simple operation! To alleviate this, I extended CGVector to include a 'magnitude' variable:
extension CGVector {
static func from(start: CGPoint, to end: CGPoint) -> CGVector {
return CGVector(dx: end.x-start.x, dy: end.y-start.y)
}
var magnitude: CGFloat {
return sqrt(dx^2 + dy^2)
}
}
The constant-rate move action could then be created much more simply:
SKAction.moveBy(myVector, duration: NSTimeInterval(myVector.magnitude/1_000))
All seemed to be going well, but I soon noticed a bug in the magnitude:
CGVector(dx: 0, dy: 200).magnitude //returns 200, as expected
CGVector(dx: 200, dy: 0).magnitude //returns 4000 unexpectedly
The source of this bug was actually the ^ function, which I had defined myself:
func ^ (lhs: CGFloat, rhs: CGFloat) -> CGFloat {
return pow(lhs, rhs)
}
The solution? Rather than trying to make the bitwise XOR work as an exponentiation operator, I could just use the power function directly:
sqrt(pow(dx, 2) + pow(dy, 2))
The result:
sqrt(dx*dx + dy*dy)
Comments
Post a Comment