使用 SceneKit 的台球游戏中的后旋效果
Posted
技术标签:
【中文标题】使用 SceneKit 的台球游戏中的后旋效果【英文标题】:Backspin effect in pool game with SceneKit 【发布时间】:2016-06-11 20:07:51 【问题描述】:我想创建一个逼真的台球游戏并至少实现一些基本的球效果。我从头开始使用 SceneKit,此时我只是在研究适合它的技术。SceneKit 将是理想的。 我设法为侧旋和某种前旋实现了可接受的球效果。我正在努力解决的问题是后旋。我正在使用 applyForce 方法的 position 参数,但似乎仅靠它不会给我我正在寻找的结果。要么我遗漏了一些东西(我对物理的了解有限),要么 SceneKit 的物理模拟不足以满足我的需求。基本上我有一个半径为 1.5 的球体,我在 Y 分量上的位置矢量从 -1.5 变为 1.5,结果是发生碰撞时我击中的白球或球跳跃。
第一个屏幕截图显示了撞击的时刻,而后者显示了碰撞之后以及它是如何跳跃的。
两个球体是这样配置的
let sphereGeometry = SCNSphere(radius: 1.5)
sphere1 = SCNNode(geometry: sphereGeometry)
sphere1.position = SCNVector3(x: -15, y: 0, z: 0)
sphere2 = SCNNode(geometry: sphereGeometry)
sphere2.position = SCNVector3(x: 15, y: 0, z: 0)
给我带来这种效果的代码如下:
sphere1.physicsBody?.applyForce(SCNVector3Make(350, 0, 0), atPosition:SCNVector3Make(1.5, -0.25, 0), impulse: true)
我在该代码中试图做的是将球击打到略低于中心的位置。我如何得到 -0.25 是得到一个 10 度的角度并计算它的 sin 函数。然后我将它乘以球体半径,这样我就可以得到一个正好位于球体表面上的点。
【问题讨论】:
请缩小这个问题的范围,以便我们为您提供帮助。提供一个简洁的代码示例,也许还有几个屏幕截图。你做了什么?你看见什么了?相反,您的期望是什么? 感谢您的意见。我编辑了我的问题。 【参考方案1】:所以我一直在阅读几篇关于池物理的论文/章节,我想我发现了一些至少证明我可以使用 SceneKit 做到这一点的东西。所以我缺少的是我。 ii. 正确的公式角速度。物理学仍然需要大量的润色,但至少它似乎得到了应用这些效果时所期望的大致轨迹。以下是代码,以防有人感兴趣:
//Cue strength
let strength : Float = 1000
//Cue mass expressed in terms of ball's mass
let cueMass : Float = self.balls[0].mass * 1.25
//White ball
let whiteBall = self.balls[0]
//The ball we are trying to hit
let targetBall = self.balls[1]
//White ball radius
let ballRadius = whiteBall.radius
//This should be in the range of -R, R where R is the ball radius. It determines how much off the center we would like to hit the ball along the z-axis. Produces left/right spin
let a : Float = 0
//This should be in the range of -R, R where R is the ball radius. It determines how much off the center we would like to hit the ball along the y-axis. Produces top/back spin
let b : Float = -ballRadius * 0.7
//This is calculated based off a and b and it is the position that we will be hitting the ball along the x-axis.
let c : Float = sqrt(ballRadius * ballRadius - a * a - b * b)
//This is the angle of the cue expressed in degrees. Values greater than zero will produce jump shots
let cueAngle : Float = 0
//Cue angle in radians for math functions
let cueAngleInRadians : Float = (cueAngle * 3.14) / 180
let cosAngle = cos(cueAngleInRadians)
let sinAngle = sin(cueAngleInRadians)
//Values to calculate the magnitude to be applied given the above variables
let m0 = a * a
let m1 = b * b * cosAngle * cosAngle
let m2 = c * c * sinAngle * sinAngle
let m3 = 2 * b * c * cosAngle * sinAngle
let w = (5 / (2 * ballRadius * ballRadius)) * (m0 + m1 + m2 + m3)
let n = 2 * whiteBall.mass * strength
let magnitude = n / (1 + whiteBall.mass / cueMass + w)
//We would like to point to the target ball
let targetVector = targetBall.position
//Get the unit vector of our target
var target = (targetVector - whiteBall.position).normal
//Multiply our direction by the force's magnitude. Y-axis component reflects the angle of the cue
target.x *= magnitude
target.y = (magnitude / whiteBall.mass) * sinAngle
target.z *= magnitude
//Apply the impulse at the given position by c, b, a
whiteBall.physicsBody?.applyForce(target, atPosition: SCNVector3Make(c, b, a), impulse: true)
//Values to calculate angular force
let i = ((2 / 5) * whiteBall.mass * ballRadius * ballRadius)
let wx = a * magnitude * sinAngle
let wy = -a * magnitude * cosAngle
let wz = -c * magnitude * sinAngle + b * magnitude * cosAngle
let wv = SCNVector3Make(wx, wy, wz) * (1 / i)
//Apply a torque
whiteBall.physicsBody?.applyTorque(SCNVector4Make(wv.x, wv.y, wv.z, 0.4), impulse: true)
请注意,a、b、c 的值应考虑目标向量的方向。
【讨论】:
您是如何制作靠垫的?我已经通过 SCNBox 完成了,但即使左右旋转也反应不佳,并且垫子不会与高速球碰撞,球直接穿过它们内部..以上是关于使用 SceneKit 的台球游戏中的后旋效果的主要内容,如果未能解决你的问题,请参考以下文章