|
|
import pygame
import math
# 初始化 Pygame
pygame.init()
# 屏幕设置
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pygame 3D Cube Demo")
clock = pygame.time.Clock()
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
ORANGE = (255, 165, 0)
# 3D 坐标点类
class Point3D:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
# 立方体的顶点 (中心在 0,0,0)
vertices = [
Point3D(-1, -1, -1),
Point3D( 1, -1, -1),
Point3D( 1, 1, -1),
Point3D(-1, 1, -1),
Point3D(-1, -1, 1),
Point3D( 1, -1, 1),
Point3D( 1, 1, 1),
Point3D(-1, 1, 1)
]
# 定义哪些点连接成边 (索引对应 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) # 连接前后
]
def project(point, width, height, scale, angle_x, angle_y):
"""
核心函数:将 3D 点投影到 2D 屏幕上
包含旋转矩阵计算
"""
x = point.x
y = point.y
z = point.z
# 绕 X 轴旋转
# y' = y*cos(a) - z*sin(a)
# z' = y*sin(a) + z*cos(a)
ry = y * math.cos(angle_x) - z * math.sin(angle_x)
rz = y * math.sin(angle_x) + z * math.cos(angle_x)
# 绕 Y 轴旋转 (使用上面旋转后的 z: rz)
# x' = x*cos(a) + z*sin(a)
# z' = -x*sin(a) + z*cos(a)
rx = x * math.cos(angle_y) + rz * math.sin(angle_y)
rz = -x * math.sin(angle_y) + rz * math.cos(angle_y)
# 简单的透视投影 (z 越大,物体越小)
# 这里的 4 是为了把物体推远一点,防止除以零
f = 4
z_factor = 1 / (f - rz)
# 转换到屏幕坐标
# 加上 width/2 和 height/2 是为了把原点移到屏幕中心
px = int(rx * z_factor * scale + width / 2)
py = int(ry * z_factor * scale + height / 2)
return (px, py)
# 主循环变量
running = True
angle_x = 0
angle_y = 0
scale = 400 # 放大倍数
while running:
clock.tick(60) # 限制 60 FPS
screen.fill(BLACK) # 清屏
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 自动旋转
angle_x += 0.01
angle_y += 0.01
# 计算所有投影后的 2D 点
projected_points = []
for v in vertices:
p = project(v, WIDTH, HEIGHT, scale, angle_x, angle_y)
projected_points.append(p)
# 画出顶点(可选)
pygame.draw.circle(screen, ORANGE, p, 5)
# 画出边
for edge in edges:
p1 = projected_points[edge[0]]
p2 = projected_points[edge[1]]
pygame.draw.line(screen, WHITE, p1, p2, 2)
pygame.display.update()
pygame.quit()
|
|