演示動畫:https://life.mdjsjd.me/2024/12/27/3d-cube-animation/
一個使用Python和Pygame制作的炫酷3D立方體動畫效果。結合了多種視覺特效,包括:
- 動態旋轉的3D立方體
- 炫彩漸變的顏色系統
- 星空背景粒子效果
- 動態殘影拖尾效果
- 深度透視投影
主要特性
- 動態變換: 立方體會進行多維度旋轉和形變
- 顏色系統: 支持多種配色方案的平滑漸變
- 星空背景: 動態的星空粒子背景效果
- 視覺特效: 包含殘影、脈沖等視覺效果
實現細節
該動畫主要由以下幾個核心類組成:
ColorPalette
: 處理顏色漸變StarField
: 生成星空背景AdvancedCubeAnimation
: 控制立方體變換與渲染
使用了多種數學變換矩陣實現3D效果:
- 旋轉矩陣
- 錯切變換
- 透視投影
運行方式
1.安裝依賴:
pip install pygame numpy opencv-python
2.代碼:
import pygame
import math
import numpy as np
import random
import cv2
import os# 初始化Pygame
pygame.init()# 屏幕設置
WIDTH, HEIGHT = 1200, 800
screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.DOUBLEBUF | pygame.HWSURFACE)
pygame.display.set_caption("🚀 究極炫酷3D立方體宇宙 🌌")
clock = pygame.time.Clock()# 顏色和漸變
class ColorPalette:def __init__(self):self.palettes = [[(255, 50, 50), (50, 255, 50), (50, 50, 255)], # 經典RGB[(255, 100, 0), (255, 200, 0), (200, 0, 255)], # 霓虹[(0, 255, 255), (255, 0, 255), (255, 255, 0)], # 賽博朋克[(100, 0, 255), (0, 255, 100), (255, 0, 100)], # 科技感]self.current_palette = random.choice(self.palettes)self.transition_speed = 0.02self.color_index = 0self.next_color_index = (self.color_index + 1) % len(self.current_palette)self.color_progress = 0def get_interpolated_color(self):start_color = self.current_palette[self.color_index]end_color = self.current_palette[self.next_color_index]r = start_color[0] + (end_color[0] - start_color[0]) * self.color_progressg = start_color[1] + (end_color[1] - start_color[1]) * self.color_progressb = start_color[2] + (end_color[2] - start_color[2]) * self.color_progressself.color_progress += self.transition_speedif self.color_progress >= 1:self.color_progress = 0self.color_index = self.next_color_indexself.next_color_index = (self.color_index + 1) % len(self.current_palette)return (int(r), int(g), int(b))# 背景星空特效
class StarField:def __init__(self, num_stars=200):self.stars = []for _ in range(num_stars):x = random.randint(0, WIDTH)y = random.randint(0, HEIGHT)z = random.uniform(0, 1)self.stars.append([x, y, z])def move_stars(self):for star in self.stars:star[2] -= 0.05if star[2] <= 0:star[0] = random.randint(0, WIDTH)star[1] = random.randint(0, HEIGHT)star[2] = 1def draw(self, screen):for star in self.stars:size = int((1 - star[2]) * 3)brightness = int(255 * (1 - star[2]))color = (brightness, brightness, brightness)pygame.draw.circle(screen, color, (int(star[0]), int(star[1])), size)# 3D變換矩陣(增加更多變換方式)
def create_transformation_matrices():matrices = {'rotate_x': lambda angle: np.array([[1, 0, 0],[0, math.cos(angle), -math.sin(angle)],[0, math.sin(angle), math.cos(angle)]]),'rotate_y': lambda angle: np.array([[math.cos(angle), 0, math.sin(angle)],[0, 1, 0],[-math.sin(angle), 0, math.cos(angle)]]),'rotate_z': lambda angle: np.array([[math.cos(angle), -math.sin(angle), 0],[math.sin(angle), math.cos(angle), 0],[0, 0, 1]]),'shear_x': lambda s: np.array([[1, s, 0],[0, 1, 0],[0, 0, 1]]),'shear_y': lambda s: np.array([[1, 0, 0],[s, 1, 0],[0, 0, 1]])}return matrices# 立方體生成器(增加隨機性和復雜性)
def create_dynamic_cube(size=1, complexity=1):half = size / 2base_vertices = np.array([[-half, -half, -half],[half, -half, -half],[half, half, -half],[-half, half, -half],[-half, -half, half],[half, -half, half],[half, half, half],[-half, half, half]])# 隨機擾動頂點if complexity > 0:noise = np.random.uniform(-complexity * 0.1, complexity * 0.1, base_vertices.shape)base_vertices += noisereturn base_vertices# 投影函數(改進的透視投影)
def advanced_project(point, distance=5, width=WIDTH, height=HEIGHT):x, y, z = point# 非線性深度縮放scale_factor = 1 / (1 + math.exp(-z))perspective_factor = distance / (distance + z + 0.1)x_proj = x * perspective_factor * width * 0.3y_proj = y * perspective_factor * height * 0.3return (int(x_proj + width / 2),int(y_proj + height / 2),scale_factor)# 主動畫類(增加更多動態效果)
class AdvancedCubeAnimation:def __init__(self):self.matrices = create_transformation_matrices()self.cube = create_dynamic_cube(complexity=1.5)self.color_palette = ColorPalette()self.starfield = StarField()# 多樣的動畫參數self.rotation_params = {'x': {'angle': 0, 'speed': 0.02, 'amplitude': 1},'y': {'angle': 0, 'speed': 0.015, 'amplitude': 1.2},'z': {'angle': 0, 'speed': 0.01, 'amplitude': 0.8}}# 額外的變形參數self.morph_params = {'shear_x': 0,'shear_y': 0,'morph_speed_x': 0.05,'morph_speed_y': 0.03}# 炫酷特效參數self.effect_params = {'pulse_scale': 1,'pulse_speed': 0.02,'trail_mode': False,'glitch_mode': False}def update_transformations(self):# 更新旋轉for axis, params in self.rotation_params.items():params['angle'] += params['speed'] * params['amplitude']# 更新形變self.morph_params['shear_x'] = math.sin(pygame.time.get_ticks() * 0.001) * 0.5self.morph_params['shear_y'] = math.cos(pygame.time.get_ticks() * 0.002) * 0.5# 脈沖效果self.effect_params['pulse_scale'] = 1 + math.sin(pygame.time.get_ticks() * self.effect_params['pulse_speed']) * 0.2def apply_transformations(self):# 組合變換矩陣Rx = self.matrices['rotate_x'](self.rotation_params['x']['angle'])Ry = self.matrices['rotate_y'](self.rotation_params['y']['angle'])Rz = self.matrices['rotate_z'](self.rotation_params['z']['angle'])Sx = self.matrices['shear_x'](self.morph_params['shear_x'])Sy = self.matrices['shear_y'](self.morph_params['shear_y'])# 組合旋轉和形變transformation = Rz @ Ry @ Rx @ Sy @ Sxreturn self.cube @ transformation.Tdef draw_cube(self, screen):# 應用變換transformed_cube = self.apply_transformations()# 立方體的邊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) # 連接邊]# 獲取動態顏色base_color = self.color_palette.get_interpolated_color()# 繪制邊for edge in edges:start = transformed_cube[edge[0]]end = transformed_cube[edge[1]]start_2d = advanced_project(start)end_2d = advanced_project(end)# 根據深度調整線條depth_factor = start_2d[2]line_width = max(1, int(4 * depth_factor))# 應用脈沖和顏色變化pulse_color = tuple(int(c * (0.7 + depth_factor * 0.3)) for c in base_color)pygame.draw.line(screen, pulse_color, start_2d[:2], end_2d[:2], line_width)def main():# 初始化animation = AdvancedCubeAnimation()# 視頻導出準備os.makedirs('output', exist_ok=True)# OpenCV視頻寫入器fourcc = cv2.VideoWriter_fourcc(*'mp4v')out = cv2.VideoWriter('output/3d_cube_animation.mp4', fourcc, 60.0, (WIDTH, HEIGHT))# 創建背景background = pygame.Surface(screen.get_size())background = background.convert()# 總幀數和持續時間frame_count = 0max_frames = 600 # 10秒 * 60幀while frame_count < max_frames:# 背景處理(拖尾效果)background.set_alpha(50)screen.blit(background, (0, 0))# 繪制星空背景animation.starfield.move_stars()animation.starfield.draw(screen)# 繪制立方體animation.update_transformations()animation.draw_cube(screen)# 更新顯示pygame.display.flip()# 捕獲幀frame_surface = screen.copy()frame_data = pygame.surfarray.array3d(frame_surface)frame_data = frame_data.transpose([1, 0, 2])# 轉換為 OpenCV 格式 (BGR)frame_bgr = cv2.cvtColor(frame_data, cv2.COLOR_RGB2BGR)out.write(frame_bgr)frame_count += 1clock.tick(60)# 釋放資源out.release()pygame.quit()print("視頻導出完成!保存在 output/3d_cube_animation.mp4")if __name__ == "__main__":main()