Exemple #1
0
def aabb_poly(A, B, collision_class=Collision):
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    A_poly = Rectangle(A.rect_coords)
    col = collision_poly(A_poly, B)
    if col is not None:
        return collision_class(A, B, pos=col.pos, normal=col.normal,
                               delta=col.delta)
    else:
        return None
Exemple #2
0
def circle_aabb(A, B):
    '''Reutiliza a lógica de Circle/Poly para realizar a colisão com AABBs'''
    
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None
    
    B_poly = Rectangle(bbox=B.bbox)
    col = circle_poly(A, B_poly)
    if col is not None:
        return Collision(A, B, pos=col.pos, normal=col.normal, delta=col.delta)
    else:
        return None
Exemple #3
0
def aabb_poly(A, B):
    '''Implementa a colisão entre um polígono arbitrário e uma caixa AABB'''

    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    A_poly = Rectangle(bbox=A.bbox)
    col = collision_poly(A_poly, B)
    if col is not None:
        return Collision(A, B, pos=col.pos, normal=col.normal, delta=col.delta)
    else:
        return None
Exemple #4
0
def circle_poly(A, B):
    '''Implementa a colisão entre um círculo arbitrário um polígono.
    
    A normal resultante sempre sai do círculo na direção do polígono.
    '''
    
    # Verifica as AABB
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    # Procura o ponto mais próximo de B
    vertices = B.vertices
    N = len(vertices)
    center = A.pos
    normals = [(i, v - center, v) for i, v in enumerate(vertices)]
    idx, _, pos = min(normals, key=lambda x: x[1].norm())
    
    # A menor distância para o centro pode ser do tipo vértice-ponto ou 
    # aresta-ponto. Assumimos o vértice inicialmente.
    distance = (pos - center).norm()
    
    # Agora verificamos cada face
    P0 = pos
    P = vertices[(idx - 1) % N]
    v = center - P
    u = P0 - P
    L = u.norm()
    delta = v.cross(u) / L
    
    # Verifica se o ponto mais próximo se encontra no segmento
    if delta < distance and u.dot(v) < L**2:
        pos = P + (u.dot(v) / L**2) * u
        distance = delta
    
    # Mesmo teste para a face do ponto posterior
    P = vertices[(idx + 1) % N]
    v = center - P
    u = P0 - P
    L = u.norm()
    delta = -v.cross(u) / L
    if delta < distance and u.dot(v) < L ** 2:
        pos = P + (u.dot(v) / L ** 2) * u
        distance = delta
    
    # Verificamos se houve colisão ou não na direção esperada
    delta = A.radius - distance
    normal = (pos - center).normalized()
    
    if delta > 0:
        return Collision(A, B, pos=pos, normal=normal, delta=delta)
    else:
        return None
Exemple #5
0
def aabb_poly(A, B, collision_class=Collision):
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    A_poly = Rectangle(A.rect_coords)
    col = collision_poly(A_poly, B)
    if col is not None:
        return collision_class(A,
                               B,
                               pos=col.pos,
                               normal=col.normal,
                               delta=col.delta)
    else:
        return None
Exemple #6
0
def circle_poly(A, B, collision_class=Collision):
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    # Searches for the nearest point to B
    vertices = B.vertices
    center = A.pos
    normals = [(i, v - center, v) for i, v in enumerate(vertices)]
    idx, _, pos = min(normals, key=lambda x: x[1].norm())

    # The smaller distance to the center can be vertex-center or side-center.
    # We need to detect this.
    separation = (pos - center).norm()

    # Verify each face
    P0 = pos
    N = len(vertices)
    for idx in [(idx - 1) % N, (idx + 1) % N]:
        P = vertices[idx]
        v = center - P
        u = P0 - P
        L = u.norm()
        distance = abs(v.cross(u) / L)

        # Verify if closest point is inside segment
        if distance < separation and u.dot(v) < L ** 2:
            pos = P + (u.dot(v) / L ** 2) * u
            separation = distance

    # Verify if there is collision in the direction of smaller separation
    delta = A.radius - separation
    normal = (pos - center).normalize()

    if delta > 0:
        return collision_class(A, B, pos=pos, normal=normal, delta=delta)
    else:
        return None
Exemple #7
0
def circle_poly(A, B, collision_class=Collision):
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    # Searches for the nearest point to B
    vertices = B.vertices
    center = A.pos
    normals = [(i, v - center, v) for i, v in enumerate(vertices)]
    idx, _, pos = min(normals, key=lambda x: x[1].norm())

    # The smaller distance to the center can be vertex-center or side-center.
    # We need to detect this.
    separation = (pos - center).norm()

    # Verify each face
    P0 = pos
    N = len(vertices)
    for idx in [(idx - 1) % N, (idx + 1) % N]:
        P = vertices[idx]
        v = center - P
        u = P0 - P
        L = u.norm()
        distance = abs(v.cross(u) / L)

        # Verify if closest point is inside segment
        if distance < separation and u.dot(v) < L**2:
            pos = P + (u.dot(v) / L**2) * u
            separation = distance

    # Verify if there is collision in the direction of smaller separation
    delta = A.radius - separation
    normal = (pos - center).normalize()

    if delta > 0:
        return collision_class(A, B, pos=pos, normal=normal, delta=delta)
    else:
        return None