PyGame 可以做 3d 吗?

发布于 2024-10-15 19:04:55 字数 102 浏览 5 评论 0原文

我似乎无法在任何地方找到这个问题的答案。我意识到你必须使用 PyOpenGL 或类似的东西来做 OpenGL 的东西,但我想知道是否有可能在没有任何其他依赖的情况下做非常基本的 3D 图形。

I can't seem to find the answer to this question anywhere. I realize that you have to use PyOpenGL or something similar to do OpenGL stuff, but I was wondering if its possible to do very basic 3D graphics without any other dependencies.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

残月升风 2024-10-22 19:04:55

不,Pygame 是 SDL 的包装器,SDL 是一个 2D api。 Pygame 不提供任何 3D 功能,而且可能永远不会。

Python 的 3D 库包括 Panda3DDirectPython ,尽管它们使用起来可能相当复杂,尤其是后者。

No, Pygame is a wrapper for SDL, which is a 2D api. Pygame doesn't provide any 3D capability and probably never will.

3D libraries for Python include Panda3D and DirectPython, although they are probably quite complex to use, especially the latter.

人│生佛魔见 2024-10-22 19:04:55

好吧,如果你能做 2D,那么你就可以做 3D。所有的 3D 实际上都是倾斜的二维表面,给人一种你正在看有深度的东西的印象。真正的问题是它能否做好,以及您是否愿意这样做。浏览了一段时间 pyGame 文档后,看起来它只是一个 SDL 包装器。 SDL 不适用于 3D 编程,因此真正问题的答案是“不”,我什至不会尝试。

Well, if you can do 2d you can always do 3d. All 3d really is is skewed 2 dimensional surfaces giving the impression you're looking at something with depth. The real question is can it do it well, and would you even want to. After browsing the pyGame documentation for a while, it looks like it's just an SDL wrapper. SDL is not intended for 3d programming, so the answer to the real question is, No, and I wouldn't even try.

握住你手 2024-10-22 19:04:55

您可以仅使用 pygame 制作伪 3D 游戏(例如“Doom”):

http://code.google .com/p/gh0stenstein/

如果您浏览 pygame.org 网站,您可能会发现更多使用 python 和 pygame 完成的“3d”游戏。

然而,如果您真的想进入 3D 编程,您应该研究 OpenGl、Blender 或任何其他真正的 3D 库。

You can do pseudo-3d games ( like "Doom" ) with pygame only:

http://code.google.com/p/gh0stenstein/

and if you browse the pygame.org site you may find more "3d" games done with python and pygame.

However, if you really want to go into 3d programming you should look into OpenGl, Blender or any other real 3d lib.

扮仙女 2024-10-22 19:04:55

在没有其他依赖项帮助的情况下,Pygame 中的 3D 渲染很难实现,并且不会表现良好。 Pygame 不提供任何绘制 3D 形状、网格、甚至透视和照明的功能。
如果你想用 Pygame 绘制 3D 场景,你需要使用向量算术计算顶点并使用多边形将几何图形缝合在一起。
然后回答 Pygame 绕轴旋转立方体的示例:

这种方法不会给出令人满意的性能,仅对学习有价值。 3D 场景是在 GPU 的帮助下生成的。仅使用 CPU 的方法无法达到所需的性能。

尽管如此,使用 2.5 维方法仍可以获得不错的结果。请参阅如何修复墙壁变形的答案在我的光线投射器中?

import pygame
import math

pygame.init()

tile_size, map_size = 50, 8
board = [
    '########',
    '#   #  #',
    '#   # ##',
    '#  ##  #',
    '#      #',
    '###  ###',
    '#      #',
    '########']

def cast_rays(sx, sy, angle):
    rx = math.cos(angle)
    ry = math.sin(angle)
    map_x = sx // tile_size
    map_y = sy // tile_size

    t_max_x = sx/tile_size - map_x
    if rx > 0:
        t_max_x = 1 - t_max_x
    t_max_y = sy/tile_size - map_y
    if ry > 0:
        t_max_y = 1 - t_max_y

    while True:
        if ry == 0 or t_max_x < t_max_y * abs(rx / ry):
            side = 'x'
            map_x += 1 if rx > 0 else -1
            t_max_x += 1
            if map_x < 0 or map_x >= map_size:
                break
        else:
            side = 'y'
            map_y += 1 if ry > 0 else -1
            t_max_y += 1
            if map_x < 0 or map_y >= map_size:
                break
        if board[int(map_y)][int(map_x)] == "#":
            break

    if side == 'x':
        x = (map_x + (1 if rx < 0 else 0)) * tile_size
        y = player_y + (x - player_x) * ry / rx
        direction = 'r' if x >= player_x else 'l'
    else:
        y = (map_y + (1 if ry < 0 else 0)) * tile_size
        x = player_x + (y - player_y) * rx / ry
        direction = 'd' if y >= player_y else 'u'
    return (x, y), math.hypot(x - sx, y - sy), direction   

def cast_fov(sx, sy, angle, fov, no_ofrays):
    max_d = math.tan(math.radians(fov/2))
    step = max_d * 2 / no_ofrays
    rays = []
    for i in range(no_ofrays):
        d = -max_d + (i + 0.5) * step
        ray_angle = math.atan2(d, 1)
        pos, dist, direction = cast_rays(sx, sy, angle + ray_angle)
        rays.append((pos, dist, dist * math.cos(ray_angle), direction))
    return rays

area_width = tile_size * map_size
window = pygame.display.set_mode((area_width*2, area_width))
clock = pygame.time.Clock()

board_surf = pygame.Surface((area_width, area_width))
for row in range(8):
    for col in range(8):
        color = (192, 192, 192) if board[row][col] == '#' else (96, 96, 96)
        pygame.draw.rect(board_surf, color, (col * tile_size, row * tile_size, tile_size - 2, tile_size - 2))

player_x, player_y = round(tile_size * 4.5) + 0.5, round(tile_size * 4.5) + 0.5
player_angle = 0
max_speed = 3
colors = {'r' : (196, 128, 64), 'l' : (128, 128, 64), 'd' : (128, 196, 64), 'u' : (64, 196, 64)}

