碰撞与段与载体algorythm错后重新定位圈载体、algorythm

2023-09-07 14:43:34 作者:爷 叼烟闯天下

在一个2D游戏,我试图repositionate了一圈后,它通过一个段。以图片为例的情况下,我需要重新定位回圈,这样B就成为圆的切点。

In a 2D game, i'm trying to repositionate a circle after it passed through a segment. Taking the picture as example situation, i need to reposition back the circle so that B will become the tangent point on the circle.

这是我有信息是:

X,圆的是

x,y of the circle

圆的半径

DIRX,dirY中:X方向,Y圈是有

dirx, diry: Direction of x,y the circle is having

A和B之间的距离

我在做什么是计算C点的坐标,然后坐标B点,再减去向量AB与交流(半径),并repositionate X,-BC的ÿ回来了。

What i'm doing is to calculate the coordinates of point C, then coordinates of point B, and then subtract vector AB from AC (radius), and repositionate x,y back of -BC.

也有一些是错误的算法中,因为后,该中心与线之间的垂直距离是永远半径完全一样。

There is something wrong in the algorithm because after that the orthogonal distance between the center and the line is never exactly like the radius.

Len = Sqrt( dirx^2 + diry^2 )
dx = dirx / Len
dy = diry / Len
// these should be coordinates of point C
tangX = x + radius * dx
tangY = y + radius * dy
// these should be coordinates of point B
wrongX = x + distance* dx
wrongY = y + distance* dy
//these should be vector BC
BCx = tangX - wrongX;
BCy = tangY - wrongY;
// now i reposition the center back of BC
x = x - BCx
y = y - BCy

该中心repositionated在正确的方向,但从来没有足够匹配距离的AC

The center is repositionated in the correct direction but never enough to match the distance AC.

在换句话说: 我想移动中心,使B室是圆和线之间的切点。让我解释一下你,换句话说这个问题:你可以看到电源的长度等于我的半径。半径在我的日志40,我打印出来以图像为例这种距离会像30 A和B之间的距离的价值,我的算法后,我想到的是AB是40(半径,AC)但它总是一个其他的数字,从来没有40

In other words: I want to move the center and make B to be the tangent point between the circle and the line. Let me explain you in other words the problem: as you can see length of AC is equal to my radius. The radius is 40. in my log, i print out the value of the distance between A and B. Taking the image as example such distance would be something like 30, after my algorithm i expect that AB is 40 (the radius, AC) but it's always an other number, never 40

推荐答案

这个问题是比较容易解决的,如果制定适当的。看来碰撞检测,在那里你正在寻找检测到碰撞后调整对象的位置的一个简单的例子。直观的方式来框架是:你有一个事件告诉你,你的对象越过边界。其最后的运动矢量(加载dirX,dirY中)和你给出的增量你的对象越过超出边界。所有你需要做的是将你的目标倒退,同样的三角洲它横渡超出边界,沿着相同的运动矢量。

This issue is relatively easy to solve, if formulated appropriately. It seems a simple case of collision detection, where you're seeking to adjust the object's position after detecting the collision. The intuitive way to frame it is: you have an event telling you your object crossed a boundary. Its last motion vector is (dirX, dirY) and you're given the delta your object crossed beyond the boundary. All you need to do is to move your object backwards, the same delta it crossed beyond the boundary, along the same motion vector.

和,而不是在切点而言推理的问题,你可以简单地在该中心方面原因,关于它的对象本身的坐标。 现在,下面的参数是给定的输入:

And instead of reasoning about the problem in terms of tangent points, you can simply reason about it in terms of the center coordinates of the object itself. Now, the following parameters are given input:

X,Y 是你对象的中心的最后坐标和研究半径 让(加载dirX,dirY中)是你的运动矢量 让字母是你的运动矢量与X轴的夹角(你可以从运动矢量本身计算的话) 让增量将距离越过超出边界 let x, y be the last coordinates of your object's center and r its radius let (dirX, dirY) be your motion vector let alpha be the angle of your motion vector to the x axis (you can compute it from the motion vector itself) let delta be the distance crossed beyond the boundary

