So I started a new project where I am tying to imitate this. It is a pseudo 3d world where a ray in cast in a 2d world and the farther away the ray travels, the smaller the walls, giving the illusion of 3d. I stared by writing rays. The way I thought of doing this is:
- Initialize a whole load of rays going from
player's angle
-player's FOV/2
toplayer's angle
+player's FOV/2
. This is basically the player field of view. - Shoot the rays in the specified direction. However, my problem is that that rays are too slow and I cant think of anything to make it go faster.
Here is the code:
import pygame
from math import sin, cos, tan, radians
pygame.init()
SW = 1200
SH = 600
WIN = pygame.display
D = WIN.set_mode((SW, SH))
class Ray:
def __init__(self, x, y, theta):
self.x = x
self.y = y
self.theta = theta
# draw only for debugging
def draw(self):
pygame.draw.circle(D, (255, 255, 0), (int(self.x), int(self.y)), 1)
class Player:
def __init__(self, x, y):
self.fov = 1.5
self.x = x
self.y = y
self.theta = 0
player = Player(600, 300)
class Sim:
def __init__(self):
self.rays = []
#lower end is
lowerEnd = player.theta - player.fov/2
previous = 0
# fov is 1.5 rads(90 degrees), so
# i want there to be 900 rays
# in 90 degrees so that every pixel
# is covered (90/0.1) becasue rays
# seem to diverge as they get farther
# away
while len(self.rays) < 900:
previous += radians(0.1)# 0.1 in radians
self.rays.append(Ray(player.x, player.y, lowerEnd + previous))
sim = Sim()
while True:
#D.fill(0)
keys = pygame.key.get_pressed()
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
#print(self.rays[0].x, self.rays[0].y)
for ray in sim.rays:
ray.x += cos(ray.theta)
ray.y -= sin(ray.theta)
ray.draw()
pygame.display.flip()
Running the code, you will be able to see that that all the pixels are covered, but it almost takes 2 seconds for the rays to get from the centre to the edge. I could force the rays to travel faster by skipping pixels, but that may bring unwanted problems later.
for ray in self.rays:
ray.x += cos(ray.theta) * 20
ray.y -= sin(ray.theta) * 20
I suspect that it might be faster when the rays are not drawn, but I cant think of a way to test this because printing the position values would also make it slow. Thanks for any help.