run = True
while run:
    clock.tick(30)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False    
    
    keys = pygame.key.get_pressed()
    hit_pos_front, dist_front, side_front = cast_rays(player_x, player_y, player_angle)
    hit_pos_back, dist_back, side_back = cast_rays(player_x, player_y, player_angle + math.pi)
    player_angle += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 0.1
    speed = ((0 if dist_front <= max_speed else keys[pygame.K_UP]) - (0 if dist_back <= max_speed else keys[pygame.K_DOWN])) * max_speed
    player_x += math.cos(player_angle) * speed
    player_y += math.sin(player_angle) * speed
    rays = cast_fov(player_x, player_y, player_angle, 60, 40)

    window.blit(board_surf, (0, 0))
    for ray in rays:
        pygame.draw.line(window, (0, 255, 0), (player_x, player_y), ray[0])
    pygame.draw.line(window, (255, 0, 0), (player_x, player_y), hit_pos_front)
    pygame.draw.circle(window, (255, 0, 0), (player_x, player_y), 8)

    pygame.draw.rect(window, (128, 128, 255), (400, 0, 400, 200))
    pygame.draw.rect(window, (128, 128, 128), (400, 200, 400, 200))
    for i, ray in enumerate(rays):
        height = round(10000 / ray[2])
        width = area_width // len(rays)
        color = pygame.Color((0, 0, 0)).lerp(colors[ray[3]], min(height/256, 1))
        rect = pygame.Rect(area_width + i*width, area_width//2-height//2, width, height)
        pygame.draw.rect(window, color, rect)
    pygame.display.flip()

pygame.quit()
exit()

另请参阅 PyGameExamplesAndAnswers - 光线投射


我知道您问过“...但我想知道是否可以在没有任何其他依赖项的情况下制作非常基本的 3D 图形。”。不管怎样,我会给你一些带有其他依赖项的附加选项。

在 Python 中使 3D 场景更强大的一种方法是使用基于 OpenGL 的库,例如 pygletModernGL

但是,您可以使用 Pygame 窗口创建 OpenGL 上下文。您需要在创建显示 Surface 时设置 pygame.OPENGL 标志(请参阅 pygame.display.set_mode):

window = pg.display.set_mode((width, height), pygame.OPENGL | pygame.DOUBLEBUF)

现代 OpenGL PyGame/PyOpenGL 示例:

import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GL.shaders import *
import ctypes
import glm

glsl_vert = """
#version 330 core

layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec4 a_col;

out vec4 v_color;

uniform mat4 u_proj; 
uniform mat4 u_view; 
uniform mat4 u_model; 

void main()
{
    v_color     = a_col;
    gl_Position = u_proj * u_view * u_model * vec4(a_pos.xyz, 1.0);
}
"""

glsl_frag = """
#version 330 core

out vec4 frag_color;
in  vec4 v_color;

void main()
{
    frag_color = v_color;
}
"""

class Cube:
  
    def __init__(self):
        v = [(-1,-1,-1), ( 1,-1,-1), ( 1, 1,-1), (-1, 1,-1), (-1,-1, 1), ( 1,-1, 1), ( 1, 1, 1), (-1, 1, 1)]
        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)]
        surfaces = [(0,1,2,3), (5,4,7,6), (4,0,3,7),(1,5,6,2), (4,5,1,0), (3,2,6,7)]
        colors = [(1,0,0), (0,1,0), (0,0,1), (1,1,0), (1,0,1), (1,0.5,0)]
        line_color = [0, 0, 0]

        edge_attributes = []
        for e in edges:
            edge_attributes += v[e[0]]
            edge_attributes += line_color
            edge_attributes += v[e[1]]
            edge_attributes += line_color

        face_attributes = []
        for i, quad in enumerate(surfaces):
            for iv in quad:
                face_attributes += v[iv]
                face_attributes += colors[i]

        self.edge_vbo = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self.edge_vbo)
        glBufferData(GL_ARRAY_BUFFER, (GLfloat * len(edge_attributes))(*edge_attributes), GL_STATIC_DRAW)
        self.edge_vao = glGenVertexArrays(1)
        glBindVertexArray(self.edge_vao)
        glVertexAttribPointer(0, 3, GL_FLOAT, False, 6*ctypes.sizeof(GLfloat), ctypes.c_void_p(0)) 
        glEnableVertexAttribArray(0) 
        glVertexAttribPointer(1, 3, GL_FLOAT, False, 6*ctypes.sizeof(GLfloat), ctypes.c_void_p(3*ctypes.sizeof(GLfloat))) 
        glEnableVertexAttribArray(1) 

        self.face_vbos = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self.face_vbos)
        glBufferData(GL_ARRAY_BUFFER, (GLfloat * len(face_attributes))(*face_attributes), GL_STATIC_DRAW)
        self.face_vao = glGenVertexArrays(1)
        glBindVertexArray(self.face_vao)
        glVertexAttribPointer(0, 3, GL_FLOAT, False, 6*ctypes.sizeof(GLfloat), ctypes.c_void_p(0)) 
        glEnableVertexAttribArray(0) 
        glVertexAttribPointer(1, 3, GL_FLOAT, False, 6*ctypes.sizeof(GLfloat), ctypes.c_void_p(3*ctypes.sizeof(GLfloat))) 
        glEnableVertexAttribArray(1) 

    def draw(self):
        glEnable(GL_DEPTH_TEST)

        glLineWidth(5)

        glBindVertexArray(self.edge_vao)
        glDrawArrays(GL_LINES, 0, 12*2)
        glBindVertexArray(0)

        glEnable(GL_POLYGON_OFFSET_FILL)
        glPolygonOffset( 1.0, 1.0 )

        glBindVertexArray(self.face_vao)
        glDrawArrays(GL_QUADS, 0, 6*4)
        glBindVertexArray(0)
        
        glDisable(GL_POLYGON_OFFSET_FILL)

def set_projection(w, h):
    return glm.perspective(glm.radians(45), w / h, 0.1, 50.0)

