自定义 UIFieldBehavior 中的意外加速
Posted
技术标签:
【中文标题】自定义 UIFieldBehavior 中的意外加速【英文标题】:Unexpected Acceleration in Custom UIFieldBehavior 【发布时间】:2018-05-20 20:48:48 【问题描述】:我正在创建一个自定义字段以在用户执行平移手势后减慢对象的运动。使用正常摩擦会使物体感觉太滑,所以我尝试应用弹簧物理来代替摩擦。
我有一个似乎可以正确计算我正在寻找的行为的函数。
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)
但是,垂直运动的表现与我预期的不同。朝向参考视图顶部的任何运动都会导致对象加速。
我玩三角学已经有一段时间了,但我很难过。 GitHub 上有 an example swift playground 演示了这个问题。
我在数学中忽略了什么?
【问题讨论】:
为什么你的力公式是force = -constant * speed
?不应该是F=kx
x
是位移吗?
@Oswald 函数每次运行,只经过一个“时间单位”,所以速度和位移是等价的。我知道这不是确切的情况,但在我试图找出正确的物理原理时,它已经是一个足够好的近似值了。不过,我不认为这可能是问题的一部分——它不能解释为什么意外行为只存在于一个方向。
【参考方案1】:
答案真的是在梦中出现的,哈哈。
出乎意料的行为是,负 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
和@ 的使用完全是 987654329@。
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)
【讨论】:
以上是关于自定义 UIFieldBehavior 中的意外加速的主要内容,如果未能解决你的问题,请参考以下文章