所以我用pygame在python中做了一個raycaster。我一點一點地投射我的光線,一旦它們撞到墻,我計算距離并使用我的墻的高度。問題是我的墻壁是彎曲的。
遺憾的是我的照片無法上傳,但我會盡力解釋。
我以為我已經通過添加這個來解決這個問題
angle = math.radians(self.view - degree)
dist *= math.cos(angle)
但這樣一來,我左邊或右邊的墻壁仍然是彎曲的。我已經嘗試了幾個小時試圖解決這個問題,但我似乎找不到正確的答案。如果您有想法,請發表評論!
這是完整的代碼,或者你可以在
優化的最小示例:

import pygame
import math
pygame.init()
tile_size, map_size = 50, 8
board = [
'########',
'# # #',
'# # ##',
'# ## #',
'# #',
'### ###',
'# #',
'########']
def cast_rays(sx, sy, angle):
rx = math.cos(angle)
ry = math.sin(angle)
map_x = sx // tile_size
map_y = sy // tile_size
t_max_x = sx/tile_size - map_x
if rx > 0:
t_max_x = 1 - t_max_x
t_max_y = sy/tile_size - map_y
if ry > 0:
t_max_y = 1 - t_max_y
while True:
if ry == 0 or t_max_x < t_max_y * abs(rx / ry):
side = 'x'
map_x = 1 if rx > 0 else -1
t_max_x = 1
if map_x < 0 or map_x >= map_size:
break
else:
side = 'y'
map_y = 1 if ry > 0 else -1
t_max_y = 1
if map_x < 0 or map_y >= map_size:
break
if board[int(map_y)][int(map_x)] == "#":
break
if side == 'x':
x = (map_x (1 if rx < 0 else 0)) * tile_size
y = player_y (x - player_x) * ry / rx
direction = 'r' if x >= player_x else 'l'
else:
y = (map_y (1 if ry < 0 else 0)) * tile_size
x = player_x (y - player_y) * rx / ry
direction = 'd' if y >= player_y else 'u'
return (x, y), math.hypot(x - sx, y - sy), direction
def cast_fov(sx, sy, angle, fov, no_ofrays):
max_d = math.tan(math.radians(fov/2))
step = max_d * 2 / no_ofrays
rays = []
for i in range(no_ofrays):
d = -max_d (i 0.5) * step
ray_angle = math.atan2(d, 1)
pos, dist, direction = cast_rays(sx, sy, angle ray_angle)
rays.append((pos, dist, dist * math.cos(ray_angle), direction))
return rays
window = pygame.display.set_mode((tile_size*map_size*2, tile_size*map_size))
clock = pygame.time.Clock()
board_surf = pygame.Surface((tile_size*map_size, tile_size*map_size))
for row in range(8):
for col in range(8):
color = (192, 192, 192) if board[row][col] == '#' else (96, 96, 96)
pygame.draw.rect(board_surf, color, (col * tile_size, row * tile_size, tile_size - 2, tile_size - 2))
player_x, player_y = round(tile_size * 4.5) 0.5, round(tile_size * 4.5) 0.5
player_angle = 0
max_speed = 3
colors = {'r' : (196, 128, 64), 'l' : (128, 128, 64), 'd' : (128, 196, 64), 'u' : (64, 196, 64)}
run = True
while run:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
hit_pos_front, dist_front, side_front = cast_rays(player_x, player_y, player_angle)
hit_pos_back, dist_back, side_back = cast_rays(player_x, player_y, player_angle math.pi)
player_angle = (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 0.1
speed = ((0 if dist_front <= max_speed else keys[pygame.K_UP]) - (0 if dist_back <= max_speed else keys[pygame.K_DOWN])) * max_speed
player_x = math.cos(player_angle) * speed
player_y = math.sin(player_angle) * speed
rays = cast_fov(player_x, player_y, player_angle, 60, 40)
window.blit(board_surf, (0, 0))
for ray in rays:
pygame.draw.line(window, (0, 255, 0), (player_x, player_y), ray[0])
pygame.draw.line(window, (255, 0, 0), (player_x, player_y), hit_pos_front)
pygame.draw.circle(window, (255, 0, 0), (player_x, player_y), 8)
pygame.draw.rect(window, (128, 128, 255), (400, 0, 400, 200))
pygame.draw.rect(window, (128, 128, 128), (400, 200, 400, 200))
for i, ray in enumerate(rays):
height = round(256 / (ray[2]/50))
color = pygame.Color((0, 0, 0)).lerp(colors[ray[3]], min(height/256, 1))
rect = pygame.Rect(400 i*10, 200-height//2, 10, height)
pygame.draw.rect(window, color, rect)
pygame.display.flip()
pygame.quit()
exit()
另請參閱PyGameExamplesAndAnswers - Raycasting
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/515352.html
上一篇:如何計算兩個矩形角之間的距離
下一篇:獲取火箭的軌跡