pygame.init()
window = pygame.display.set_mode((400, 300), pygame.DOUBLEBUF | pygame.OPENGL | pygame.RESIZABLE)
clock = pygame.time.Clock()

proj = set_projection(*window.get_size())
view = glm.lookAt(glm.vec3(0, 0, 5), glm.vec3(0, 0, 0), glm.vec3(0, 1, 0))
model = glm.mat4(1)
cube = Cube()
angle_x, angle_y = 0, 0

program = compileProgram( 
    compileShader(glsl_vert, GL_VERTEX_SHADER),
    compileShader(glsl_frag, GL_FRAGMENT_SHADER))
attrib = { a : glGetAttribLocation(program, a) for a in ['a_pos', 'a_col'] }
print(attrib)
uniform = { u : glGetUniformLocation(program, u) for u in ['u_model', 'u_view', 'u_proj'] }
print(uniform)
glUseProgram(program)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.VIDEORESIZE:
            glViewport(0, 0, event.w, event.h)
            proj = set_projection(event.w, event.h)

    model = glm.mat4(1)
    model = glm.rotate(model, glm.radians(angle_y), glm.vec3(0, 1, 0))
    model = glm.rotate(model, glm.radians(angle_x), glm.vec3(1, 0, 0))
   
    glUniformMatrix4fv(uniform['u_proj'], 1, GL_FALSE, glm.value_ptr(proj))
    glUniformMatrix4fv(uniform['u_view'], 1, GL_FALSE, glm.value_ptr(view))
    glUniformMatrix4fv(uniform['u_model'], 1, GL_FALSE, glm.value_ptr(model))

    angle_x += 1
    angle_y += 0.4

    glClearColor(0.5, 0.5, 0.5, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    cube.draw()    
    pygame.display.flip()

pygame.quit()
exit()

旧版 OpenGL PyGame/PyOpenGL 示例:

import pygame
from OpenGL.GL import *
from OpenGL.GLU import *

class Cube:
  
    def __init__(self):
        self.v = [(-1,-1,-1), ( 1,-1,-1), ( 1, 1,-1), (-1, 1,-1), (-1,-1, 1), ( 1,-1, 1), ( 1, 1, 1), (-1, 1, 1)]
        self.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)]
        self.surfaces = [(0,1,2,3), (5,4,7,6), (4,0,3,7),(1,5,6,2), (4,5,1,0), (3,2,6,7)]
        self.colors = [(1,0,0), (0,1,0), (0,0,1), (1,1,0), (1,0,1), (1,0.5,0)]

    def draw(self):
        glEnable(GL_DEPTH_TEST)

        glLineWidth(5)
        glColor3fv((0, 0, 0))
        glBegin(GL_LINES)
        for e in self.edges:
            glVertex3fv(self.v[e[0]])
            glVertex3fv(self.v[e[1]])
        glEnd()

        glEnable(GL_POLYGON_OFFSET_FILL)
        glPolygonOffset( 1.0, 1.0 )

        glBegin(GL_QUADS)
        for i, quad in enumerate(self.surfaces):
            glColor3fv(self.colors[i])
            for iv in quad:
                glVertex3fv(self.v[iv])
        glEnd()

        glDisable(GL_POLYGON_OFFSET_FILL)

def set_projection(w, h):
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, w / h, 0.1, 50.0)
    glMatrixMode(GL_MODELVIEW)

def screenshot(display_surface, filename):
    size = display_surface.get_size()
    buffer = glReadPixels(0, 0, *size, GL_RGBA, GL_UNSIGNED_BYTE)
    screen_surf = pygame.image.fromstring(buffer, size, "RGBA")
    pygame.image.save(screen_surf, filename)

pygame.init()
window = pygame.display.set_mode((400, 300), pygame.DOUBLEBUF | pygame.OPENGL | pygame.RESIZABLE)
clock = pygame.time.Clock()

set_projection(*window.get_size())
cube = Cube()
angle_x, angle_y = 0, 0

