我正在创建一个自定义字段,以在用户执行平移手势后减慢对象的运动速度。使用正常的摩擦力会使物体感觉太滑,因此我尝试应用 Spring 物理来代替摩擦力。
我有一个函数似乎可以正确计算我正在寻找的行为。
extension UIFieldBehavior {
static func dampingField(_ constant: CGFloat) -> UIFieldBehavior {
return UIFieldBehavior.field { field, position, velocity, mass, charge, time in
let speed = sqrt(pow(velocity.dx, 2) + pow(velocity.dy, 2))
let angle = acos(velocity.dx / speed)
let force = -constant * speed
guard angle.isNaN == false, force.isNaN == false
else { return .zero }
return CGVector(dx: cos(angle) * force, dy: sin(angle) * force)
}
}
}
但是,垂直运动的表现并不符合我的预期。任何朝向引用 View 顶部的运动都会导致对象加速得更快。
我玩三角学有一段时间了,但我很困惑。有an example swift playground在 GitHub 上演示了这个问题。
我在数学中忽略了什么?
最佳答案
答案确实是在梦中出现的,哈哈。
意想不到的行为是负 y 方向上的力本应为正,但却变成了负,导致最终速度的绝对值增加。
果然,添加检查以确保力的 y 分量始终具有与给定速度的 y 分量相反的符号解决了问题。
var vector = CGVector(dx: cos(angle) * force, dy: sin(angle) * force)
if vector.dy.sign == velocity.dy.sign {
vector.dy *= -1
}
return vector
试图思考为什么只有 y 分量被错误地签名,我注意到角度是相对于 x 轴计算的。
let angle = acos(velocity.dx / speed)
我想我应该尝试根据相对于 y 轴的角度来计算 y 坐标的力,这也解决了问题。
return CGVector(dx: cos(angle) * force, dy: sin(asin(velocity.dy / speed)) * force)
思考了一下,我意识到,因为 asin
和 acos
是 sin
和 cos
分别,可以减少代码以完全删除 sin
和 cos
的使用。
return CGVector(dx: velocity.dx / speed * force, dy: velocity.dy / speed * force)
实际上,我根本不需要将三角学引入其中,因为对向量分量的操作相当于对向量本身的操作。现在我的力量按预期工作并且更容易推理。
extension UIFieldBehavior {
static func dampingField(_ constant: CGFloat) -> UIFieldBehavior {
return UIFieldBehavior.field { field, position, velocity, mass, charge, time in
return CGVector(dx: -constant * velocity.dx, dy: -constant * velocity.dy)
}
}
}
关于ios - 自定义 UIFieldBehavior 中的意外加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50439223/