猫史档案馆


【Python作品分享】PyGame 3D正方形【教程贴】

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


【作品展示】

center_image

 

【作品介绍】

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


回复

上一页1 页 / 共 0下一页