run = True
while run:
    clock.tick(60)
    take_screenshot = False
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.VIDEORESIZE:
            glViewport(0, 0, event.w, event.h)
            set_projection(event.w, event.h)
        elif event.type == pygame.KEYDOWN:
            take_screenshot = True

    glLoadIdentity()
    glTranslatef(0, 0, -5)
    glRotatef(angle_y, 0, 1, 0)
    glRotatef(angle_x, 1, 0, 0)
    angle_x += 1
    angle_y += 0.4

    glClearColor(0.5, 0.5, 0.5, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    cube.draw()   
    if take_screenshot: 
        screenshot(window, "cube.png")
    pygame.display.flip()
    
pygame.quit()
exit()

3D rendering in Pygame without the help of other dependencies is hard to achieve and will not perform well. Pygame does not offer any functionality for drawing 3D shapes, meshes, or even perspective and lighting.
If you want to draw a 3D scene with Pygame, you need to compute the vertices using vector arithmetic and stitch the geometry together using polygons.
Example of then answer to Pygame rotating cubes around axis:

This approach won't give a satisfying performance and is only valuable for studying. 3D scenes are generated with the help of the GPU. A CPU-only approach does not achieve the required performance.

Nevertheless, nice results can be achieved with a 2.5-D approach. See the answer to How do I fix wall warping in my raycaster?:

import pygame
import math

pygame.init()

tile_size, map_size = 50, 8
board = [
    '########',
    '#   #  #',
    '#   # ##',
    '#  ##  #',
    '#      #',
    '###  ###',
    '#      #',
    '########']

def cast_rays(sx, sy, angle):
    rx = math.cos(angle)
    ry = math.sin(angle)
    map_x = sx // tile_size
    map_y = sy // tile_size

    t_max_x = sx/tile_size - map_x
    if rx > 0:
        t_max_x = 1 - t_max_x
    t_max_y = sy/tile_size - map_y
    if ry > 0:
        t_max_y = 1 - t_max_y

    while True:
        if ry == 0 or t_max_x < t_max_y * abs(rx / ry):
            side = 'x'
            map_x += 1 if rx > 0 else -1
            t_max_x += 1
            if map_x < 0 or map_x >= map_size:
                break
        else:
            side = 'y'
            map_y += 1 if ry > 0 else -1
            t_max_y += 1
            if map_x < 0 or map_y >= map_size:
                break
        if board[int(map_y)][int(map_x)] == "#":
            break

    if side == 'x':
        x = (map_x + (1 if rx < 0 else 0)) * tile_size
        y = player_y + (x - player_x) * ry / rx
        direction = 'r' if x >= player_x else 'l'
    else:
        y = (map_y + (1 if ry < 0 else 0)) * tile_size
        x = player_x + (y - player_y) * rx / ry
        direction = 'd' if y >= player_y else 'u'
    return (x, y), math.hypot(x - sx, y - sy), direction   

def cast_fov(sx, sy, angle, fov, no_ofrays):
    max_d = math.tan(math.radians(fov/2))
    step = max_d * 2 / no_ofrays
    rays = []
    for i in range(no_ofrays):
        d = -max_d + (i + 0.5) * step
        ray_angle = math.atan2(d, 1)
        pos, dist, direction = cast_rays(sx, sy, angle + ray_angle)
        rays.append((pos, dist, dist * math.cos(ray_angle), direction))
    return rays

area_width = tile_size * map_size
window = pygame.display.set_mode((area_width*2, area_width))
clock = pygame.time.Clock()

board_surf = pygame.Surface((area_width, area_width))
for row in range(8):
    for col in range(8):
        color = (192, 192, 192) if board[row][col] == '#' else (96, 96, 96)
        pygame.draw.rect(board_surf, color, (col * tile_size, row * tile_size, tile_size - 2, tile_size - 2))

player_x, player_y = round(tile_size * 4.5) + 0.5, round(tile_size * 4.5) + 0.5
player_angle = 0
max_speed = 3
colors = {'r' : (196, 128, 64), 'l' : (128, 128, 64), 'd' : (128, 196, 64), 'u' : (64, 196, 64)}

run = True
while run:
    clock.tick(30)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False    
    
    keys = pygame.key.get_pressed()
    hit_pos_front, dist_front, side_front = cast_rays(player_x, player_y, player_angle)
    hit_pos_back, dist_back, side_back = cast_rays(player_x, player_y, player_angle + math.pi)
    player_angle += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 0.1
    speed = ((0 if dist_front <= max_speed else keys[pygame.K_UP]) - (0 if dist_back <= max_speed else keys[pygame.K_DOWN])) * max_speed
    player_x += math.cos(player_angle) * speed
    player_y += math.sin(player_angle) * speed
    rays = cast_fov(player_x, player_y, player_angle, 60, 40)

    window.blit(board_surf, (0, 0))
    for ray in rays:
        pygame.draw.line(window, (0, 255, 0), (player_x, player_y), ray[0])
    pygame.draw.line(window, (255, 0, 0), (player_x, player_y), hit_pos_front)
    pygame.draw.circle(window, (255, 0, 0), (player_x, player_y), 8)

    pygame.draw.rect(window, (128, 128, 255), (400, 0, 400, 200))
    pygame.draw.rect(window, (128, 128, 128), (400, 200, 400, 200))
    for i, ray in enumerate(rays):
        height = round(10000 / ray[2])
        width = area_width // len(rays)
        color = pygame.Color((0, 0, 0)).lerp(colors[ray[3]], min(height/256, 1))
        rect = pygame.Rect(area_width + i*width, area_width//2-height//2, width, height)
        pygame.draw.rect(window, color, rect)
    pygame.display.flip()

pygame.quit()
exit()

Also see PyGameExamplesAndAnswers - Raycasting


I am aware that you asked "... but I was wondering if its possible to do very basic 3D graphics without any other dependencies.". Anyway, I will give you some additional options with other dependencies.

One way to make 3D scenes more powerful in Python is to use an OpenGL based library like pyglet or ModernGL.

However, you can use a Pygame window to create an OpenGL Context. You need to set the pygame.OPENGL flag when creating the display Surface (see pygame.display.set_mode):

window = pg.display.set_mode((width, height), pygame.OPENGL | pygame.DOUBLEBUF)

Modern OpenGL PyGame/PyOpenGL example:

import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GL.shaders import *
import ctypes
import glm

glsl_vert = """
#version 330 core

layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec4 a_col;

out vec4 v_color;

uniform mat4 u_proj; 
uniform mat4 u_view; 
uniform mat4 u_model; 

void main()
{
    v_color     = a_col;
    gl_Position = u_proj * u_view * u_model * vec4(a_pos.xyz, 1.0);
}
"""

glsl_frag = """
#version 330 core

out vec4 frag_color;
in  vec4 v_color;

void main()
{
    frag_color = v_color;
}
"""

class Cube:
  
    def __init__(self):
        v = [(-1,-1,-1), ( 1,-1,-1), ( 1, 1,-1), (-1, 1,-1), (-1,-1, 1), ( 1,-1, 1), ( 1, 1, 1), (-1, 1, 1)]
        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)]
        surfaces = [(0,1,2,3), (5,4,7,6), (4,0,3,7),(1,5,6,2), (4,5,1,0), (3,2,6,7)]
        colors = [(1,0,0), (0,1,0), (0,0,1), (1,1,0), (1,0,1), (1,0.5,0)]
        line_color = [0, 0, 0]

        edge_attributes = []
        for e in edges:
            edge_attributes += v[e[0]]
            edge_attributes += line_color
            edge_attributes += v[e[1]]
            edge_attributes += line_color

        face_attributes = []
        for i, quad in enumerate(surfaces):
            for iv in quad:
                face_attributes += v[iv]
                face_attributes += colors[i]

        self.edge_vbo = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self.edge_vbo)
        glBufferData(GL_ARRAY_BUFFER, (GLfloat * len(edge_attributes))(*edge_attributes), GL_STATIC_DRAW)
        self.edge_vao = glGenVertexArrays(1)
        glBindVertexArray(self.edge_vao)
        glVertexAttribPointer(0, 3, GL_FLOAT, False, 6*ctypes.sizeof(GLfloat), ctypes.c_void_p(0)) 
        glEnableVertexAttribArray(0) 
        glVertexAttribPointer(1, 3, GL_FLOAT, False, 6*ctypes.sizeof(GLfloat), ctypes.c_void_p(3*ctypes.sizeof(GLfloat))) 
        glEnableVertexAttribArray(1) 

        self.face_vbos = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self.face_vbos)
        glBufferData(GL_ARRAY_BUFFER, (GLfloat * len(face_attributes))(*face_attributes), GL_STATIC_DRAW)
        self.face_vao = glGenVertexArrays(1)
        glBindVertexArray(self.face_vao)
        glVertexAttribPointer(0, 3, GL_FLOAT, False, 6*ctypes.sizeof(GLfloat), ctypes.c_void_p(0)) 
        glEnableVertexAttribArray(0) 
        glVertexAttribPointer(1, 3, GL_FLOAT, False, 6*ctypes.sizeof(GLfloat), ctypes.c_void_p(3*ctypes.sizeof(GLfloat))) 
        glEnableVertexAttribArray(1) 

    def draw(self):
        glEnable(GL_DEPTH_TEST)

        glLineWidth(5)

        glBindVertexArray(self.edge_vao)
        glDrawArrays(GL_LINES, 0, 12*2)
        glBindVertexArray(0)

        glEnable(GL_POLYGON_OFFSET_FILL)
        glPolygonOffset( 1.0, 1.0 )

        glBindVertexArray(self.face_vao)
        glDrawArrays(GL_QUADS, 0, 6*4)
        glBindVertexArray(0)
        
        glDisable(GL_POLYGON_OFFSET_FILL)

