Swift游戏中处理圆圈碰撞的最佳方法



我正在制作一款类似于SpriteKit中的空中冰球的Swift游戏。

当冰球被球员的木槌击打时,我正在努力将准确/预期的"冲动"施加到冰球上。

我可以了解球员的速度。通过使用CCD_ 1,我还可以准确地检测两个圆之间的碰撞。此外,我还根据球击中球员木槌的位置确定了球反弹的预期方向(由于它是一个圆圈,这个方向可能与你通过观察球员的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

最新更新