import pygame
import math

# Initialize Pygame
pygame.init()

# Screen dimensions
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("3D Cube in Pygame")

# Define the vertices of the cube
vertices = [
    [-1, -1, -1],
    [ 1, -1, -1],
    [ 1,  1, -1],
    [-1,  1, -1],
    [-1, -1,  1],
    [ 1, -1,  1],
    [ 1,  1,  1],
    [-1,  1,  1]
]

# Define the edges connecting the vertices
edges = [
    (0, 1), (1, 2), (2, 3), (3, 0),
    (4, 5), (5, 6), (6, 7), (7, 4),
    (0, 4), (1, 5), (2, 6), (3, 7)
]

# Perspective projection function
def project(x, y, z):
    fov = 500  # Field of view
    distance = 5
    factor = fov / (distance + z)
    x = x * factor + width / 2
    y = -y * factor + height / 2
    return x, y

# Function to rotate points around the X axis
def rotateX(point, angle):
    x, y, z = point
    y = y * math.cos(angle) - z * math.sin(angle)
    z = y * math.sin(angle) + z * math.cos(angle)
    return x, y, z

# Function to rotate points around the Y axis
def rotateY(point, angle):
    x, y, z = point
    x = x * math.cos(angle) + z * math.sin(angle)
    z = -x * math.sin(angle) + z * math.cos(angle)
    return x, y, z

# Function to rotate points around the Z axis
def rotateZ(point, angle):
    x, y, z = point
    x = x * math.cos(angle) - y * math.sin(angle)
    y = x * math.sin(angle) + y * math.cos(angle)
    return x, y, z

# Main loop
running = True
angleX, angleY, angleZ = 0, 0, 0
clock = pygame.time.Clock()

color_change_rate = 0.01
color_phase = 0

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill((0, 0, 0))

    # Rotate and project the cube vertices
    transformed_vertices = []
    for vertex in vertices:
        rotated = rotateX(vertex, angleX)
        rotated = rotateY(rotated, angleY)
        rotated = rotateZ(rotated, angleZ)
        projected = project(*rotated)
        transformed_vertices.append(projected)

    # Calculate color based on the phase
    color_phase += color_change_rate
    r = (math.sin(color_phase) * 127 + 128) % 256
    g = (math.sin(color_phase + 2 * math.pi / 3) * 127 + 128) % 256
    b = (math.sin(color_phase + 4 * math.pi / 3) * 127 + 128) % 256
    color = (int(r), int(g), int(b))

    # Draw the edges of the cube
    for edge in edges:
        points = []
        for vertex in edge:
            points.append(transformed_vertices[vertex])
        pygame.draw.line(screen, color, points[0], points[1], 2)

    pygame.display.flip()
    clock.tick(60)
    angleX += 0.01
    angleY += 0.01
    angleZ += 0.01

pygame.quit()