def set_projection(w, h):
    return glm.perspective(glm.radians(45), w / h, 0.1, 50.0)

pygame.init()
window = pygame.display.set_mode((400, 300), pygame.DOUBLEBUF | pygame.OPENGL | pygame.RESIZABLE)
clock = pygame.time.Clock()

proj = set_projection(*window.get_size())
view = glm.lookAt(glm.vec3(0, 0, 5), glm.vec3(0, 0, 0), glm.vec3(0, 1, 0))
model = glm.mat4(1)
cube = Cube()
angle_x, angle_y = 0, 0

program = compileProgram( 
    compileShader(glsl_vert, GL_VERTEX_SHADER),
    compileShader(glsl_frag, GL_FRAGMENT_SHADER))
attrib = { a : glGetAttribLocation(program, a) for a in ['a_pos', 'a_col'] }
print(attrib)
uniform = { u : glGetUniformLocation(program, u) for u in ['u_model', 'u_view', 'u_proj'] }
print(uniform)
glUseProgram(program)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.VIDEORESIZE:
            glViewport(0, 0, event.w, event.h)
            proj = set_projection(event.w, event.h)

    model = glm.mat4(1)
    model = glm.rotate(model, glm.radians(angle_y), glm.vec3(0, 1, 0))
    model = glm.rotate(model, glm.radians(angle_x), glm.vec3(1, 0, 0))
   
    glUniformMatrix4fv(uniform['u_proj'], 1, GL_FALSE, glm.value_ptr(proj))
    glUniformMatrix4fv(uniform['u_view'], 1, GL_FALSE, glm.value_ptr(view))
    glUniformMatrix4fv(uniform['u_model'], 1, GL_FALSE, glm.value_ptr(model))

    angle_x += 1
    angle_y += 0.4

    glClearColor(0.5, 0.5, 0.5, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    cube.draw()    
    pygame.display.flip()

pygame.quit()
exit()

Legacy OpenGL PyGame/PyOpenGL example:

import pygame
from OpenGL.GL import *
from OpenGL.GLU import *

class Cube:
  
    def __init__(self):
        self.v = [(-1,-1,-1), ( 1,-1,-1), ( 1, 1,-1), (-1, 1,-1), (-1,-1, 1), ( 1,-1, 1), ( 1, 1, 1), (-1, 1, 1)]
        self.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)]
        self.surfaces = [(0,1,2,3), (5,4,7,6), (4,0,3,7),(1,5,6,2), (4,5,1,0), (3,2,6,7)]
        self.colors = [(1,0,0), (0,1,0), (0,0,1), (1,1,0), (1,0,1), (1,0.5,0)]

    def draw(self):
        glEnable(GL_DEPTH_TEST)

        glLineWidth(5)
        glColor3fv((0, 0, 0))
        glBegin(GL_LINES)
        for e in self.edges:
            glVertex3fv(self.v[e[0]])
            glVertex3fv(self.v[e[1]])
        glEnd()

        glEnable(GL_POLYGON_OFFSET_FILL)
        glPolygonOffset( 1.0, 1.0 )

        glBegin(GL_QUADS)
        for i, quad in enumerate(self.surfaces):
            glColor3fv(self.colors[i])
            for iv in quad:
                glVertex3fv(self.v[iv])
        glEnd()

        glDisable(GL_POLYGON_OFFSET_FILL)

def set_projection(w, h):
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, w / h, 0.1, 50.0)
    glMatrixMode(GL_MODELVIEW)

def screenshot(display_surface, filename):
    size = display_surface.get_size()
    buffer = glReadPixels(0, 0, *size, GL_RGBA, GL_UNSIGNED_BYTE)
    screen_surf = pygame.image.fromstring(buffer, size, "RGBA")
    pygame.image.save(screen_surf, filename)

pygame.init()
window = pygame.display.set_mode((400, 300), pygame.DOUBLEBUF | pygame.OPENGL | pygame.RESIZABLE)
clock = pygame.time.Clock()

set_projection(*window.get_size())
cube = Cube()
angle_x, angle_y = 0, 0

