我想在我的SpriteKit GameScene中跟踪子弹路径。
我正在使用“enumerateBodies(alongRayStart”,可以轻松计算与物理体的第一次碰撞。
我不知道如何计算反射角度,给定接触点和接触法线。
我想计算5次反射/弹跳后的路径,所以首先:
我不知道如何计算反射角度,给定接触点和接触法线。
我想计算5次反射/弹跳后的路径,所以首先:
- 投掷光线,获取其相交的所有物体,并获取最近的一个。
- 然后将该接触点用作下一个反射/弹跳的起点...但我在确定终点时遇到了困难...
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)
}
}