【问题标题】:Pygame 3D Cube translate,movePygame 3D Cube 平移、移动
【发布时间】:2014-05-18 01:05:08
【问题描述】:

我已经制作了跟随 3D 立方体,我需要制作一个平移功能来移动这个立方体,例如用键向上移动到 x 轴,用立方体 y 在轴 y 上移动,在 z 轴上移动,我搜索找到一个翻译功能,但它适用于 2D here 但我的思想栈和我很困惑。

现在我想要跟随,我怎样才能将这个翻译功能调整到我的代码,或者有任何人知道如何移动,将我的立方体转换到下面代码的顶点3?

请人帮忙

import sys, math, pygame

class Point3D:
    def __init__(self, x = 0, y = 0, z = 0):
        self.x, self.y, self.z = float(x), float(y), float(z)

    def rotateX(self, angle):
        """ Rotates the point around the X axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        y = self.y * cosa - self.z * sina
        z = self.y * sina + self.z * cosa
        return Point3D(self.x, y, z)

    def rotateY(self, angle):
        """ Rotates the point around the Y axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        z = self.z * cosa - self.x * sina
        x = self.z * sina + self.x * cosa
        return Point3D(x, self.y, z)

    def rotateZ(self, angle):
        """ Rotates the point around the Z axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        x = self.x * cosa - self.y * sina
        y = self.x * sina + self.y * cosa
        return Point3D(x, y, self.z)

    def project(self, win_width, win_height, fov, viewer_distance):
        """ Transforms this 3D point to 2D using a perspective projection. """
        factor = fov / (viewer_distance + self.z)
        x = self.x * factor + win_width / 2
        y = -self.y * factor + win_height / 2
        return Point3D(x, y, 1)

class Simulation:
    def __init__(self, win_width = 640, win_height = 480):
        pygame.init()

        self.screen = pygame.display.set_mode((win_width, win_height))
        pygame.display.set_caption("3D Wireframe Cube Simulation (http://codeNtronix.com)")

        self.clock = pygame.time.Clock()

        self.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)
            ]

        self.vertices2 = [
            Point3D(-1,-1,-1),
            Point3D(-1,0,-1),
            Point3D(0,0,-1),
            Point3D(0,-1,-1),
            Point3D(-1,0,0),
            Point3D(0,0,0),
            Point3D(0,-1,0),
            Point3D(-1,-1,0)
            ]


        self.vertices3 = [
            Point3D(0,-1,-1),
            Point3D(0,0,-1),
            Point3D(1,0,-1),
            Point3D(1,-1,-1),
            Point3D(0,0,0),
            Point3D(1,0,0),
            Point3D(1,-1,0),
            Point3D(0,-1,0)
            ]

        # Define the vertices that compose each of the 6 faces. These numbers are
        # indices to the vertices list defined above.
        self.faces = [(0,1,2,3),(0,1,4,7),(4,5,6,7),(7,6,3,0),(5,6,3,2)]
        self.faces2 = [(0,1,2,3),(0,1,4,7),(4,5,6,7),(7,6,3,0),(5,6,3,2)]


        self.angleX, self.angleY, self.angleZ = 0, 0, 0

    def run(self):
        """ Main Loop """
        while 1:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:       
                    sys.exit()

            self.clock.tick(50)
            self.screen.fill((0,0,0))

            # Will hold transformed vertices.
            t = []
            t1 = []  

            for v in self.vertices:
                # Rotate the point around X axis, then around Y axis, and finally around Z axis.
                r = v.rotateX(self.angleX).rotateY(self.angleY).rotateZ(self.angleZ)
                # Transform the point from 3D to 2D
                p = r.project(self.screen.get_width(), self.screen.get_height(), 256, 4)
                # Put the point in the list of transformed vertices
                t.append(p)
                x, y = int(p.x), int(p.y)
                self.screen.fill((255,0,0),(x,y,2,2))


            for v1 in self.vertices2:
                # Rotate the point around X axis, then around Y axis, and finally around Z axis.
                r1 = v1.rotateX(self.angleX).rotateY(self.angleY).rotateZ(self.angleZ)
                # Transform the point from 3D to 2D
                p1 = r1.project(self.screen.get_width(), self.screen.get_height(), 256, 4)
                # Put the point in the list of transformed vertices
                t1.append(p1)
                x, y = int(p1.x), int(p1.y)
                self.screen.fill((255,0,0),(x,y,3,3)) 

            for f in self.faces:
                pygame.draw.line(self.screen, (255,255,255), (t[f[0]].x, t[f[0]].y), (t[f[1]].x, t[f[1]].y))
                pygame.draw.line(self.screen, (255,255,255), (t[f[1]].x, t[f[1]].y), (t[f[2]].x, t[f[2]].y))
                pygame.draw.line(self.screen, (255,255,255), (t[f[2]].x, t[f[2]].y), (t[f[3]].x, t[f[3]].y))
                pygame.draw.line(self.screen, (255,255,255), (t[f[3]].x, t[f[3]].y), (t[f[0]].x, t[f[0]].y))


            for f1 in self.faces2:
                pygame.draw.line(self.screen, (255,255,255), (t1[f1[0]].x, t1[f1[0]].y), (t1[f1[1]].x, t1[f1[1]].y))
                pygame.draw.line(self.screen, (255,255,255), (t1[f1[1]].x, t1[f1[1]].y), (t1[f1[2]].x, t1[f1[2]].y))
                pygame.draw.line(self.screen, (255,255,255), (t1[f1[2]].x, t1[f1[2]].y), (t1[f1[3]].x, t1[f1[3]].y))
                pygame.draw.line(self.screen, (255,255,255), (t1[f1[3]].x, t1[f1[3]].y), (t1[f1[0]].x, t1[f1[0]].y))

            self.angleX += 1
            self.angleY += 1
            self.angleZ += 1

            pygame.display.flip()

if __name__ == "__main__":
    Simulation().run()

【问题讨论】:

    标签: python python-2.7 3d pygame pygame-surface


    【解决方案1】:

    我找到了我的问题的答案,还有更多,跟着我可以移动、旋转和缩放一个立方体,你可以找到代码

    herehere

    将页面另存为 .py 在同一文件夹中,运行 displaywireframe3 就可以了。如果您想知道控制键,请检查 displayWireframe3 中的代码。

    【讨论】:

      【解决方案2】:
      import pygame
      import math
      import numpy as np
      import sys
      
      '''
      Not really sure but I think pygame needs to run under Python 3.6
      
      Here is what I used:
      Pycharm - Community Version
      Python Ver:3.6
      Pygame Ver:2.0.1
      Numpy Ver: 1.19.3
      
      Good Luck!
      '''
      print()
      print("Python Ver: " + str(sys.version_info.major) + '.' + str(sys.version_info.minor))
      print("Pygame Ver: " + pygame.__version__)
      print("Numpy Ver:  " + np.__version__)
      
      BLACK = (  0,   0,   0)
      WHITE = (255, 255, 255)
      GREEN = (  0, 255,   0)
      RED   = (  0,   0, 255)
      
      WDT = 640
      HGT = 480
      
      pygame.init()                                     # Set up pygame parameters
      pygame.display.set_caption("Rotating 3D Cube Projection in PYGame")
      screen = pygame.display.set_mode((WDT, HGT))
      
      points = [n for n in range(8)]                   # Define 3D cube
      
      points[0] = [[-1], [-1],  [1]]
      points[1] = [[1],  [-1],  [1]]
      points[2] = [[1],   [1],  [1]]
      points[3] = [[-1],  [1],  [1]]
      points[4] = [[-1], [-1], [-1]]
      points[5] = [[1],  [-1], [-1]]
      points[6] = [[1],   [1], [-1]]
      points[7] = [[-1],  [1], [-1]]
      
      
      def draw_line(i, j, k):                   # Draw lines between edges of cube
          a = k[i]
          b = k[j]
          pygame.draw.line(screen, GREEN, (a[0], a[1]), (b[0], b[1]), 2)
      
      
      angle_x = 0                    # starting x position
      angle_y = 0                    # starting y position
      angle_z = 0                    # starting z position
      
      cube_size = 600                # 300 = small   900 = large
      distance_from_cube = 5         # view point distance - MUST BE GREATER THAN 1
      
      while True:
          screen.fill(BLACK)
      
          for event in pygame.event.get():
              if event.type == pygame.QUIT:    pygame.quit()
              if event.type == pygame.KEYDOWN: pygame.quit()
      
          projected_points = [j for j in range(len(points))]
      
          rotation_x = [[1,                 0,                  0],
                        [0, math.cos(angle_x), -math.sin(angle_x)],
                        [0, math.sin(angle_x),  math.cos(angle_x)]]
      
          rotation_y = [[math.cos(angle_y), 0, -math.sin(angle_y)],
                        [0,                 1,                  0],
                        [math.sin(angle_y), 0, math.cos(angle_y)]]
      
          rotation_z = [[math.cos(angle_z), -math.sin(angle_z), 0],
                        [math.sin(angle_z),  math.cos(angle_z), 0],
                        [0,              0,                     1]]
      
          index = 0
          for point in points:
              rotated_y = np.matmul(rotation_y, point)        # Cube rotation in y axis
              rotated_x = np.matmul(rotation_x, rotated_y)    # Cube rotation in yx axis
              rotated_xyz = np.matmul(rotation_z, rotated_x)  # Cube rotation in yxz axis
      
              z = 1 / (distance_from_cube - rotated_xyz[2][0])
              projection_matrix = [[z, 0, 0], [0, z, 0]]
              projected_2d = np.matmul(projection_matrix, rotated_xyz)
      
              x = int(projected_2d[0][0] * cube_size) + WDT // 2   # x,y 2D projection
              y = int(projected_2d[1][0] * cube_size) + HGT // 2
      
              projected_points[index] = [x, y]
              index += 1
              pygame.draw.circle(screen, RED, (x, y), 4)
      
          for m in range(4):                                 # Draw lines to connect dots/circles
              draw_line(m,       (m+1)%4, projected_points)
              draw_line(m+4, (m+1)%4 + 4, projected_points)
              draw_line(m,           m+4, projected_points)
      
          angle_x += 0.00030       # Rotation speed about x axis
          angle_y += 0.00020       # Rotation speed about y axis
          angle_z += 0.00010       # Rotation speed about z axis
      
          pygame.display.update()
      
      

      【讨论】:

      • 欢迎来到 Stack Overflow。虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请编辑您的答案以添加解释并说明适用的限制和假设。
      猜你喜欢
      • 2012-12-14
      • 1970-01-01
      • 1970-01-01
      • 2022-12-04
      • 1970-01-01
      • 2023-01-04
      • 2014-12-02
      • 1970-01-01
      • 2016-05-19
      相关资源
      最近更新 更多