run = True
while run:
    clock.tick(60)
    take_screenshot = False
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.VIDEORESIZE:
            glViewport(0, 0, event.w, event.h)
            set_projection(event.w, event.h)
        elif event.type == pygame.KEYDOWN:
            take_screenshot = True

    glLoadIdentity()
    glTranslatef(0, 0, -5)
    glRotatef(angle_y, 0, 1, 0)
    glRotatef(angle_x, 1, 0, 0)
    angle_x += 1
    angle_y += 0.4

    glClearColor(0.5, 0.5, 0.5, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    cube.draw()   
    if take_screenshot: 
        screenshot(window, "cube.png")
    pygame.display.flip()
    
pygame.quit()
exit()
就像说晚安 2024-10-22 19:04:55

Pygame 最初并不是用来做 3D 的,但是有一种方法可以用任何 2D 图形库来做 3D。您所需要的只是以下函数,它将 3d 点转换为 2d 点,这样您只需在屏幕上画线即可制作任何 3d 形状。

def convert_to_2d(point=[0,0,0]):
    return [point[0]*(point[2]*.3),point[1]*(point[2]*.3)]

这称为伪 3d 或 2.5d。这是可以做到的,但可能会很慢,而且非常难做到,因此建议您使用适用于 3d 的库。

Pygame was never originally meant to do 3d, but there is a way you can do 3d with any 2d graphics library. All you need is the following function, which converts 3d points to 2d points, which allows you to make any 3d shape by just drawing lines on a screen.

def convert_to_2d(point=[0,0,0]):
    return [point[0]*(point[2]*.3),point[1]*(point[2]*.3)]

This is called pseudo 3d, or 2.5d. This can be done, but may be slow, and is extremely difficult to do, so it is suggested that you use a library meant for 3d.

慕巷 2024-10-22 19:04:55

它不支持,但与 PyOpenGL 结合,您可以利用两者的力量,这里是一个完整的示例

    import pygame
    from pygame.locals import *

    from OpenGL.GL import *
    from OpenGL.GLU import *

    import random

    vertices = ((1, -1, -1),(1, 1, -1),(-1, 1, -1),(-1, -1, -1),(1, -1, 1),(1, 1, 1),(-1, -1, 1),(-1, 1, 1))
edges = ((0,1),(0,3),(0,4),(2,1),(2,3),(2,7),(6,3),(6,4),(6,7),(5,1),(5,4),(5,7))
    surfaces = ((0,1,2,3),(3,2,7,6),(6,7,5,4),(4,5,1,0),(1,5,7,2),(4,0,3,6))
    colors = ((1,0,0),(0,1,0),(0,0,1),(0,1,0),(1,1,1),(0,1,1),(1,0,0),(0,1,0),(0,0,1),(1,0,0),(1,1,1),(0,1,1),)

   
    def set_vertices(max_distance, min_distance = -20):
        x_value_change = random.randrange(-10,10)
        y_value_change = random.randrange(-10,10)
        z_value_change = random.randrange(-1*max_distance,min_distance)
        new_vertices = []
        for vert in vertices:
            new_vert = []
            new_x = vert[0] + x_value_change
            new_y = vert[1] + y_value_change
            new_z = vert[2] + z_value_change
            new_vert.append(new_x)
            new_vert.append(new_y)
            new_vert.append(new_z)
            new_vertices.append(new_vert)
        return new_vertices
            
        


    def Cube(vertices):
        glBegin(GL_QUADS)
        for surface in surfaces:
            x = 0

            for vertex in surface:
                x+=1
                glColor3fv(colors[x])
                glVertex3fv(vertices[vertex])
        glEnd()
        glBegin(GL_LINES)
        for edge in edges:
            for vertex in edge:
                glVertex3fv(vertices[vertex])
        glEnd()

    def main():
        pygame.init()
        display = (800,600)
        pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
        max_distance = 100
        gluPerspective(45, (display[0]/display[1]), 0.1, max_distance)
        glTranslatef(random.randrange(-5,5),random.randrange(-5,5), -40)
        #object_passed = False
        x_move = 0
        y_move = 0
        cube_dict = {}

        for x in range(50):
            cube_dict[x] =set_vertices(max_distance)

        #glRotatef(25, 2, 1, 0)

        
        x = glGetDoublev(GL_MODELVIEW_MATRIX)
        camera_x = x[3][0]
        camera_y = x[3][1]
        camera_z = x[3][2]
        button_down = False
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()
                if event.type == pygame.MOUSEMOTION:
                    if button_down == True:
                        print(pygame.mouse.get_pressed())
                        glRotatef(event.rel[1], 1, 0, 0)
                        glRotatef(event.rel[0], 0, 1, 0)
            
            for event in pygame.mouse.get_pressed():
                # print(pygame.mouse.get_pressed())
                if pygame.mouse.get_pressed()[0] == 1:
                    button_down = True
                elif pygame.mouse.get_pressed()[0] == 0:
                    button_down = False

           

            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)


            for each_cube in cube_dict:
                Cube(cube_dict[each_cube])

            pygame.display.flip()
            pygame.time.wait(10)

    main()
    pygame.quit()
    quit()

在此处输入图像描述

It does not support, but combining with PyOpenGL you can make use of the power of both, here is a full example

    import pygame
    from pygame.locals import *

    from OpenGL.GL import *
    from OpenGL.GLU import *

    import random

    vertices = ((1, -1, -1),(1, 1, -1),(-1, 1, -1),(-1, -1, -1),(1, -1, 1),(1, 1, 1),(-1, -1, 1),(-1, 1, 1))
