我想创建一个逼真的池游戏并实现至少一些基本的球效果。我从头开始使用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函数。然后我将它乘以球体半径,这样我就可以得到一个位于球体表面上的点。
答案 0 :(得分:2)
所以我一直在阅读有关池物理学的几篇论文/章节,我想我发现了至少证明我可以用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的值应考虑目标矢量的方向。