- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Stack Overflow 社区的帮助下,我编写了一个非常基本但有趣的物理模拟器。
您单击并拖动鼠标来发射球。它会弹来弹去,最终停在“地板”上。
我想添加的下一个重要功能是球与球的碰撞。球的运动被分解为 x 和 y 速度矢量。我有重力(每一步都会小幅减少 y 向量),我有摩擦力(每次与墙壁碰撞时两个向量都会小幅减少)。球以一种令人惊讶的真实方式诚实地移动。
我想我的问题有两个部分:
处理“墙”的碰撞检测和由此产生的矢量变化很容易,但我发现球与球的碰撞更加复杂。对于墙壁,我只需取适当的 x 或 y 向量的负值,然后它就会朝正确的方向移动。对于球,我不认为是这样。
一些快速说明:为了简单起见,我现在可以接受完美的弹性碰撞,而且我所有的球现在都具有相同的质量,但我将来可能会改变这一点。
<小时/>编辑:我发现有用的资源
带有向量的二维球物理:2-Dimensional Collisions Without Trigonometry.pdf
2d 球碰撞检测示例:Adding Collision Detection
我的球碰撞检测和响应工作得很好!
相关代码:
碰撞检测:
for (int i = 0; i < ballCount; i++)
{
for (int j = i + 1; j < ballCount; j++)
{
if (balls[i].colliding(balls[j]))
{
balls[i].resolveCollision(balls[j]);
}
}
}
这将检查每个球之间的碰撞,但跳过多余的检查(如果您必须检查球 1 是否与球 2 碰撞,那么您不需要检查球 2 是否与球 1 碰撞。此外,它还会跳过检查与自身碰撞)。
然后,在我的球类中,我有 colliding() 和resolveCollision() 方法:
public boolean colliding(Ball ball)
{
float xd = position.getX() - ball.position.getX();
float yd = position.getY() - ball.position.getY();
float sumRadius = getRadius() + ball.getRadius();
float sqrRadius = sumRadius * sumRadius;
float distSqr = (xd * xd) + (yd * yd);
if (distSqr <= sqrRadius)
{
return true;
}
return false;
}
public void resolveCollision(Ball ball)
{
// get the mtd
Vector2d delta = (position.subtract(ball.position));
float d = delta.getLength();
// minimum translation distance to push balls apart after intersecting
Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / ball.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2d v = (this.velocity.subtract(ball.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse
float i = (-(1.0f + Constants.restitution) * vn) / (im1 + im2);
Vector2d impulse = mtd.normalize().multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
ball.velocity = ball.velocity.subtract(impulse.multiply(im2));
}
源代码:Complete source for ball to ball collider.
如果有人对如何改进这个基本物理模拟器有一些建议,请告诉我!我还没有添加的一件事是角动量,这样球会更真实地滚动。还有其他建议吗?发表评论!
最佳答案
要检测两个球是否发生碰撞,只需检查两个球中心之间的距离是否小于半径的两倍即可。要在球之间进行完美的弹性碰撞,您只需担心碰撞方向上的速度分量。两个球的另一个分量(与碰撞相切)将保持相同。您可以通过创建一个指向从一个球到另一个球的方向的单位向量,然后与球的速度向量进行点积来获得碰撞分量。然后,您可以将这些组件代入一维完美弹性碰撞方程。
维基百科有一个相当不错的summary of the whole process 。对于任何质量的球,可以使用以下方程计算新的速度(其中 v1 和 v2 是碰撞后的速度,u1、u2 是碰撞前的速度):
如果球具有相同的质量,则只需交换速度即可。这是我编写的一些代码,它们执行类似的操作:
void Simulation::collide(Storage::Iterator a, Storage::Iterator b)
{
// Check whether there actually was a collision
if (a == b)
return;
Vector collision = a.position() - b.position();
double distance = collision.length();
if (distance == 0.0) { // hack to avoid div by zero
collision = Vector(1.0, 0.0);
distance = 1.0;
}
if (distance > 1.0)
return;
// Get the components of the velocity vectors which are parallel to the collision.
// The perpendicular component remains the same for both fish
collision = collision / distance;
double aci = a.velocity().dot(collision);
double bci = b.velocity().dot(collision);
// Solve for the new velocities using the 1-dimensional elastic collision equations.
// Turns out it's really simple when the masses are the same.
double acf = bci;
double bcf = aci;
// Replace the collision velocity components with the new ones
a.velocity() += (acf - aci) * collision;
b.velocity() += (bcf - bci) * collision;
}
至于效率,Ryan Fox 是对的,您应该考虑将区域划分为多个部分,然后在每个部分内进行碰撞检测。请记住,球可能会与部分边界上的其他球发生碰撞,因此这可能会使您的代码变得更加复杂。不过,除非你有几百个球,否则效率可能并不重要。为了获得奖励积分,您可以在不同的核心上运行每个部分,或者拆分每个部分内的碰撞处理。
关于graphics - 球与球的碰撞 - 检测和处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/345838/
我想知道如何在 OCaml 中设置文本大小。我尝试了 Graphics.set_text_size,我猜这应该可以解决问题。 但是无论我输入 set_text_size 200 还是 set_text
我想使用mathematica 为我正在写的书绘制图表。我想在mathematica中画一个图,将其保存为图片,然后将其导入到quarkxpress中,最后将其导出为pdf。 我的问题是最好使用哪种格
在顶层加载 Graphics 模块时,我收到一条错误消息“找不到 graphics.cma”。 我使用的是 OS X,而且我很确定我已经正确安装了 OCaml,因为我已经使用了大约一个月了。所以看起来
我知道 DDS 文件的存在,允许在 as/400 上对显示图形进行编程,但是还有其他方法吗? 具体来说,我想要做的是直接操作终端缓冲区,以便能够显示除文本之外的任何其他内容。例如,终端如下所示: 假设
Graphics.Save 与 Graphics.BeginContainer 有何不同? 最佳答案 看看here : The documentation does not differentiate
由于 Gdiplus::Graphics::DrawGraphics(Graphics*, x, y) 不存在,执行此类操作的最佳方法是什么? 例如,创建一个 Graphics 对象,使用各种 Dra
你能看出这有什么问题吗: (define (box d x1 y1 x2 y2) ( (graphics-draw-line d x1 y
我想编写一个 2D 游戏引擎。我遇到的问题(我不使用opengl之类的东西,所以我用cpu渲染)是,我通过graphics.drawImage()只得到7fps;您有任何加快速度的建议或其他替代方案吗
我在某些代码中发现了渲染错误,并找到了解决方法,但我想知道为什么我会得到不同的行为。在旧代码中,背景(有时)会呈现为白色,尽管在调试时 getBackground() 会返回正确的颜色。 旧代码: @
有谁知道是否有办法(也许通过外部API)将图形绘图/转换为多个图形?这个想法是同时保存 PNG 和 PDF(使用 Java IText 库)。 最佳答案 您可以将 Graphics 对象写入(java
我试图了解如何在英特尔芯片组上以 x86 保护模式绘制简单图形。我已经(有点)知道如何使用 VGA 接口(interface)来做到这一点,并且我正在尝试了解如何使用 G35 Express 来做到这
在我的应用程序中,我生成了一个条形码图像,该图像是根据用户使用 OpenFileDialog 上传的文件中的数据生成的。我的目标是允许用户在屏幕上查看条形码数据和图像本身,打印并使他们能够将两者保存为
我是 Java 新手,我只是想得到一些简单的东西,可能类似于 Zelle's graphics对于Python。 最佳答案 Java 类 Graphics和 Graphics2D应该包含 Zelle
如何将 FMX.Graphics.TBitmap 转换为 VCL.Graphics.TBitmap 或 Vcl.Imaging.PngImage.TPngImage? 我的项目中有FMX表单和VCL表
我需要找到用于间距目的的字体大小,发现这很有帮助:https://docs.oracle.com/javase/tutorial/2d/text/measuringtext.html 但是,我不确定如
我有一点奇怪的错误是由一个看似简单的问题引起的。 在我的源代码中,我尝试使用 QQuickPaintedItem 来呈现 QWidget 派生类 (QPushButton) 的整体外观,然后将其绘制到
我正在尝试通过具有以下规范的设备来解决 Android 应用程序崩溃的问题: Device PAP3400DUO 1 Manufacturer — Android version Android 4.
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我有这行代码: mBgTransition = (TransitionDrawable) mSwitchBg.getBackground(); 背景曾经是一个常规的可绘制对象, 但现在是 9 个补丁
当我的应用程序在启动时崩溃时尝试实现自适应图标时出现此错误。 我无法想象为什么会收到此错误,因为在下面错误日志中提到的文件(MainActivity 和 BaseActivity)中,我没有使用Ada
我是一名优秀的程序员,十分优秀!