教你用python做用鼠标旋转的正方体
效果如下:
能用鼠标控制,老规矩先讲思路:
思路由作者老程个人想法提出,仅供参考
以下是这个程序实现用鼠标控制旋转的正方体并绘制其外部轮廓的主要思路:
1. 初始化:
-
导入所需的 pygame 和 numpy 库。
-
定义屏幕的尺寸、颜色、正方体的顶点和面等基本信息。
-
设置初始的旋转角度。
2. 矩阵操作:
-
定义投影矩阵。
-
根据鼠标的移动计算旋转角度。
-
通过矩阵乘法实现正方体顶点的旋转。
3. 绘制部分:
-
在主循环中,先处理事件,如检测是否退出程序、鼠标按下等。
-
根据鼠标移动更新旋转角度。
-
计算旋转和投影后的顶点位置。
-
绘制背景为黑色。
-
绘制正方体的面为白色。
-
对于外部轮廓的绘制,通过明确正方体 12 条边的顶点顺序,将投影后的顶点连接成线来绘制轮廓,线条颜色为红色,宽度为 2。
-
使用 pygame.display.flip() 刷新屏幕显示。
-
通过 clock.tick(60) 控制帧率。
总之,整个程序的核心是通过数学运算实现正方体的旋转和投影,并使用 pygame 的绘图功能将其展示在屏幕上,同时根据鼠标操作实现交互。
接下来就是代码实践了
import pygame
import numpy as np
# 初始化 Pygame
pygame.init()
# 屏幕尺寸
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
OUTLINE_COLOR = (255, 0, 0) # 轮廓颜色,这里设置为红色
# 正方体的顶点
vertices = np.array([
[-1, -1, -1],
[1, -1, -1],
[1, 1, -1],
[-1, 1, -1],
[-1, -1, 1],
[1, -1, 1],
[1, 1, 1],
[-1, 1, 1]
])
# 正方体的面
faces = np.array([
[0, 1, 2, 3],
[1, 5, 6, 2],
[5, 4, 7, 6],
[4, 0, 3, 7],
[3, 2, 6, 7],
[4, 5, 1, 0]
])
# 初始旋转角度
rotation_x = 0
rotation_y = 0
# 投影矩阵
projection_matrix = np.array([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
])
# 屏幕
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Rotating Cube")
clock = pygame.time.Clock()
# 鼠标按下标志
mouse_pressed = False
# 主循环
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_pressed = True
elif event.type == pygame.MOUSEBUTTONUP:
mouse_pressed = False
if mouse_pressed:
mouse_x, mouse_y = pygame.mouse.get_rel()
rotation_x += mouse_y * 0.1
rotation_y += mouse_x * 0.1
# 旋转矩阵
rotation_matrix_x = np.array([
[1, 0, 0],
[0, np.cos(rotation_x), -np.sin(rotation_x)],
[0, np.sin(rotation_x), np.cos(rotation_x)]
])
rotation_matrix_y = np.array([
[np.cos(rotation_y), 0, np.sin(rotation_y)],
[0, 1, 0],
[-np.sin(rotation_y), 0, np.cos(rotation_y)]
])
# 应用旋转
rotated_vertices = np.dot(vertices, rotation_matrix_x)
rotated_vertices = np.dot(rotated_vertices, rotation_matrix_y)
# 投影
projected_vertices = np.dot(rotated_vertices, projection_matrix)
# 绘制背景
screen.fill(BLACK)
# 绘制正方体的面
for face in faces:
pygame.draw.polygon(screen, WHITE, [(projected_vertices[vertex][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[vertex][1] * 100 + SCREEN_HEIGHT / 2) for vertex in face])
# 绘制正方体的外部轮廓
outline_vertices = [
(projected_vertices[0][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[0][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[1][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[1][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[2][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[2][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[3][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[3][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[0][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[0][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[4][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[4][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[5][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[5][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[1][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[1][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[2][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[2][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[6][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[6][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[7][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[7][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[3][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[3][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[4][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[4][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[5][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[5][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[6][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[6][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[7][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[7][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[0][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[0][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[3][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[3][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[1][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[1][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[2][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[2][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[4][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[4][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[7][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[7][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[5][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[5][1] * 100 + SCREEN_HEIGHT / 2),
(projected_vertices[6][0] * 100 + SCREEN_WIDTH / 2, projected_vertices[6][1] * 100 + SCREEN_HEIGHT / 2),
]
for i in range(0, len(outline_vertices) - 1, 2):
pygame.draw.line(screen, OUTLINE_COLOR, outline_vertices[i], outline_vertices[i + 1], 2) # 2 为线条宽度
pygame.display.flip()
clock.tick(60)
pygame.quit()
效果已展示(如上图)
下面是创新建议:
以下是针对这个程序的一些创新建议:
- 材质和光照效果
-
为正方体添加不同的材质,例如金属、木质或塑料质感。
-
引入简单的光照模型,使正方体在旋转时表面的明暗效果发生变化,增强立体感和真实感。
- 多物体交互
-
增加多个可旋转的正方体,它们之间可以相互碰撞或产生某种关联的运动。
-
或者添加其他形状的物体,如球体、锥体等,丰富场景。
- 动画效果
- 除了手动旋转,添加一些自动的动画效果,例如正方体缓慢地缩放、变色或变形。
- 纹理映射
- 为正方体的表面添加图像纹理,比如地图、图案等,使其更加生动和有趣。
- 视角切换
- 实现不同的视角切换,如俯视、仰视、侧视等,或者允许用户自由调整视角。
- 交互方式
-
除了鼠标控制,添加键盘控制选项,例如特定的按键可以加速或减速旋转,或者改变旋转轴。
-
支持触摸屏幕操作,适用于移动设备。
- 数据可视化应用
- 将正方体的旋转和展示与数据相关联,例如根据实时数据改变正方体的颜色、大小或旋转速度,用于数据可视化展示。
- 物理模拟
- 引入简单的物理模拟,例如重力、摩擦力等,使正方体的运动更加真实和有趣。
- 保存和分享
- 增加保存当前正方体状态或整个场景的功能,以便用户可以分享他们创建的独特配置。
- 3D 场景扩展
- 构建一个更复杂的 3D 场景,添加背景、地面、其他装饰物等,使正方体处于一个更丰富的环境中。
最后,请大家多多支持老程,接下来会展示更多的作品,望大家多多支持,谢谢!!!