Johnny_0212 2022-07-31 19:43 采纳率: 25%
浏览 70

python 3d方块咋做

问题遇到的现象和发生背景 :
最近我想做3d,发现了pyglet。但,我不会用pyglet。

我想要达到的结果:
出现一个屏幕,里面有一个草方块,跟MC的差不多。

图片资源:
草方块顶面图片路径:H:/mc/grass.png
草方块侧面图片路径:H:/mc/grass_soil.png
草方块底面图片路径:H:/mc/soil.png

  • 写回答

1条回答 默认 最新

  • linuszp 2025-10-19 20:06
    关注
    
    import pyglet
    from pyglet.gl import *
    
    # ----------------------------------------------
    # 1. 资源路径(改成你自己的)
    # ----------------------------------------------
    TOP_IMG   = r'H:/mc/grass.png'      # 草顶
    SIDE_IMG  = r'H:/mc/grass_soil.png' # 草+泥侧面
    BOTTOM_IMG= r'H:/mc/soil.png'       # 纯泥土底面
    
    # ----------------------------------------------
    # 2. 把 pyglet.image 转成 OpenGL texture
    # ----------------------------------------------
    def load_texture(path):
        img = pyglet.image.load(path)
        texture = img.get_texture()
        glBindTexture(GL_TEXTURE_2D, texture.id)
        # 纹理参数:最近邻过滤 + 重复边缘
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
        return texture
    
    # ----------------------------------------------
    # 3. 建一个立方体:6 面 → 12 三角形 → 36 顶点
    #    每顶点:position(3) + texcoord(2)
    # ----------------------------------------------
    def make_cube_vertices(size=1.0):
        s = size/2
        # 顶点坐标
        vertices = (
            # 前面 (+Y)
            -s,-s, s,  0,0,   s,-s, s,  1,0,   s, s, s,  1,1,  -s, s, s,  0,1,
            # 后面 (-Y)
             s,-s,-s,  0,0,  -s,-s,-s,  1,0,  -s, s,-s,  1,1,   s, s,-s,  0,1,
            # 右面 (+X)
             s,-s, s,  0,0,   s,-s,-s,  1,0,   s, s,-s,  1,1,   s, s, s,  0,1,
            # 左面 (-X)
            -s,-s,-s,  0,0,  -s,-s, s,  1,0,  -s, s, s,  1,1,  -s, s,-s,  0,1,
            # 顶面 (+Z)
            -s, s, s,  0,0,   s, s, s,  1,0,   s, s,-s,  1,1,  -s, s,-s,  0,1,
            # 底面 (-Z)
            -s,-s,-s,  0,0,   s,-s,-s,  1,0,   s,-s, s,  1,1,  -s,-s, s,  0,1,
        )
        return (GLfloat * len(vertices))(*vertices)
    
    # ----------------------------------------------
    # 4. 初始化 OpenGL
    # ----------------------------------------------
    def setup():
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_TEXTURE_2D)
        glEnable(GL_CULL_FACE)
        glClearColor(0.5, 0.7, 1.0, 1)  # 天蓝色背景
    
    # ----------------------------------------------
    # 5. 窗口事件
    # ----------------------------------------------
    class Win(pyglet.window.Window):
        def __init__(self):
            super().__init__(width=800, height=600, caption='Minecraft Grass Cube',
                             resizable=True)
            setup()
            self.vertices = make_cube_vertices(2.0)
            # 载入纹理
            self.tex_top    = load_texture(TOP_IMG)
            self.tex_side   = load_texture(SIDE_IMG)
            self.tex_bottom = load_texture(BOTTOM_IMG)
            # 简单旋转
            self.rot_x = -20
            self.rot_y = 30
            # 鼠标拖动
            self._drag = False
    
        def on_draw(self):
            self.clear()
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            gluPerspective(60, self.width/self.height, 0.1, 100)
            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()
            gluLookAt(0, 0, 10,   0,0,0,   0,1,0)
            glRotatef(self.rot_x, 1, 0, 0)
            glRotatef(self.rot_y, 0, 1, 0)
    
            # 画 6 个面
            glInterleavedArrays(GL_T2F_V3F, 0, self.vertices)
            # 0 前 1 后 2 右 3 左 4 顶 5 底
            for face in range(6):
                if face == 4:   # 顶
                    glBindTexture(GL_TEXTURE_2D, self.tex_top.id)
                elif face == 5: # 底
                    glBindTexture(GL_TEXTURE_2D, self.tex_bottom.id)
                else:           # 四周
                    glBindTexture(GL_TEXTURE_2D, self.tex_side.id)
                glDrawArrays(GL_QUADS, face*4, 4)
    
        def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
            if buttons & pyglet.window.mouse.LEFT:
                self.rot_y += dx*0.5
                self.rot_x += dy*0.5
    
    # ----------------------------------------------
    # 6. 运行
    # ----------------------------------------------
    if __name__ == '__main__':
        Win()
        pyglet.app.run()
    

    运行这个

    评论

报告相同问题?

问题事件

  • 创建了问题 7月31日