【发布时间】:2021-01-07 21:48:12
【问题描述】:
我正在用 SpriteKit 制作一个类似于 Air Hockey 的 Swift 游戏。
当球被球员的木槌击打时,我正在尝试对球施加准确/预期的“脉冲”。
我可以访问玩家的速度。通过使用func didBegin(_ contact: SKPhysicsContact),我还可以在两个圆之间进行准确的碰撞检测。此外,我还根据球击中玩家槌的位置确定了球应该反弹的预期方向(因为它是一个圆圈,所以这个方向可能与您通过查看玩家的 dx 和 dy 所期望的不同。)
这是我目前正在做的,但感觉有点不自然和不正常:
func didBegin(_ contact: SKPhysicsContact)
{
if (contact.bodyA.categoryBitMask == BodyType.ball.rawValue && contact.bodyB.categoryBitMask == BodyType.player.rawValue) && (contact.bodyA.contactTestBitMask == 25 || contact.bodyB.contactTestBitMask == 25) && bottomTouchForCollision == true
{
ball!.physicsBody!.applyImpulse(CGVector(dx: CGFloat(UserDefaults.standard.float(forKey: "BottomVelocity")) * contact.contactNormal.dx, dy: CGFloat(UserDefaults.standard.float(forKey: "BottomVelocity")) * contact.contactNormal.dy))
}
}
什么是对球产生准确且反应灵敏的冲动的最佳方法。我认为仅仅依靠contact.contactNormal.dy 的方向感觉不自然,因为如果玩家的圆圈在一个地方不动,这是预期的方向。我已经为这个问题苦苦挣扎了好几个星期,不知道如何最好地解决它。代码解释表示赞赏,但任何事情都有帮助。
我以类似的方式提出了这个问题,并收到了回复:
“考虑球撞击静止木槌的情况。它会以相同的速度反射出去,最终的运动方向是入射角等于接触点处的反射角。然后对于以速度矢量 v 移动的木槌,从所有速度中减去 v 以转换为静止木槌的情况。在转换后的问题中计算球速度。然后通过将 v 添加到结果中来转换回来。(如果你这样计算它,你不必应用Impulse,直接设置新的速度即可。)"
我无法理解如何实现这个想法,但是如果有人可以帮助提供伪代码或代码,那就太好了!
编辑:这是我在下面的帮助下的方法。
if (contact.bodyA.categoryBitMask == BodyType.ball.rawValue && contact.bodyB.categoryBitMask == BodyType.player.rawValue) && (contact.bodyA.contactTestBitMask == 75 || contact.bodyB.contactTestBitMask == 75) && northTouchForCollision == true
{
let vmallet = CGVector(dx: CGFloat(UserDefaults.standard.float(forKey: "NorthForceDX")), dy: CGFloat(UserDefaults.standard.float(forKey: "NorthForceDY")))
let vball = ball?.physicsBody?.velocity
let vrelativedx = vball!.dx - vmallet.dx
let vrelativedy = vball!.dy - vmallet.dy
let vrelative = CGVector(dx: vrelativedx, dy: vrelativedy)
let c = (vrelative.dx * contact.contactNormal.dx) + (vrelative.dy * contact.contactNormal.dy)
let vperpendicular = CGVector(dx: contact.contactNormal.dx * c, dy: contact.contactNormal.dy * c)
let vtangential = CGVector(dx: vrelative.dx - vperpendicular.dx, dy: vrelative.dy - vperpendicular.dy)
// vtangential is unchanged in the collision, vperpendicular reflects
let newvrelative = CGVector(dx: vtangential.dx - vperpendicular.dx, dy: vtangential.dy - vperpendicular.dy)
let newvball = CGVector(dx: newvrelative.dx + vmallet.dx, dy: newvrelative.dy + vmallet.dy)
// set ball velocity to newvball
// ball?.physicsBody?.velocity = newvball
ball!.physicsBody!.applyImpulse(newvball)
}
【问题讨论】:
标签: swift xcode sprite-kit game-physics collision