I am writing a pseudo-3D game in Python. After I tried to fix the fisheye problem, a new one appeared - if you stand close to the wall and look so that the wall is on the side, then the borders of the wall will be round, not straight. Here is the code and screenshot

WIDTH, HEIGHT = 1024, 800
px = 502 #player x
py = 290 #player y
pr = 15 #player radius (viewed from top to bottom, the player will be a circle with the given radius)
angle = 0 #central ray
vision_distance = 500
important = vision_distance - pr
prop = WIDTH / important
rays = 200 #rays count
view_angle = 90
rays_distance = view_angle / rays #distance between rays
wall_width = WIDTH / rays
color_prop = 255 / vision_distance
j = 0

for i in frange(angle-view_angle//2, angle+view_angle//2+rays_distance, rays_distance): #frange is range with float numbers support, check picture to understand the arguments
        x2 = px+math.cos(math.radians(i))*vision_distance # check picture
        y2 = py+math.sin(math.radians(i))*vision_distance # check picture
        for wall in walls:
            colrect = collision_rect(px, py, x2, y2, wall.x, wall.y, wall.width, wall.height)
            if (colrect): #If ray collide with wall
                _d = (min(colrect) - pr) * math.cos(math.radians(abs(angle - i))) # Distance between player and wall
                _3d_wall_height = (important - _d) * prop
                _x = j * wall_width # x coordinate of 3D wall
                _y = (HEIGHT / 2) - (_3d_wall_height / 2) # y coordinate of 3D wall
                color = (vision_distance - abs(_d)) * color_prop
                pygame.draw.rect(display, (color, color, color), (_x, _y, wall_width+1, _3d_wall_height))


explaining variables

  • 1
    \$\begingroup\$ Because you've only solved the problem in one axis. Your diagram is wrong for both screen axes, x and y. Raycasters with non-fisheye perspective are not meant to have their rays shooting out at fixed angles with the same length i.e. radius. Instead they are meant to shoot to the surface of the far viewing plane -- a flat plane, not a hemispherical surface nor a hemicylindrical surface which is what it looks like you currently have. This means the ray lengths vary according to the distance from the eye to the surface of that plane. \$\endgroup\$
    – Engineer
    Jul 22, 2023 at 14:29
  • 1
    \$\begingroup\$ I have an answer with some diagrams showing what Engineer is describing here \$\endgroup\$
    – DMGregory
    Jul 22, 2023 at 15:14
  • \$\begingroup\$ @Engineer i know, the collision_rect function is responsible for calculating the distance from the player to the object, which will return the distance \$\endgroup\$
    – kingley
    Jul 22, 2023 at 15:39
  • 1
    \$\begingroup\$ That cannot fix the root problem which is that you're firing rays at evenly spaced intervals in the first place. You cannot get a correct display for a flat screen that way. \$\endgroup\$
    – DMGregory
    Jul 24, 2023 at 1:42


You must log in to answer this question.

Browse other questions tagged .