完美无瑕的鼠标碰撞检测和矩形形状的移动

时间:2016-02-15 21:46:51

标签: python pygame collision-detection

我之前发过一篇与我正在进行的项目有关的帖子,但我收到的信息还不够,所以我只是把这一切都放在盘子里。我正在进行的项目是一个非常类似于http://cursors.io的游戏。播放器控制鼠标后面的游戏中光标。但是,光标无法移动到墙壁和块等对象之外。 enter image description here

第三种方法,光标卡在交叉路口

Terminology:

Cursor - The ingame object
Mouse  - The player's actual cursor

我尝试了几种方法。

方法1

我尝试将光标移动到每个帧的播放器鼠标顶部,如果它在可碰撞的形状对象内部,则它不会移动该帧。但是,这个 如果用户暂停游戏,将鼠标移动到屏幕上的其他位置并取消暂停,则会出现问题。或者,即使用户足够快地移动鼠标以跨越单个帧内的对象的距离,他们也能够出现故障。通过它。

方法2

我尝试的下一个方法是在播放器鼠标的方向上每帧移动光标一定数量的像素,应用与方法1相同的检查方法。这导致生涩,缓慢的移动,担心如果设定的像素移动太高,它仍会跳过非常薄的障碍物。

方法3

我尝试的最后一种方法是使用线段交叉点。我将定义从光标到鼠标的主线,然后是每个可碰撞对象的边界线。当鼠标移动时,我会检查主线段是否与任何边界线相交,如果是,则记录它。检查完所有边界线后,最近的交叉点将是保留的交叉点。我会将光标移动到该交叉点并完成调用。如果没有发生交叉,我只需将光标移动到鼠标。但问题是,一旦光标移动到交叉点,就会卡住。交点停留在光标的新位置,因为它仍然位于边界线的顶部。同样,我无法想到一种让光标在边界线上滑动的方法,跟随鼠标的x或y移动而不通过。

一些示例代码:

# ============
#  Approach 1
# ============
# Game loop {
if not any([i.contains(mousepos) for i in collideables]):
    cursorpos = mousepos
# }
# ============
#  Approach 2
# ============
speed = 5

# Game loop {
dx = copysign(1, mousepos[0]-cursorpos[0])
dy = copysign(1, mousepos[1]-cursorpos[1])
destx = dx*speed
desty = dy*speed
if not any([i.contains([destx, desty]) for i in collideables]):
    cursorpos = [destx, desty]
# }
# ============
#  Approach 3
# ============
def lineIntersection(line1, line2):
    # intersection code to determine x and y of intersection, as well
    # as the distance across line1 to the intersection
    if intersection:
        return [x, y, distance]
    return None

# Game loop {
closestIntersect = None
for collideable in collideables:
    for boundaryline in collideable:
        intersect = lineIntersection(mainline, boundaryline)
        if intersect:
            if not closestIntersect or intersect[2] < closestIntersect[2]:
                closestIntersect = intersect
if closestIntersect:
    cursorpos = intersect[0], intersect[1]
# }

2 个答案:

答案 0 :(得分:0)

方法3是正确的方法,但有一个额外的: 我认为你必须在这里考虑法线。如果边缘法线和光标移动方向的点积不为负,则可以安全地移动光标。 在这里我们假设,形状的法线面向外。

编辑: 关于交叉点 - 我认为你可以通过检查至少一个交叉点的边缘与光标方向的正常点积是否为负值来解决这个问题

答案 1 :(得分:0)

我认为方法3的代码实际上很好,但是游戏循环中的交叉测试应该过滤出与鼠标位置一致的伪交叉。 即测试if intersect and mouse_position != xy_from_intersect而不是if intersect