问题遇到的现象和发生背景 :
最近我想做3d,发现了pyglet。但,我不会用pyglet。
我想要达到的结果:
出现一个屏幕,里面有一个草方块,跟MC的差不多。
图片资源:
草方块顶面图片路径:H:/mc/grass.png
草方块侧面图片路径:H:/mc/grass_soil.png
草方块底面图片路径:H:/mc/soil.png
问题遇到的现象和发生背景 :
最近我想做3d,发现了pyglet。但,我不会用pyglet。
我想要达到的结果:
出现一个屏幕,里面有一个草方块,跟MC的差不多。
图片资源:
草方块顶面图片路径:H:/mc/grass.png
草方块侧面图片路径:H:/mc/grass_soil.png
草方块底面图片路径:H:/mc/soil.png
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()
运行这个