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

    }

Respuestas a la pregunta(1)

Su respuesta a la pregunta