I am following the raycasting engine tutorial by javidx9 (the tutorial is here: https://www.youtube.com/watch?v=xW8skO7MFYw), but I am writing it in Python instead. Note that I am stuck at around the 20-minute mark. He is able to achieve movement (back and forth, forward and backward, etc), but I am absolutely stumped as to why this is not working in my version. I have no error messages, I have tried setting variables such as the ray angle as constants, and I have tried modifying the map to see anything else than the standard bars appearing; but it doesn't seem to budge! All of the dependencies are built-ins, so it would be easy to test. Could someone more experienced with raycasting math tell me what I am doing wrong?
# Source.py
import os, sys, time, math, curses
"""Global variables"""
##########
SCREEN_WIDTH, SCREEN_HEIGHT = 120, 40 # os.get_terminal_size()# 120, 40# os.get_terminal_size() # 120 : 40
screen = []
# for _ in range(40 * 120):
for _ in range(SCREEN_WIDTH * SCREEN_HEIGHT):
screen.append("")
player_x = 8.0
player_y = 8.0
player_angle = 0.0
MAP_HEIGHT, MAP_WIDTH = 16, 16
FOV = math.pi / 4
DEPTH = 16.0
map_ = ""
map_ += "################"
map_ += "#..............#"
map_ += "#..............#"
map_ += "#........####..#"
map_ += "#........#..#..#"
map_ += "#........#..####"
map_ += "#..............#"
map_ += "###............#"
map_ += "#..........#...#"
map_ += "#...#..........#"
map_ += "#..........#...#"
map_ += "###....#.#.....#"
map_ += "#..............#"
map_ += "#..............#"
map_ += "#..............#"
map_ += "################"
COLOR = "\033[48;5;{}m{}\033[0m"
##########
def make_screen():
for index, char in enumerate(screen):
yield "\n" if index % SCREEN_WIDTH == 0 else char
def get_char(stdscr):
stdscr.nodelay(True)
char_num = stdscr.getch()
if char_num != -1:
return chr(char_num)
def main():
global screen, player_angle, player_x, player_y
time_1 = time.time()
time_2 = time.time()
while True:
for char in make_screen(): print(char, end = "")
time_2 = time.time()
elapsed = float(time_2 - time_1)
time_1 = time_2
key = curses.wrapper(get_char)
# key = input(">")
# key = "a"
time.sleep(0.2)
if key == "a":
player_angle -= 0.8 * elapsed
elif key == "d":
player_angle += 0.8 * elapsed
elif key == "w":
player_x += math.sin(player_angle) * 5.0 * elapsed
player_y += math.cos(player_angle) * 5.0 * elapsed
elif key == "s":
player_x -= math.sin(player_angle) * 5.0 * elapsed
player_y -= math.cos(player_angle) * 5.0 * elapsed
os.system("printf '\033c'")
for x in range(SCREEN_WIDTH):
ray_angle = (player_angle - FOV / 2.0) + (float(x) / float(SCREEN_WIDTH)) * FOV
# ray_angle = 30.0
print("ray angle", ray_angle)
distance_to_wall = 0.0
has_hit_wall = False
eye_x = math.sin(ray_angle)
eye_y = math.cos(ray_angle)
while not has_hit_wall and distance_to_wall < DEPTH:
distance_to_wall += 0.1
test_x = int(player_x + eye_x * distance_to_wall)
test_y = int(player_y + eye_y * distance_to_wall)
if test_x < 0 or test_x >= MAP_WIDTH or test_y < 0 or test_y >= MAP_HEIGHT:
hit_wall = True
distance_to_wall = DEPTH
else:
if map_[test_x * MAP_WIDTH + test_x] == "#":
hit_wall = True
ceiling = int(float(SCREEN_HEIGHT / 2.0) - SCREEN_HEIGHT / float(distance_to_wall))
floor = SCREEN_HEIGHT - ceiling
shade = 0
if distance_to_wall <= DEPTH / 4: shade = 207
elif distance_to_wall <= DEPTH / 3: shade = 208
elif distance_to_wall <= DEPTH / 2: shade = 209
elif distance_to_wall <= DEPTH: shade = 210
for y in range(SCREEN_HEIGHT):
if y < ceiling:
screen[y * SCREEN_WIDTH + x] = COLOR.format(34, " ")
elif y > ceiling and y <= floor:
screen[y * SCREEN_WIDTH + x] = COLOR.format(shade, " ")
else:
screen[y * SCREEN_WIDTH + x] = COLOR.format(34, " ")
if __name__ == "__main__":
main()