用户:
有趣的超能鸭QX64查看:0 回复:0 评论:0 创建时间:2021-01-26T12:12:30
【作品展示】

【作品介绍】
Pygame 3D
【作品源代码】
import pygame
import os
from pygame.locals import *
from pygame.math import *
from math import *
from random import randint
print("操作方法:\
w,a,s,d控制前进等,\
空格上升,\
按esc退出,\
鼠标控制方向。\
")
i = int(input("鼠标偏移量是否打开(1:是/2:否):"))
c = int(input("摄像机速度是否打开(默认30.0, 30.0, 30.0)(1:是/2:否):"))
D = int(input("是否显示鼠标(1:是/2:否):"))
P = int(input("是否锁定鼠标(1:是/2:否):"))
E = ""
y = ""
# 窗口大小
SCREEN_SIZE = (840, 680)
# 正方体边长
CUBE_SIZE = 300
# pygame 初始化
pygame.init()
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (10, 10)
screen = pygame.display.set_mode(SCREEN_SIZE, 0)
font = pygame.font.SysFont('simhei', 24)
clock = pygame.time.Clock()
# 让pygame完全控制鼠标
if D == 1:
y = True
else:
y = False
print(y)
pygame.mouse.set_visible(y)
if P == 1:
E = True
else:
E = False
print(E)
pygame.event.set_grab(E)
# 3D points(所有的小球都在这)
points = []
fov = 90. # 视野
rov = 5
mov = 90
FPS = 60
is_grab = True
def calculate_viewing_distance(fov, screen_width):
d = (screen_width / 2.0) / tan(fov / 2.0)
return d
def set_points():
# 边沿的一系列点
for x in range(0-20*5, CUBE_SIZE + 1 + 20*5, 20):
edge_x = x == 0 or x == CUBE_SIZE
for y in range(0-20*5, CUBE_SIZE + 1 + 20*5, 20):
edge_y = y == 0 or y == CUBE_SIZE
for z in range(0-20*5, CUBE_SIZE + 1 + 20*5, 20):
edge_z = z == 0 or z == CUBE_SIZE
if sum((edge_x, edge_y, edge_z)) >= 2:
point_x = float(x) - CUBE_SIZE / 2
point_y = float(y) - CUBE_SIZE / 2
point_z = float(z) - CUBE_SIZE / 2
points.append(Vector3(point_x, point_y, point_z))
def move_points(dv):
for p in points:
p.update(p + dv)
points.sort(key=lambda p: p.z, reverse=True)
def rotate_points(p_float, v):
for p in points:
p.update(p.rotate(p_float, v))
points.sort(key=lambda p: p.z, reverse=True)
def run():
global fov, is_grab
# 视距
viewing_distance = calculate_viewing_distance(radians(fov), SCREEN_SIZE[0])
set_points()
center_x, center_y = SCREEN_SIZE
center_x /= 2
center_y /= 2
ball_w, ball_h = 50, 50
ball_center_x = ball_w / 2
ball_center_y = ball_h / 2
camera_position = Vector3(0.0, 0.0, 0.0) # 摄像机位置
if c == 1:
camera_speed = Vector3(30.0, 30.0, 30.0) # 摄像机速度
while True:
for event in pygame.event.get():
if event.type == QUIT:
return
# 按Esc则退出游戏
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
screen.fill((0, 0, 0))
pressed_keys = pygame.key.get_pressed()
if i == 1:
pressed_mouse = pygame.mouse.get_pressed()
movement_direction = 0. # 鼠标偏移量
if is_grab:
mouse_rel = pygame.mouse.get_rel()
drx = mouse_rel[0] * 2 * rov
dry = mouse_rel[1] * 2 * rov
else:
drx, dry = 0, 0
dx, dy, dz = 0.0, 0.0, 0.0
# 旋转
# 绕y轴旋转
rotate_points(drx * 1/FPS, Vector3(0.0, -1.0, 0.0))
# 绕x轴旋转
rotate_points(dry * 1/FPS, Vector3(-1.0, 0.0, 0.0))
if pressed_keys[K_a]:
dx = +mov * 1/FPS
elif pressed_keys[K_d]:
dx = -mov * 1/FPS
if pressed_keys[K_w]:
dz = -mov * 1/FPS
elif pressed_keys[K_s]:
dz = +mov * 1/FPS
if pressed_keys[K_SPACE]:
dy = -mov * 1/FPS
elif pressed_keys[K_LCTRL]:
dy = +mov * 1/FPS
if pressed_keys[K_BACKQUOTE] and is_grab:
pygame.mouse.set_visible(True)
pygame.event.set_grab(False)
is_grab = False
elif pressed_keys[K_BACKQUOTE]:
pygame.mouse.set_visible(False)
pygame.event.set_grab(True)
is_grab = True
if pressed_keys[K_o]:
fov = min(179., fov + 1.)
w = SCREEN_SIZE[0]
viewing_distance = calculate_viewing_distance(radians(fov), w)
elif pressed_keys[K_l]:
fov = max(1., fov - 1.)
w = SCREEN_SIZE[0]
viewing_distance = calculate_viewing_distance(radians(fov), w)
move_points(Vector3(dx, dy, dz))
# 绘制点
for point in points:
x, y, z = point - camera_position
if z > 0:
x = x * viewing_distance / z
y = -y * viewing_distance / z
x += center_x
y += center_y
bw = min(100/point.magnitude()*ball_w, center_x)
pygame.draw.circle(
screen,
(255, 0, 0),
(int(x - ball_center_x), int(y - ball_center_y)),
int(bw)
)
# 绘制表
diagram_width = SCREEN_SIZE[0] / 4
col = (50, 255, 50)
diagram_points = []
diagram_points.append((diagram_width / 2, 100 + viewing_distance / 4))
diagram_points.append((0, 100))
diagram_points.append((diagram_width, 100))
diagram_points.append((diagram_width / 2, 100 + viewing_distance / 4))
diagram_points.append((diagram_width / 2, 100))
pygame.draw.lines(screen, col, False, diagram_points, 2)
# 绘制文字
white = (255, 255, 255)
cam_text = font.render("摄像机出生点 = " + str(camera_position), True, white)
screen.blit(cam_text, (5, 5))
fov_text = font.render("摄像机视野 = %i" % int(fov), True, white)
screen.blit(fov_text, (5, 35))
txt = "摄像机视距 = %.3f" % viewing_distance
d_text = font.render(txt, True, white)
screen.blit(d_text, (5, 65))
pygame.display.update()
time_passed = clock.tick(FPS)
if __name__ == "__main__":
run()
【提示】
部分含有Python第三方库相关内容的作品,在海龟编辑器网页端无法运行哦!如遇到这种情况,可以打开下面的链接,下载海龟编辑器客户端:
https://python.codemao.cn