- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个程序可以让圆圈相互反弹。我按照此处的说明旋转矢量并根据碰撞角度缩放大小:http://www.vobarian.com/collisions/2dcollisions2.pdf
这段代码是我用python写的(0索引表示x坐标):
norm_vect = [(object2.pos[0] - object1.pos[0]), (object2.pos[1] - object1.pos[1])]
unit = sqrt((norm_vect[0]**2) + (norm_vect[1]**2))
unit_vect = [float(norm_vect[0]) / unit, float(norm_vect[1]) /unit]
tan_vect = [-unit_vect[1], unit_vect[0]]
vel1 = object1.vel
vel2 = object2.vel
vel1_norm = vel1[0] * unit_vect[0] + vel1[1] * unit_vect[1]
vel1_tan = vel1[0] * tan_vect[0] + vel1[1] * tan_vect[1]
vel2_norm = vel2[0] * unit_vect[0] + vel2[1] * unit_vect[1]
vel2_tan = vel2[0] * tan_vect[0] + vel2[1] * tan_vect[1]
new_vel1_norm = (vel1_norm * (object1.mass - object2.mass) + 2 * object2.mass * vel2_norm) / (object1.mass + object2.mass)
new_vel2_norm = (vel2_norm * (object2.mass - object1.mass) + 2 * object1.mass * vel1_norm) / (object1.mass + object2.mass)
new_norm_vect1 = [new_vel1_norm * float(unit_vect[0]), new_vel1_norm * float(unit_vect[1])]
new_norm_vect2 = [new_vel2_norm * float(unit_vect[0]), new_vel2_norm * float(unit_vect[1])]
new_tan_vect1 = [new_vel1_norm * float(tan_vect[0]), new_vel1_norm * float(tan_vect[1])]
new_tan_vect2 = [new_vel2_norm * float(tan_vect[0]), new_vel2_norm * float(tan_vect[1])]
# Now update the object's velocity
object1.vel = [new_norm_vect1[0] + new_tan_vect1[0], + new_norm_vect1[1] + new_tan_vect1[1]]
object2.vel = [new_norm_vect2[0] + new_tan_vect2[0], + new_norm_vect2[1] + new_tan_vect2[1]]
问题是它有时有效,但有时无效。谁能告诉我为什么?似乎如果球以正确的角度碰撞,那么它们的导出轨迹就会交换或发生其他事情。我在 codeskulptor 浏览器中写了这个:http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_2.py
谁能指出我哪里做错了?
编辑:这可能是我处理碰撞的方式吗?以下是步骤:
1) Draw the balls on the screen
2) Create set of unique pairs of collidable objects
3) For each ball, move the ball's position 1 frame forward according to the velocity:
->1) Check to see if the ball is hitting a wall
->2) For each pairset, if the ball in question is a member of the pair:
-->1) If distance between centers is less than sum of radii:
-->1) Calculate rebound trajectories
---2) Find N such that position + rebound trajectory *N is out of collision zone
最佳答案
在线模拟真爽!我没有详细研究您的完整代码,只是研究了您在问题中发布的片段。快速浏览一下,您可以正确计算切向和法向单位向量、旧法向和切向速度以及新法向速度。但在那之后,你似乎有点迷路了。正如关于碰撞的文档中所解释的那样,切向速度在碰撞过程中不会发生变化,因此无需计算 new_tan_vect1/2
。我也不明白你为什么要计算new_norm_vect1
,法向量在碰撞过程中不会改变。
一些其他的小备注:
为什么在代码中使用float()
?这通常不需要。如果这样做的原因是为了获得正确的除法结果,您应该在代码顶部添加一个 from __future__ import division
,因为您似乎使用的是 Python2。参见 this old question了解更多信息。
你所说的norm_vect
其实就是非归一化的法向量,你所说的unit_vect
其实就是归一化的法向量。我会同时调用 norm_vect,以使法线和切线之间的区别更加清楚。单位向量是长度为 1 的任何向量,因此将其用于法线向量有点误导。
如果您打算进行更多此类模拟,您应该考虑学习 numpy
。这允许您编写矢量化计算,而不是手写出所有 x
和 y
的方程式。例如。 norm_vect = pos2 - pos1; norm_vect/= np.linalg.norm(norm_vect)
或 object1.vel = norm_vect * new_vel1_norm + tang_vect * vel1_tang
。
我会写你的代码片段应该或多或少像这样(未经测试的代码):
from __future__ import division # move this to the top of your program
# calculate normal and tangential unit vectors
norm_vect = [(object2.pos[0] - object1.pos[0]),
(object2.pos[1] - object1.pos[1])] # stil un-normalized!
norm_length = sqrt((norm_vect[0]**2) + (norm_vect[1]**2))
norm_vect = [norm_vect[0] / norm_length,
norm_vect[1] / norm_length] # do normalization
tang_vect = [-norm_vect[1], norm_vect[0]] # rotate norm_vect by 90 degrees
# normal and tangential velocities before collision
vel1 = object1.vel
vel2 = object2.vel
vel1_norm = vel1[0] * norm_vect[0] + vel1[1] * norm_vect[1]
vel1_tang = vel1[0] * tang_vect[0] + vel1[1] * tang_vect[1]
vel2_norm = vel2[0] * norm_vect[0] + vel2[1] * norm_vect[1]
vel2_tang = vel2[0] * tang_vect[0] + vel2[1] * tang_vect[1]
# calculate velocities after collision
new_vel1_norm = (vel1_norm * (object1.mass - object2.mass)
+ 2 * object2.mass * vel2_norm) / (object1.mass + object2.mass)
new_vel2_norm = (vel2_norm * (object2.mass - object1.mass)
+ 2 * object1.mass * vel1_norm) / (object1.mass + object2.mass)
# no need to calculate new_vel_tang, since it does not change
# Now update the object's velocity
object1.vel = [norm_vect[0] * new_vel1_norm + tang_vect[0] * vel1_tang,
norm_vect[1] * new_vel1_norm + tang_vect[1] * vel1_tang]
object2.vel = [norm_vect[0] * new_vel2_norm + tang_vect[0] * vel2_tang,
norm_vect[1] * new_vel2_norm + tang_vect[1] * vel2_tang]
我重命名了一些变量以使其更清晰。
关于python - 我找不到 python 中的这个圆反弹计算有什么问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29136677/
我正在尝试在 Windows 上运行的小于 1GB 的 VM 上设置 YouTrack 和 TeamCity。使用率将非常低(用户和请求)。这是一个 POC 环境,如果它有效,我可能会将它推送到一个超
所以我在尝试使用 FORFILES 解决这个问题时遇到了麻烦。我正在尝试获取不超过 4 天的文件。所以基本上少于 4 天。然而,这似乎不太可能,因为/d -4 获取所有 4 天或更早的项目。 以下是我
如何从下面的 events 表中选择小于 15 分钟前创建的 events? CREATE TABLE events ( created_at timestamp NOT NULL DEFAU
Google Analytics Realtime提供 rt:minutesAgo ,可以过滤查询。 然而,它是一个维度而不是一个度量标准,<=不能在过滤器中使用。 假设我想在最后 n 分钟内获得一些
iOS 核心数据 - 严重的应用程序错误 - 尝试插入 nil 你好, 我的应用程序实际上运行稳定,但在极少数情况下它会崩溃并显示此错误消息... 2019-04-02 20:48:52.437172
我想制作一个 html div 以快速向右移动(例如不到 1 秒)并消失。然后1秒后再次直接出现在这个过程最开始div的位置。此过程将由单击按钮并重复 10 次触发。 我试图在 CSS 中使用过渡属性
我发现使用 TimeTrigger 是 Windows 10 (UWP) 上计划后台任务的方式。但是看起来我们需要给出的最小数字是 15 分钟。只是想知道,即使我们安排它在接下来的 1 分钟内运行,警
我必须在 1 秒内在屏幕上打印 2^20 行整数 printf 不够快,还有其他易于使用的快速输出替代方法吗? 每一行只包含 1 个整数。 我要求它用于竞争性编程问题,我必须将其源代码提交给法官。 最
我是一名优秀的程序员,十分优秀!