10. Separating axis theorem

from pygame import *

def edges_of(vertices):
    edges = []

    N = len(vertices)
    for i in range(N):
        e = vertices[(i + 1) % N] - vertices[i]
        edges.append(e)

    return edges


def orthogonal(v):
    return Vector2(-v.y, v.x)

def is_separating_axis(axis, p1, p2):
    min_p1 = float("inf")
    max_p1 = float("-inf")
    for p in p1:
        projection = p.dot(axis)
        min_p1 = min(min_p1, projection)
        max_p1 = max(max_p1, projection)

    min_p2 = float("inf")
    max_p2 = float("-inf")
    for p in p2:
        projection = p.dot(axis)
        min_p2 = min(min_p2, projection)
        max_p2 = max(max_p2, projection)

    if max_p1 >= min_p2 and max_p2 >= min_p1:
        return False
    else:
        return True


def polygon_collision(P1, P2):
    edges = edges_of(P1) + edges_of(P2)
    orthogonals = []
    for e in edges:
        orthogonals.append(orthogonal(e))

    for axis in orthogonals:
        if is_separating_axis(axis, P1, P2):
            return False
    return True


if __name__ == "__main__":
    screen = display.set_mode([600, 400])

    pos_5gon = Vector2(100, 100)
    pos_3gon = Vector2(300, 250)
    step = 5

    while True:
        screen.fill(Color(0, 0, 0))
        event.poll()
        k = key.get_pressed()

        if k[K_UP]:
            pos_5gon.y -= step
        elif k[K_DOWN]:
            pos_5gon.y += step
        elif k[K_RIGHT]:
            pos_5gon.x += step
        elif k[K_LEFT]:
            pos_5gon.x -= step

        if k[K_w]:
            pos_3gon.y -= step
        elif k[K_s]:
            pos_3gon.y += step
        elif k[K_d]:
            pos_3gon.x += step
        elif k[K_a]:
            pos_3gon.x -= step

        pentagon = []
        v = Vector2(50, 0)
        for i in range(5):
            pentagon.append(v + pos_5gon)
            v = v.rotate(360 // 5)

        triangle = []
        v = Vector2(20, 0)
        for i in range(3):
            triangle.append(v + pos_3gon)
            v = v.rotate(360 // 3)

        color = Color(255, 255, 255)
        if polygon_collision(pentagon, triangle):
            color = Color(255, 0, 0)

        draw.polygon(screen, color, [[int(v.x), int(v.y)] for v in pentagon], 1)
        draw.polygon(screen, color, [[int(v.x), int(v.y)] for v in triangle], 1)

        display.update()
        time.delay(20)