import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import numpy as np
# 设置方块大小
BLOCK_SIZE = 1.0
# 初始化 pygame 显示
def init_display():
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
pygame.display.set_caption("我的世界 - 简化版")
gluPerspective(45, (display[0] / display[1]), 0.1, 100.0)
glTranslatef(0.0, 0.0, -5) # 初始后移观察世界
# 创建一个平面作为地面
def create_world():
world = {}
for x in range(-10, 11):
for z in range(-10, 11):
y = 0 # 地面高度
world[(x, y, z)] = (0.2, 0.6, 0.2) # 绿色地面
return world
# 绘制一个立方体(方块)
def draw_cube(position, color):
x, y, z = position
vertices = [
[x, y, z],
[x + BLOCK_SIZE, y, z],
[x + BLOCK_SIZE, y + BLOCK_SIZE, z],
[x, y + BLOCK_SIZE, z],
[x, y, z + BLOCK_SIZE],
[x + BLOCK_SIZE, y, z + BLOCK_SIZE],
[x + BLOCK_SIZE, y + BLOCK_SIZE, z + BLOCK_SIZE],
[x, y + BLOCK_SIZE, z + BLOCK_SIZE]
]
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)
]
faces = [
(0,1,2,3), (4,5,6,7), (0,1,5,4),
(2,3,7,6), (0,3,7,4), (1,2,6,5)
]
# 绘制面(带颜色填充)
glBegin(GL_QUADS)
glColor3f(*color)
for face in faces:
for i in face:
glVertex3fv(vertices[i])
glEnd()
# 绘制边框(黑色轮廓)
glBegin(GL_LINES)
glColor3f(0.0, 0.0, 0.0)
for edge in edges:
for vertex in edge:
glVertex3fv(vertices[vertex])
glEnd()
# 主循环
def main():
init_display()
world = create_world()
clock = pygame.time.Clock()
# 视角控制变量
angle_x, angle_y = 0, 0
pos_x, pos_y, pos_z = 0, 1, 0 # 玩家位置
mouse_locked = True
pygame.mouse.set_visible(not mouse_locked)
pygame.event.set_grab(mouse_locked)
running = True
while running:
dt = clock.tick(60) / 1000.0 # 帧时间差
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
mouse_locked = not mouse_locked
pygame.mouse.set_visible(not mouse_locked)
pygame.event.set_grab(mouse_locked)
if event.type == MOUSEMOTION and mouse_locked:
dx, dy = event.rel
angle_x += dx * 0.15
angle_y -= dy * 0.15
angle_y = max(-89, min(89, angle_y)) # 限制上下看角度
# 获取按键状态
keys = pygame.key.get_pressed()
forward = np.array([
np.sin(np.radians(angle_x)),
0,
np.cos(np.radians(angle_x))
])
right = np.array([
np.sin(np.radians(angle_x + 90)),
0,
np.cos(np.radians(angle_x + 90))
])
if keys[K_w]:
pos_x += forward[0] * dt * 5
pos_z += forward[2] * dt * 5
if keys[K_s]:
pos_x -= forward[0] * dt * 5
pos_z -= forward[2] * dt * 5
if keys[K_a]:
pos_x -= right[0] * dt * 5
pos_z -= right[2] * dt * 5
if keys[K_d]:
pos_x += right[0] * dt * 5
pos_z += right[2] * dt * 5
if keys[K_SPACE]:
pos_y += dt * 3
if keys[K_LSHIFT]:
pos_y -= dt * 3
# 鼠标点击交互
mouse_buttons = pygame.mouse.get_pressed()
if mouse_buttons[0]: # 左键破坏方块
block_pos = (int(pos_x), int(pos_y), int(pos_z))
if block_pos in world:
del world[block_pos]
elif mouse_buttons[2]: # 右键放置方块
block_pos = (int(pos_x + 2 * np.sin(np.radians(angle_x))),
int(pos_y),
int(pos_z + 2 * np.cos(np.radians(angle_x))))
if block_pos not in world:
world[block_pos] = (0.6, 0.6, 0.6) # 灰色新方块
# 更新视角
glLoadIdentity()
gluPerspective(45, (800 / 600), 0.1, 100.0)
# 计算视线方向
rad_x = np.radians(angle_x)
forward_vec = [
np.sin(rad_x),
np.sin(np.radians(angle_y)),
np.cos(rad_x)
]
target = (pos_x + forward_vec[0], pos_y + forward_vec[1], pos_z + forward_vec[2])
glRotatef(angle_y, 1, 0, 0)
glRotatef(angle_x, 0, 1, 0)
glTranslatef(-pos_x, -pos_y, -pos_z)
# 渲染场景
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
for block_pos, color in world.items():
draw_cube(block_pos, color)
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()