I want to build a Brick game. I have a ball which want to shoot it in direction of drew line.
Here is how I shoot the ball:
let ang = angle(between: balls.first!.position, ending: CGPoint(x: guideLine.frame.maxX, y: guideLine.frame.maxY))
let force = CGVector(dx:cos(ang) * gameSpeed, dy:sin(ang) * gameSpeed)
for i in 0..<balls.count {
DispatchQueue.main.asyncAfter(deadline: .now() + Double(i) * 0.1) {
if !balls.isEmpty {
balls[i].physicsBody!.applyImpulse(force)
}
}
}
Here is my 'angle' function which converts the two positions to an angle:
func angle(between starting: CGPoint, ending: CGPoint) -> CGFloat {
let center = CGPoint(x: ending.x - starting.x, y: ending.y - starting.y)
let radians = atan2(center.y, center.x)
let degrees = GLKMathRadiansToDegrees(Float(radians))
return degrees > 0 ? CGFloat(degrees) : CGFloat(degrees + degrees)
}
As you see I get the start point of the line from wher the ball is located & get the end of the line from the line maxX & maxY itself... I'm not sure its the proper way though...
The result is very weird! The ball goes to any direction it wants to, each time is different (sometimes next to my lines & sometimes very far), I can't figure it out.
Here are screenshots:
You're computing an angle in degrees, then passing it to sin
and cos
which expect radians. That's likely your main issue.
Regarding other things, it's not clear what the purpose of all the degrees > 0
stuff is. Also, it's probably better in SpriteKit to stick with the various SKAction
s for things like running stuff after a delay rather than to sprinkle in DispatchQueue
stuff. The latter will not interact correctly with SpriteKit's facilities for pausing, changing node speeds, etc.
let ang = angle(between: balls.first!.position, ending: CGPoint(x: guideLine.frame.maxX, y: guideLine.frame.maxY))
let actions = [SKAction]()
let force = CGVector(dx:cos(ang) * gameSpeed, dy:sin(ang) * gameSpeed)
let wait = SKAction.wait(forDuration:0.1)
for ball in balls {
let action = SKAction.run{
ball.physicsBody!.applyImpulse(force)
}
actions.append(wait)
actions.append(action)
}
run(SKAction.sequence(actions))
func angle(between starting: CGPoint, ending: CGPoint) -> CGFloat {
let relativeToStart = CGPoint(x: ending.x - starting.x, y: ending.y - starting.y)
let radians = atan2(relativeToStart.y, relativeToStart.x)
//let degrees = GLKMathRadiansToDegrees(Float(radians))
return radians > 0 ? (radians : (.pi * 2) + radians)
}