felipebubu
felipebubu

Reputation: 171

Why my raycasting keeps going through walls?

here's my code, ignore unused stuff and its overal messiness

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()

so far, it's behaving this way:

faulty raycasting

it works, but it doesn't. i've tinkered the numbers, sometimes it gets better adding to the x, to the y, but it doesn't work completely. If you guys wanna try on your computer, here are the files needed for: map

ball

(it's tiny) so, what's going on?

Upvotes: 2

Views: 373

Answers (1)

Rabbid76
Rabbid76

Reputation: 210889

You need to read the color of the map instead of the color of the screen. You draw the lines on the screen, each line "cuts a small piece of the wall:

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):

Alternatively you can draw the lines after casting the rays:

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)

Upvotes: 1

Related Questions