Bounce rays con enumerateBodies alongRayStart
Quiero rastrear el camino donde se moverá una bala en mi SpriteKit GameScene. Estoy usando "enumerateBodies (alongRayStart", puedo calcular fácilmente la primera colisión con un cuerpo de física.
No sé cómo calcular el ángulo de reflexión, dado el punto de contacto y el contacto normal.
Quiero calcular la ruta, más de 5 reflexiones / rebotes, así que primero:
che un rayo, obtenga todos los cuerpos con los que se cruza y obtenga el más cercano. Luego uso ese punto de contacto como el comienzo de mi próximo reflejo / rebote ... pero estoy luchando con lo que el punto final debe establecerse en ...Lo que yopensa Lo que debería hacer es obtener el ángulo entre el punto de contacto y el contacto normal, y luego calcular un nuevo punto opuesto a ese ...
var points: [CGPoint] = []
var start: CGPoint = renderComponent.node.position
var end: CGPoint = crossHairComponent.node.position
points.append(start)
var closestNormal: CGVector = .zero
for i in 0...5 {
closestNormal = .zero
var closestLength: CGFloat? = nil
var closestContact: CGPoint!
// Get the closest contact point.
self.physicsWorld.enumerateBodies(alongRayStart: start, end: end) { (physicsBody, contactPoint, contactNormal, stop) in
let len = start.distance(point: contactPoint)
if closestContact == nil {
closestNormal = contactNormal
closestLength = len
closestContact = contactPoint
} else {
if len <= closestLength! {
closestLength = len
closestNormal = contactNormal
closestContact = contactPoint
}
}
}
// This is where the code is just plain wrong and my math fails me.
if closestContact != nil {
// Calculate intersection angle...doesn't seem right?
let v1: CGVector = (end - start).normalized().toCGVector()
let v2: CGVector = closestNormal.normalized()
var angle = acos(v1.dot(v2)) * (180 / .pi)
let v1perp = CGVector(dx: -v1.dy, dy: v1.dx)
if(v2.dot(v1perp) > 0) {
angle = 360.0 - angle
}
angle = angle.degreesToRadians
// Set the new start point
start = closestContact
// Calculate a new end point somewhere in the distance to cast a ray to, so we can repeat the process again
let x = closestContact.x + cos(angle)*100
let y = closestContact.y + sin(-angle)*100
end = CGPoint(x: x, y: y)
// Add points to array to draw them on the screen
points.append(closestContact)
points.append(end)
}
}