swift - 在 Swift 游戏中处理圆-圆碰撞的最佳方法是什么?
问题描述
我正在制作一个类似于 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)
}
解决方案
伪代码:
let vmallet = mallet velocity
let vball = ball velocity
let vrelative = vball - vmallet
let vperpendicular = dotProduct(vrelative, contactNormal) * contactNormal
let vtangential = vrelative - vperpendicular
// vtangential is unchanged in the collision, vperpendicular reflects
let newvrelative = vtangential - vperpendicular
let newvball = newvrelative + vmallet
// set ball velocity to newvball
推荐阅读
- python - 使用 OpenCV 比较图像
- database - 哪个是正确的基数表示法?
- python - 如何使用附加功能和版本说明符 pip install -e?
- javascript - 仅当可拖动容器有溢出时,jquery ui 拖放元素在拖动到 droppables 时被切断
- vuejs2 - 强制重新计算到 Vue 计算属性?
- javascript - 如何创建在 switch case 中检测特殊字符的逻辑(错误处理)
- c++ - 带指针的 C++ 双向链表:类的对象构造不正确
- html - 智能手机上的 SVG 动画不流畅
- windows - 如果发件人是原始来源,如何有条件地在冒泡事件中运行代码?(UWP 应用)
- python - 使用 python 创建 midi 文件或安装 midiutil