为什么我的光线投射一直穿过墙壁?
Why my raycasting keeps going through walls?
这是我的代码,忽略未使用的内容及其整体混乱
import sys, pygame, time, math
pygame.init()
size = width, height = 640, 640
black = 0, 0, 0
screen = pygame.display.set_mode(size)
ball = pygame.image.load("ball.png")
map = pygame.image.load("map.png")
ballrect = ball.get_rect()
ballrect.x = 262
ballrect.y = 582
direction = math.pi
FOV = math.pi / 3
HALF_FOV = FOV / 2
CASTED_ARRAYS = 640
STEP_ANGLE = FOV / CASTED_ARRAYS
MAX_DEPTH = 640
def cast_rays():
start_angle = direction - HALF_FOV
for ray in range(CASTED_ARRAYS):
for depth in range(MAX_DEPTH):
target_x = (ballrect.centerx) - math.sin(start_angle) * depth
target_y = (ballrect.centery) + math.cos(start_angle) * depth
if screen.get_at((int(target_x), int(target_y))) == (223, 113, 38):
pygame.draw.line(screen, (0, 255, 255), (ballrect.centerx, ballrect.centery),
(target_x, target_y))
break
start_angle += STEP_ANGLE
while 1:
screen.blit(map, (0, 0))
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
direction -= 0.1
if keys[pygame.K_RIGHT]:
direction += 0.1
if keys[pygame.K_UP]:
ballrect.centerx += -math.sin(direction) * 5
ballrect.centery += math.cos(direction) * 5
if keys[pygame.K_DOWN]:
ballrect.centerx -= -math.sin(direction) * 5
ballrect.centery -= math.cos(direction) * 5
time.sleep(0.01)
screen.blit(ball, ballrect)
cast_rays()
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
到目前为止,它的行为是这样的:
有效,但无效。我修改了数字,有时它会更好地添加到 x 和 y,但它并不完全有效。如果你们想在您的计算机上尝试,这里是需要的文件:
(很小)
那么,这是怎么回事?
您需要阅读地图的颜色,而不是屏幕的颜色。你在屏幕上画线,每条线“切一小块墙:
if screen.get_at((int(target_x), int(target_y))) == (223, 113, 38):
if map.get_at((int(target_x), int(target_y))) == (223, 113, 38):
或者您可以在投射光线后绘制线条:
def cast_rays():
targets = []
for ray in range(CASTED_ARRAYS):
angle = direction - HALF_FOV + ray * STEP_ANGLE
s, c = math.sin(angle), math.cos(angle)
for depth in range(MAX_DEPTH):
target = (round(ballrect.centerx - s * depth), round(ballrect.centery + c * depth))
if screen.get_at(target) == (223, 113, 38):
targets.append(target)
break
start = (ballrect.centerx, ballrect.centery)
for target in targets:
pygame.draw.line(screen, (0, 255, 255), start, target)
这是我的代码,忽略未使用的内容及其整体混乱
import sys, pygame, time, math
pygame.init()
size = width, height = 640, 640
black = 0, 0, 0
screen = pygame.display.set_mode(size)
ball = pygame.image.load("ball.png")
map = pygame.image.load("map.png")
ballrect = ball.get_rect()
ballrect.x = 262
ballrect.y = 582
direction = math.pi
FOV = math.pi / 3
HALF_FOV = FOV / 2
CASTED_ARRAYS = 640
STEP_ANGLE = FOV / CASTED_ARRAYS
MAX_DEPTH = 640
def cast_rays():
start_angle = direction - HALF_FOV
for ray in range(CASTED_ARRAYS):
for depth in range(MAX_DEPTH):
target_x = (ballrect.centerx) - math.sin(start_angle) * depth
target_y = (ballrect.centery) + math.cos(start_angle) * depth
if screen.get_at((int(target_x), int(target_y))) == (223, 113, 38):
pygame.draw.line(screen, (0, 255, 255), (ballrect.centerx, ballrect.centery),
(target_x, target_y))
break
start_angle += STEP_ANGLE
while 1:
screen.blit(map, (0, 0))
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
direction -= 0.1
if keys[pygame.K_RIGHT]:
direction += 0.1
if keys[pygame.K_UP]:
ballrect.centerx += -math.sin(direction) * 5
ballrect.centery += math.cos(direction) * 5
if keys[pygame.K_DOWN]:
ballrect.centerx -= -math.sin(direction) * 5
ballrect.centery -= math.cos(direction) * 5
time.sleep(0.01)
screen.blit(ball, ballrect)
cast_rays()
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
到目前为止,它的行为是这样的:
有效,但无效。我修改了数字,有时它会更好地添加到 x 和 y,但它并不完全有效。如果你们想在您的计算机上尝试,这里是需要的文件:
(很小) 那么,这是怎么回事?
您需要阅读地图的颜色,而不是屏幕的颜色。你在屏幕上画线,每条线“切一小块墙:
if screen.get_at((int(target_x), int(target_y))) == (223, 113, 38):
if map.get_at((int(target_x), int(target_y))) == (223, 113, 38):
或者您可以在投射光线后绘制线条:
def cast_rays():
targets = []
for ray in range(CASTED_ARRAYS):
angle = direction - HALF_FOV + ray * STEP_ANGLE
s, c = math.sin(angle), math.cos(angle)
for depth in range(MAX_DEPTH):
target = (round(ballrect.centerx - s * depth), round(ballrect.centery + c * depth))
if screen.get_at(target) == (223, 113, 38):
targets.append(target)
break
start = (ballrect.centerx, ballrect.centery)
for target in targets:
pygame.draw.line(screen, (0, 255, 255), start, target)