Exemplo n.º 1
0
def collision_aabb(A, B):
    '''Retorna uma colisão com o objeto other considerando apenas a caixas
    de contorno alinhadas ao eixo.'''

    # Detecta colisão pelas sombras das caixas de contorno
    rx, ry = B._pos - A._pos
    shadowx = A._delta_x + B._delta_x - abs(rx)
    shadowy = A._delta_y + B._delta_y - abs(ry)
    if shadowx <= 0 or shadowy <= 0:
        return None

    # Calcula ponto de colisão
    x_col = max(A.xmin, B.xmin) + shadowx / 2.
    y_col = max(A.ymin, B.ymin) + shadowy / 2.
    pos_col = Vec2(x_col, y_col)

    # Define sinal dos vetores normais: colisões tipo PONG
    if shadowx > shadowy:
        n = Vec2(0, (1 if A.ymin < B.ymin else -1))
        delta = shadowy
    else:
        n = Vec2((1 if A.xmin < B.xmin else -1), 0)
        delta = shadowx

    return Collision(A, B, pos=pos_col, normal=n, delta=delta)
Exemplo n.º 2
0
def circle_aabb(A, B):
    # TODO: implementar direito, está utilizando AABBs
    r = A.cbb_radius
    x, y = A._pos
    Axmin, Axmax = x - r, x + r
    Aymin, Aymax = y - r, y + r

    x, y = B._pos
    dx, dy = B._delta_x, B._delta_y
    Bxmin, Bxmax = x - dx, x + dx
    Bymin, Bymax = y - dy, y + dy

    shadowx = min(Axmax, Bxmax) - max(Axmin, Bxmin)
    shadowy = min(Aymax, Bymax) - max(Aymin, Bymin)
    if shadowx < 0 or shadowy < 0:
        return None

    # Calcula ponto de colisão
    x_col = max(A.xmin, B.xmin) + shadowx / 2.
    y_col = max(A.ymin, B.ymin) + shadowy / 2.
    pos_col = Vec2(x_col, y_col)

    # Define sinal dos vetores normais: colisões tipo PONG
    if shadowx > shadowy:
        n = Vec2(0, (1 if A.ymin < B.ymin else -1))
    else:
        n = Vec2((1 if A.xmin < B.xmin else -1), 0)

    return Collision(A, B, pos=pos_col, normal=n)
Exemplo n.º 3
0
def circle_collision(A, B):
    '''Testa a colisão pela distância dos centros'''

    delta = B.pos - A.pos
    if delta.norm() < A.radius + B.radius:
        n = delta.normalized()
        D = A.radius + B.radius - delta.norm()
        pos = A.pos + (A.radius - D / 2) * n
        return Collision(A, B, pos=pos, n=n)
    else:
        return None
Exemplo n.º 4
0
def collision_circle(A, B):
    '''Testa a colisão pela distância dos centros'''

    rA = A.cbb_radius
    rB = B.cbb_radius
    delta = B._pos - A._pos
    if delta.norm() < rA + rB:
        n = delta.normalize()
        D = rA + rB - delta.norm()
        pos = A._pos + (rA - D / 2) * n
        return Collision(A, B, pos=pos, normal=n, delta=D)
    else:
        return None
Exemplo n.º 5
0
def get_collision_generic(A, B):
    '''Retorna uma colisão genérica definido pela CBB dos objetos A e B'''

    rA = A.cbb_radius
    rB = B.cbb_radius
    delta = B._pos - A._pos
    if delta.norm() < rA + rB:
        n = delta.normalize()
        D = rA + rB - delta.norm()
        pos = A._pos + (rA - D / 2) * n
        return Collision(A, B, pos=pos, normal=n, delta=D)
    else:
        return None
Exemplo n.º 6
0
def get_collision_poly(A, B, directions=None):
    '''Implementa a colisão entre dois polígonos arbitrários'''

    # Cria a lista de direções a partir das normais do polígono
    if directions is None:
        if A.num_normals + B.num_normals < 9:
            directions = A.get_normals() + B.get_normals()
        else:
            directions = DEFAULT_DIRECTIONS

    # Testa se há superposição de sombras em todas as direções consideradas
    # e calcula o menor valor para sombra e a direção normal
    min_shadow = float('inf')
    norm = None
    for u in directions:
        A_coords = [round(dot(pt, u), 6) for pt in A.vertices]
        B_coords = [round(dot(pt, u), 6) for pt in B.vertices]
        Amax, Amin = max(A_coords), min(A_coords)
        Bmax, Bmin = max(B_coords), min(B_coords)
        minmax, maxmin = min(Amax, Bmax), max(Amin, Bmin)
        shadow = minmax - maxmin
        if shadow < 0:
            return None
        elif shadow < min_shadow:
            min_shadow = shadow
            norm = u

    # Determina o sentido da normal
    if dot(A.pos, norm) > dot(B.pos, norm):
        norm = -norm

    # Computa o polígono de intersecção e usa o seu centro de massa como ponto
    # de colisão
    try:
        clipped = clip(A.vertices, B.vertices)
    # não houve superposição (talvez por usar normais aproximadas)
    except ValueError:
        return None

    if area(clipped) == 0:
        return None
    col_pt = center_of_mass(clipped)
    return Collision(A, B, col_pt, norm, min_shadow)
Exemplo n.º 7
0
def collision_aabb(A, B):
    # Detects collision using bounding box shadows.
    x0, x1 = max(A.xmin, B.xmin), min(A.xmax, B.xmax)
    y0, y1 = max(A.ymin, B.ymin), min(A.ymax, B.ymax)
    dx = x1 - x0
    dy = y1 - y0
    if x1 < x0 or y1 < y0:
        return None

    # Chose collision center as the center point in the intersection
    pos = Vec2((x1 + x0) / 2, (y1 + y0) / 2)

    # Normal is the direction with smallest penetration
    if dy < dx:
        delta = dy
        normal = Vec2(0, (1 if A.pos.y < B.pos.y else -1))
    else:
        delta = dx
        normal = Vec2((1 if A.pos.x < B.pos.x else -1), 0)

    return Collision(A, B, pos=pos, normal=normal, delta=delta)