该问题的解决,能减轻到以下内容:

The problem's resolution reduces to the following:

而这里的在Python 2可执行code样品,实现和测试的解决方案:

And here's an executable code sample in python 2 that implements and tests that solution:

from math import sin, cos, atan, fabs as abs, sqrt, pow
from collections import namedtuple

# utility types and functions
Disk = namedtuple('Disk', 'x y radius')
MotionVector = namedtuple('MotionVector', 'x y')

def sqr(d):
    return pow(d, 2)


# the actual implementation of the solution
def reposition_disk(disk, delta, motion_vector):
    # we start by computing the angle to the x axis of the motion vector
    alpha = atan(motion_vector.y / motion_vector.x)

    # then we compute the displacement we should apply
    # to our object along both axes

    dX = cos(alpha) * delta
    dY = sin(alpha) * delta

    # and we update the object's coordinates
    return Disk(disk.x - dX, disk.y - dY, disk.radius)


# a test method to exercise our implementation
def test_reposition_disk():
    # initialiasing our disk at a position where it is supposed
    # to have crossed a boundary
    disk = Disk(80, 70, 40)

    # the disk was moving along the following motion vector:
    motion_vector = MotionVector(10, -5)

    delta = 5

    updated = reposition_disk(disk, delta, motion_vector)

    # now we need to compute the coordinates of the 
    # point of the boundary the disk should have stopped at

    alpha = atan(motion_vector.y / motion_vector.x)
    bX = disk.x + (disk.radius - delta) * cos(alpha)
    bY = disk.y + (disk.radius - delta) * sin(alpha)

    # and finally we have to assert that the distance from
    # the object's new coordinates to the boundary is equal
    # to its radius

    distance = sqrt(sqr(updated.x - bX ) + sqr(updated.y - bY))
    print('Distance to boundary : %f' % distance)
    assert abs(distance - disk.radius) < 0.01


test_reposition_disk()

附录 我经历了code您粘贴除非我错了,还有,通过它,你检查碰撞,从圆到相交线的中心计算距离的逻辑存在问题。准确的实现,逻辑意味着解一元二次方程(检查此link以供将来参考),了解线路是否相交的圆圈。然后计算距离,你必须解决的基础上的交线的方向向量的点积的公式,和正交线经过圆心。

Addendum I went through the code you pasted and unless I am mistaken, there is a problem with the logic through which, you are checking for collision and computing the distance from the center of the circle to the intersecting line. An accurate implementation of that logic implies solving a quadratic equation (check this link for future reference) to find out whether the line intersects the circle. Then to compute the distance you'll have to solve an equation based on the dot product of the direction vector of the intersecting line, and the orthogonal line passing through the center of the circle.

下面是一个Python代码段说明的第一部分(找出该行是否不相交的圆圈)和松散按照上面的链接的详细步骤:

Here's a python snippet illustrating the first part (figuring out whether or not the line intersects the circle) and loosely following the steps detailed in the above link:

Line = namedtuple('Line', 'x1 y1 x2 y2')

# currying the square out of pow
def sqr(d):
    return pow(d, 2)


# function to compute the line equation
# out of the coordinates of a couple of
# points
def coords_to_affine(line):
    # y = hx + j
    h = (line.y2 - line.y1) / (line.x2 - line.x1)
    j = y1 - (h * x1)
    return (h, j)


# function to compute the quadratic equation
# parameters
def compute_quadratic_params(disk, line):
    (h, j) = coords_to_affine(line)
    (p, q, r) = (disk.x, disk.y, disk.r)

    a = sqr(h) + 1
    b = 2 * ((h * j) - (h * q) - p)
    c = sqr(q) - sqr(r) + sqr(p) - (2 * (j * q)) + sqr(j)
    return (a, b, c)


# function to test whether a given circle
# intersects a line
def disk_intersects_line(a, b, c):
    # true if (b² - 4ac) >= 0
    return (sqr(b) - (4 * a * c)) >= 0
 
精彩推荐
图片推荐