【发布时间】:2019-11-02 19:16:40
【问题描述】:
至于我之前的问题,我正在尝试在 pygame 中模拟一个 3d 空间。到目前为止,我想出了一个非常简单的想法,它使用第三个坐标作为分母来“压缩”(很确定这里有一些我不知道的术语)屏幕中心周围最远的点并减小它们的大小.
有人可以建议对这个想法进行简单的改进吗?我觉得我可以调整用于投影的分母(请参阅代码)以创建更准确的模拟方式。
如果你运行下面的代码,你会得到一个不错的模拟(比如说)一艘飞船经过一些星星(按 w 或 s)。如果他们走远了,他们就会消失,之后会创建一个新的。但是,如果我应用旋转(a 或 d),很明显模拟效果不佳,因为我并没有真正将 3d 点投影到 2d 屏幕上。
import pygame
import random
import numpy as np
pygame.init()
run=True
#screensize
screensize = (width,height)=(600,600)
center=(int(width/2),int(height/2))
screen = pygame.display.set_mode(screensize)
#delta mov
ds=0.1
do=0.0001
#Stars
points=[]
for i in range(1000):
n1 = random.randrange(-5000,5000)
n2 = random.randrange(-5000,5000)
n3 = random.randrange(-30,30)
points.append([n1,n2,n3])
while run:
pygame.time.delay(20)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run=False
################## keys
keys=pygame.key.get_pressed()
if keys[pygame.K_w]:
for p in points:
p[2]-=ds
if keys[pygame.K_s]:
for p in points:
p[2]+=ds
if keys[pygame.K_a] or keys[pygame.K_d]:
if keys[pygame.K_a]:
for p in points:
p[0]=np.cos(-do)*p[0]-np.sin(-do)*p[2]
p[2]=np.sin(-do)*p[0]+np.cos(-do)*p[2]
else:
for p in points:
p[0]=np.cos(do)*p[0]-np.sin(do)*p[2]
p[2]=np.sin(do)*p[0]+np.cos(do)*p[2]
###############################projection###################
for p in points:
#this is to create new stars
if p[2]<=-30 or p[2]>=30:
p[0] = random.randrange(-5000,5000)
p[1] = random.randrange(-5000,5000)
p[2] =30
else:
#this is to ignore stars which are behind the ship
if p[2]<=0:
pass
else:
try:
#THIS IS THE PROJECTION I USE, I TAKE THE RADIUS BECAUSE I GUESS I'LL NEED IT... BUT I DON'T USE IT XD
r = ((p[0]**2+p[1]**2+p[2]**2)**(1/2))
pygame.draw.circle(screen,(255,255,0),(int(p[0]/p[2]+center[0]),int(p[1]/p[2]+center[1])),int(10/p[2]))
#this is to prevent division by cero and alike
except Exception as e:
pass
pygame.display.update()
screen.fill((0,0,0))
pygame.quit()
【问题讨论】:
-
你所做的一点也不差。一般perspective是通过Homogeneous coordinates实现的。你的方法很接近。
-
一定是错了XD,我旋转场景就乱了
标签: python 3d pygame projection perspective