Antonio C
Antonio C

Reputation: 71

Swift/SpriteKit - Ball node downwards angle of release

I need the ball node to be be initially released in my game in a downwards angle (which is randomly generated each time). I found out the velocity of the ball includes both the direction and speed (please correct me if this is wrong) therefore I generated a random angle and multiplied this by a value such as '0.5' to represent the impulse/speed. My code for this can be seen below:

let minAngle : UInt32 = 181
let maxAngle : UInt32 = 359
let randomAngle = arc4random_uniform(maxAngle - minAngle) + minAngle
let dx:CGFloat = 0.5 * CGFloat(randomAngle)
let dy:CGFloat = 0.5 * CGFloat(randomAngle)

ball.physicsBody?.velocity = CGVector(dx: dx, dy: dy)

However I realised this isn't working as the ball goes in upwards direction. Is my range in-correct or is my method of doing so incorrect? If it is my method how could I guarantee that the ball always is released in a downwards angle (I must also add a speed to the ball)?

Thanks

Upvotes: 3

Views: 222

Answers (2)

hamobi
hamobi

Reputation: 8130

spritekit works using radians not degrees. better to learn to think in terms of radians rather than degrees since that's what you'll be using. If you want to continue using degrees you can use this kind of formula.

func convertToRadians(degrees: Int) -> CGFloat {
    return CGFloat(M_PI) * CGFloat(degrees) / 180
}

let minAngle = convertToRadians(degrees: 181)
let maxAngle = convertToRadians(degrees: 359)

another way of calculating it

let minAngle = CGFloat(Measurement(value: 181, unit: UnitAngle.degrees).converted(to: .radians).value)
let maxAngle = CGFloat(Measurement(value: 359, unit: UnitAngle.degrees).converted(to: .radians).value)

get a random angle in radians between two sets of degrees

func random() -> CGFloat {
    return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}

func randomDegreesToRadians(min: CGFloat, max: CGFloat) -> CGFloat {
    assert(min < max)
    let randomDegrees = random() * (max - min) + min
    return CGFloat(M_PI) * CGFloat(randomDegrees) / 180
}


randomDegreesToRadians(min: 100, max: 200)

Upvotes: 1

Knight0fDragon
Knight0fDragon

Reputation: 16827

You need to use SIN COS and ATAN on angles to get where you are going.

If you know your angle and speed, you use SIN and COS:

extension Int {
    var degreesToRadians: Double { return Double(self) * .pi / 180 }
    var radiansToDegrees: Double { return Double(self) * 180 / .pi }
}
extension FloatingPoint {
    var degreesToRadians: Self { return self * .pi / 180 }
    var radiansToDegrees: Self { return self * 180 / .pi }
}

credit to Leo Dabus How can I convert from degrees to radians?

let minAngle = 181.degreesToRadans
let maxAngle = 359.degreesToRadans
let randomAngle = arc4random_uniform(maxAngle - minAngle) + minAngle
let dx:CGFloat = 0.5 * cos(CGFloat(randomAngle))
let dy:CGFloat = 0.5 * sin(CGFloat(randomAngle))

ball.physicsBody?.velocity = CGVector(dx: dx, dy: dy)

If you only know 2 points, and need to get the angle, you use arctan2: (We need to make point1 our origin, so we subtract point2 from point1)

   let point1 = CGPoint(x:0,y:1)
   let point2 = CGPoint(x:0,y:2)
   let distancePoint = CGPoint(x:point2.x - point1.x, y:point2.y - point1.y)
   let angle = atan2(distancePoint.y,distancePoint.x)

Upvotes: 1

Related Questions