edges = ((0,1),(0,3),(0,4),(2,1),(2,3),(2,7),(6,3),(6,4),(6,7),(5,1),(5,4),(5,7))
    surfaces = ((0,1,2,3),(3,2,7,6),(6,7,5,4),(4,5,1,0),(1,5,7,2),(4,0,3,6))
    colors = ((1,0,0),(0,1,0),(0,0,1),(0,1,0),(1,1,1),(0,1,1),(1,0,0),(0,1,0),(0,0,1),(1,0,0),(1,1,1),(0,1,1),)

   
    def set_vertices(max_distance, min_distance = -20):
        x_value_change = random.randrange(-10,10)
        y_value_change = random.randrange(-10,10)
        z_value_change = random.randrange(-1*max_distance,min_distance)
        new_vertices = []
        for vert in vertices:
            new_vert = []
            new_x = vert[0] + x_value_change
            new_y = vert[1] + y_value_change
            new_z = vert[2] + z_value_change
            new_vert.append(new_x)
            new_vert.append(new_y)
            new_vert.append(new_z)
            new_vertices.append(new_vert)
        return new_vertices
            
        


    def Cube(vertices):
        glBegin(GL_QUADS)
        for surface in surfaces:
            x = 0

            for vertex in surface:
                x+=1
                glColor3fv(colors[x])
                glVertex3fv(vertices[vertex])
        glEnd()
        glBegin(GL_LINES)
        for edge in edges:
            for vertex in edge:
                glVertex3fv(vertices[vertex])
        glEnd()

    def main():
        pygame.init()
        display = (800,600)
        pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
        max_distance = 100
        gluPerspective(45, (display[0]/display[1]), 0.1, max_distance)
        glTranslatef(random.randrange(-5,5),random.randrange(-5,5), -40)
        #object_passed = False
        x_move = 0
        y_move = 0
        cube_dict = {}

        for x in range(50):
            cube_dict[x] =set_vertices(max_distance)

        #glRotatef(25, 2, 1, 0)

        
        x = glGetDoublev(GL_MODELVIEW_MATRIX)
        camera_x = x[3][0]
        camera_y = x[3][1]
        camera_z = x[3][2]
        button_down = False
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()
                if event.type == pygame.MOUSEMOTION:
                    if button_down == True:
                        print(pygame.mouse.get_pressed())
                        glRotatef(event.rel[1], 1, 0, 0)
                        glRotatef(event.rel[0], 0, 1, 0)
            
            for event in pygame.mouse.get_pressed():
                # print(pygame.mouse.get_pressed())
                if pygame.mouse.get_pressed()[0] == 1:
                    button_down = True
                elif pygame.mouse.get_pressed()[0] == 0:
                    button_down = False

           

            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)


            for each_cube in cube_dict:
                Cube(cube_dict[each_cube])

            pygame.display.flip()
            pygame.time.wait(10)

    main()
    pygame.quit()
    quit()

enter image description here

我不咬妳我踢妳 2024-10-22 19:04:55

你看到的3D游戏实际上是2D游戏。毕竟,您正在观看屏幕,(通常;))是 2D 的。虚拟世界(3D)被投影到一个平面上,然后显示在屏幕上。然后,我们的大脑将该 2D 图像转换为 3D 图像(就像处理我们眼睛的图像一样),使其看起来像是 3D 的。

因此,制作 3D 游戏相对容易:您只需使用多维矩阵创建一个虚拟世界,然后将其每个循环投影到 2D 平面上,然后将其显示在屏幕上。

这个教程可以帮助您开始 3D 程序(使用 pygame)

What you see as a 3D is actually a 2D game. After all, you are watching your screen, which (normally ;) ) is 2D. The virtual world (which is in 3D) is projected onto a plane, which is then shown on your screen. Our brains then convert that 2D image into a 3D one (like they do with the image of our eyes), making it look like it's 3D.

So it's relatively easy to make a 3D game: you just create a virtual world using a multidimensional matrix and then project it each loop on a 2D plane, which you display on your screen.

One tutorial that can put you on your way to 3D programs (using pygame) is this one .

笑梦风尘 2024-10-22 19:04:55

你可以这样做:

def convert_2d(x, y, z, horizon):
    d = 1 - (z/horizon)
    return x*d, y*d
def draw_list_of_points(lst):
    '''Assume that lst is a list of 3 dimentionnal points like [(0, 0, 0), (1, 6, 2)...
    Let's take 200 for the horizon, it can give us a pretty clean 3D''' 
    for x, y, z in lst:
        pygame.draw.circle(screen, color, convert_2d(x, y, z, 200), 1)

但它不是很快。如果你想快速尝试用 C++/SDL2 或 C 实现。
Pygame 不太适合 3d 图形。

You can make like this :

def convert_2d(x, y, z, horizon):
    d = 1 - (z/horizon)
    return x*d, y*d
def draw_list_of_points(lst):
    '''Assume that lst is a list of 3 dimentionnal points like [(0, 0, 0), (1, 6, 2)...
    Let's take 200 for the horizon, it can give us a pretty clean 3D''' 
    for x, y, z in lst:
        pygame.draw.circle(screen, color, convert_2d(x, y, z, 200), 1)

But it's not very fast. If you want fast try to implement in C++/SDL2 or C.
Pygame is not very good for 3d graphics.

Spring初心 2024-10-22 19:04:55

为 PyGame 制作 3D 驱动程序很容易。 PyGame 拥有一些用于 3D 游戏开发的资源。
我现在正在使用 PyGame 开发 Py3D 驱动程序。完成后,我将向您展示下载 Py3D 的链接。我尝试使用 PyGame 制作 3D 游戏,并且我只需要 PyGame 的小插件。您认为必须使用 SDL、PyOpenGL、OpenGL、PyQt5、Tkinter 是错误的。对于制作 3D 游戏来说,这些都是错误的。 OpenGL 和 PyOpenGL 或 Panda3D 非常难学。我用这些驱动程序制作的所有游戏都很糟糕。 PyQt5 和 Tkinter 不是用于制作游戏的驱动程序,但它们有插件。不要尝试在这些驱动程序上制作任何游戏。我们需要使用数学模块的所有驱动程序都很困难。你可以轻松地为它们制作小插件,我想每个人都可以在 1-2 周内为 PyGame 制作驱动程序。

It is easy to make 3D driver for PyGame. PyGame has some assets for 3D game development.
I am developing Py3D driver using PyGame now. When I finish, I'll show you link to download Py3D. I tried to make 3D game with PyGame, and I needed just small addon for PyGame. It is wrong you think you must use SDL, PyOpenGL, OpenGL, PyQt5, Tkinter. All of them are wrong for making 3D games. OpenGL and PyOpenGL or Panda3D are very hard to learn. All my games made on those drivers were awful. PyQt5 and Tkinter aren't drivers for making games, but they've got addons for it. Don't try to make any game on those drivers. All drivers where we need to use the math module are hard. You can easily make small addon for them, I think everybody can make driver for PyGame in 1-2 weeks.

狼亦尘 2024-10-22 19:04:55

