Aug-27-2021, 11:42 AM
A pygame program that tumbles a cube. Rotations about x, y and z.
import pygame, math from pygame.locals import * class Point(): '''A point in space''' def __init__(self, x, y, z): self.x = x self.y = y self.z = z def projection(self): '''Return projection on xy plane. Not doing perspective''' return self.x, self.y def move(self, x=0, y=0, z=0): '''Move self in x, y and z''' self.x += x self.y += y self.z += z def rotate_x(self, degrees, center=(0, 0, 0)): '''Rotate self about x axis degrees is angle of rotation measured in degrees center is the center of rotation ''' cx, cy, cz = center y = self.y - cy z = self.z - cz d = math.hypot(y, z) theta = math.atan2(y, z) + degrees * math.pi/180 self.z = cz + d * math.cos(theta) self.y = cy + d * math.sin(theta) def rotate_y(self, degrees, center=(0, 0, 0)): '''Rotate self about y axis degrees is angle of rotation measured in degrees center is the center of rotation ''' cx, cy, cz = center x = self.x - cx z = self.z - cz d = math.hypot(x, z) theta = math.atan2(x, z) + degrees * math.pi/180 self.z = cz + d * math.cos(theta) self.x = cx + d * math.sin(theta) def rotate_z(self, degrees, center=(0, 0, 0)): '''Rotate self about z axis degrees is angle of rotation measured in degrees center is the center of rotation ''' cx, cy, cz = center x = self.x - cx y = self.y - cy d = math.hypot(y, x) theta = math.atan2(y, x) + degrees * math.pi/180 self.x = cx + d * math.cos(theta) self.y = cy + d * math.sin(theta) def __str__(self): return f'({self.x}, {self.y}, {self.z})' class Cube(): '''A 3D cube''' def __init__(self, size, center=(0, 0, 0)): x, y, z = center a = size/2 self.points = [ Point(x-a, y-a, z+a), Point(x+a, y-a, z+a), Point(x+a, y+a, z+a), Point(x-a, y+a, z+a), Point(x-a, y-a, z-a), Point(x+a, y-a, z-a), Point(x+a, y+a, z-a), Point(x-a, y+a, z-a), ] def center(self): '''Calculate center of cube''' x = y = z = 0 for point in self.points: x += point.x y += point.y z += point.z return x/8, y/8, z/8 def move(self, x=0, y=0, z=0): '''Move cube in x, y and z''' for point in self.points: point.move(x, y, z) def rotate_x(self, degrees, center=None): '''Rotate self about x axis degrees is angle of rotation measured in degrees center is the center of rotation. If center not provided rotate about self.center. ''' if center is None: center = self.center() for point in self.points: point.rotate_x(degrees, center) def rotate_y(self, degrees, center=None): '''Rotate self about y axis degrees is angle of rotation measured in degrees center is the center of rotation. If center not provided rotate about self.center. ''' if center is None: center = self.center() for point in self.points: point.rotate_y(degrees, center) def rotate_z(self, degrees, center=None): '''Rotate self about z axis degrees is angle of rotation measured in degrees center is the center of rotation. If center not provided rotate about self.center. ''' if center is None: center = self.center() for point in self.points: point.rotate_z(degrees, center) def draw(self, surface, color=(255, 255, 255)): '''Draw self on surface''' for a, b in zip([0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3], [1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7]): pygame.draw.line(surface, color, self.points[a].projection(), self.points[b].projection()) def __str__(self): return f"{{{', '.join([str(point) for point in self.points])}}}" FPS = 30 pygame.init() DISPLAYSURF = pygame.display.set_mode((200, 200)) pygame.display.set_caption('Cube') fpsClock = pygame.time.Clock() cube = Cube(60, (160, 100, 0)) running = True while running: for event in pygame.event.get(): if event.type == QUIT: running = False break DISPLAYSURF.fill((0, 0, 0)) cube.rotate_x(1) cube.rotate_y(1) cube.rotate_z(1, (100, 100, 0)) cube.draw(DISPLAYSURF) pygame.display.flip() fpsClock.tick(FPS) pygame.quit()