如何在 2D 碰撞检测中正确解析碰撞的位置?
How do I resolve a collision's position properly in 2D collision detection?
我的当前实现如下:
if (shapesCollide) {
if (velocity.y > 0) entity.position.y = other.position.y - entity.size.y;
else entity.position.y = other.position.y + other.size.y;
velocity.y = 0;
if (velocity.x > 0) entity.position.x = other.position.x - entity.size.x;
else entity.position.x = other.position.x + other.size.x;
velocity.x = 0;
}
但是,这会导致在两个轴上发生运动时的怪异处理 - 例如,让entity
向下移动到object
的左侧,然后将其移至与object
碰撞,将正确解决水平碰撞,但会破裂垂直运动。
我以前只是去了
if (shapesCollide) {
position = oldPosition;
velocity = { 0, 0 };
}
,但这导致了另一个多轴问题:如果我将entity
放在object
上,它将无法移动,因为重力诱导的运动将不断取消两个速度。我还尝试了分别考虑两个轴,但是只有在考虑到两个速度时发生碰撞时,这会导致问题。
解决两个轴上碰撞的最佳解决方案是什么?
我认为可以将实体视为或多或少是圆形,而大小是实体的半径?
我们可能需要一点矢量数学来解决此问题。(我不知道C 中的Square-root函数,因此请在SQRT上知道。
float rEntity = sqrt(entity.size.x * entity.size.x + entity.size.y * entity.size.y);
float rOther = sqrt(other.size.x * other.size.x + other.size.y * other.size.y);
float midX = (entity.position.x + other.position.x) / 2.0;
float midY = (entity.position.y + other.position.y) / 2.0;
float dx = entity.position.x - midX;
float dy = entity.position.y - midY;
float D = sqrt(dx * dx + dy * dy);
租金和 rother 是对象的半径, midx 和 midy 是他们的中心坐标。 dx 和 dy 是距实体中心的距离。
然后做:
entity.position.x = midX + dx * rEntity / D;
entity.position.y = midY + dy * rEntity / D;
other.position.x = midX - dx * rOther / D;
other.position.y = midY - dy * rOther / D;
您可能应该检查 d 不是0,如果是,只需设置dx = 1,dy = 0,d = 1或类似的东西。
您还应该这样做:
velocity.x = 0;
velocity.y = 0;
如果您希望实体停止。
要进行更准确的建模,您也可以尝试以下操作:
float rEntity = sqrt(entity.size.x * entity.size.x + entity.size.y * entity.size.y);
float rOther = sqrt(other.size.x * other.size.x + other.size.y * other.size.y);
float midX = (entity.position.x * rOther + other.position.x * rEntity) / (rEntity + rOther);
float midY = (entity.position.y * rOther + other.position.y * rEntity) / (rEntity + rOther);
float dxEntity = entity.position.x - midX;
float dyEntity = entity.position.y - midY;
float dEntity = sqrt(dxEntity * dxEntity + dyEntity * dyEntity);
float dxOther = other.position.x - midX;
float dyOther = other.position.y - midY;
float dOther = sqrt(dxOther * dxOther + dyOther * dyOther);
entity.position.x = midX + dxEntity * rEntity / dEntity;
entity.position.y = midY + dyEntity * rEntity / dEntity;
other.position.x = midX + dxOther * rOther / dOther;
other.position.y = midY + dyOther * rOther / dOther;
在考虑半径时找到了中点。但是我不能保证这有效。另外,最后添加的标志很重要。
我希望这有帮助(并有效)。让我知道是否不清楚。
相关文章:
- 将值指定给向量(2D)的向量中的某个位置
- 使用Unreal C++获取VR耳机的世界位置/方向
- 写入位置0x0000000C时发生访问冲突
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- GL_SHADERSTORAGE_BUFFER位置是否与其他着色器位置冲突
- 如何使用cudaMallocManaged在指针位置初始化对象?(C++)
- 无法获取webot::PositionSensor对象中位置传感器的值
- 落砂模拟碰撞检测C++和SFML
- 非常量变量只读位置的赋值
- 如何定义更改car类中car位置的方法
- 使用迭代器时如何访问对象在向量中的位置?
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 求最大元素位置的分治算法
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 为什么我的点没有在 OpenGL 中绘制鼠标所在的位置?
- 如何将元素添加到向量的字符串位置
- 如何在 2D 碰撞检测中正确解析碰撞的位置?
- SFML鼠标位置和碰撞从文件加载
- SFML 碰撞检测,C++ -> 重置玩家位置
- 在子弹物理Hello World项目中更改碰撞体的位置