如果您想在制作游戏时坚持使用 Python 风格的语言,Godot 是一个不错的选择,它同时支持 2D 和 3D,拥有大型社区和大量教程。它的自定义脚本语言(gdscript)有一些细微的差别,但总体来说基本相同。它还支持 C# 和 C++,并且在游戏开发方面具有更多功能。

If you want to stick with a python-esque language when making games, Godot is a good alternative with both 2D and 3D support, a large community, and lots of tutorials. Its custom scripting language(gdscript) has some minor differences, but overall its mostly the same. It also has support for c# and c++, and has much more features when it comes to game development.

染墨丶若流云 2024-10-22 19:04:55

Pygame 只是一个用于更改像素颜色的库(以及其他一些对游戏编程有用的东西)。您可以通过将图像传输到屏幕或直接设置像素颜色来完成此操作。

正因为如此,使用 pygame 编写 2D 游戏很容易,因为上面的内容就是您真正需要的。但 3D 游戏只是将一些 3D 对象“压缩”(渲染)为 2D,以便可以在屏幕上显示。因此,要仅使用 pygame 制作 3D 游戏,您必须自己处理渲染,包括所有必要的复杂矩阵数学。

由于涉及巨大的处理能力,这不仅会导致运行缓慢,而且还需要您编写一个庞大的 3D 渲染/光栅化引擎。而且由于 python 被解释,它会更慢。正确的方法是使用 (Py)opengl 在 GPU 上运行此进程。

所以,是的,从技术上来说,仅使用 pygame 来实现 3D 是可行的,但绝对不推荐。我建议你学习Panda3D或一些类似的3D引擎。

Pygame is just a library for changing the color of pixels (and some other useful stuff for programming games). You can do this by blitting images to the screen or directly setting the colors of pixels.

Because of this, it is easy to write 2D games with pygame, as the above is all you really need. But a 3D game is just some 3D objects 'squashed' (rendered) into 2D so that it can be displayed on the screen. So, to make a 3D game using only pygame, you would have handle this rendering by yourself, including all the complex matrix maths necessary.

Not only would this run slowly because of the immense processing power involved in this, but it would require you to write a massive 3D rendering/rasterisation engine. And because of python being interpreted it would be even slower. The correct approach would be to have this process run on the GPU using (Py)opengl.

So, yes it is technically possible to do 3D using only pygame, but definitely not recommended. I would suggest you learn Panda3D or some similar 3D engine.

债姬 2024-10-22 19:04:55

简单的:
只需绘制一堆多边形,例如:

import pygame
screen = pygame.display.set_mode((100, 100))
While True:
   screen.fill((0, 0, 0))
   Pos = [(10, 10), (20, 10), (20, 20), (10, 20)]
   # first side (the front) in red
   pygame.draw.polygon(screen, (225, 0, 0), Pos)
   # outline in white
   pygame.draw.lines(screen, (225, 225, 225), Pos)
   # Second side (the back) in blue
   Pos2 = [(Pos[0[0]] + 2.5, Pos[0[1]] + 2.5), (Pos2[0[0]] + 5, Pos2[0[1]]), (Pos2[1[0]], Pos2[1[1]] + 5), (Pos2[0[0]], Pos2[0[1]] + 5)]
   pygame.draw.polygon(screen, (0, 0, 225), Pos2)
   pygame.draw.lines(screen, (225, 225, 225), Pos2)
   # Third side (the left but just 2 lines(not really)) in green 
   Pos3 = [Pos[0], Pos2[0], Pos2[3], Pos[3]]
   pygame.draw.polygon(screen, (0, 225, 0), Pos3)
   pygame.draw.lines(screen, (225, 225, 225), Pos3)
   # Fourth side (the right) in purple
   Pos4 = [Pos[1], Pos2[1], Pos2[2], Pos[2]]
   pygame.draw.polygon(screen, (225, 0, 225), Pos4)
   pygame.draw.lines(screen, (225, 225, 225), Pos4)
   pygame.display.flip()

&有一个简单的立方体 &我很快将提供完整代码的链接,以便能够旋转立方体和旋转立方体。调整它的大小

这应该给你一个相当于使用 OpenGL 得到的结果

Simple:
Just draw a bunch of polygons like:

import pygame
screen = pygame.display.set_mode((100, 100))
While True:
   screen.fill((0, 0, 0))
   Pos = [(10, 10), (20, 10), (20, 20), (10, 20)]
   # first side (the front) in red
   pygame.draw.polygon(screen, (225, 0, 0), Pos)
   # outline in white
   pygame.draw.lines(screen, (225, 225, 225), Pos)
   # Second side (the back) in blue
   Pos2 = [(Pos[0[0]] + 2.5, Pos[0[1]] + 2.5), (Pos2[0[0]] + 5, Pos2[0[1]]), (Pos2[1[0]], Pos2[1[1]] + 5), (Pos2[0[0]], Pos2[0[1]] + 5)]
   pygame.draw.polygon(screen, (0, 0, 225), Pos2)
   pygame.draw.lines(screen, (225, 225, 225), Pos2)
   # Third side (the left but just 2 lines(not really)) in green 
   Pos3 = [Pos[0], Pos2[0], Pos2[3], Pos[3]]
   pygame.draw.polygon(screen, (0, 225, 0), Pos3)
   pygame.draw.lines(screen, (225, 225, 225), Pos3)
   # Fourth side (the right) in purple
   Pos4 = [Pos[1], Pos2[1], Pos2[2], Pos[2]]
   pygame.draw.polygon(screen, (225, 0, 225), Pos4)
   pygame.draw.lines(screen, (225, 225, 225), Pos4)
   pygame.display.flip()

& there is a simple cube & I will soon provide a link for the full code to be able to rotate the cube & resize it

This should give you an equivalent of what you would get by using OpenGL

不寐倦长更 2024-10-22 19:04:55

这就是我仅使用 Pygame 和 Numpy 就能做到的事情,而无需使用带有一些基本着色的 OpenGL。

输入图片此处描述

您可以在 PyGame 中进行 3D,但可能不是最高效和最快的。

This is what I have managed to do with just Pygame and Numpy without using OpenGL with some basic shading.

enter image description here

You can do 3D in PyGame but probably isn't the most efficient and fastest.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文