[Python] How do I fix the fisheye effect on my python raycaster?

Discussão em 'Python' iniciado por Stack, Junho 25, 2025.

  1. Stack

    Stack Membro Participativo

    I really can't seem to fix the fisheye effect, I've been reading other solutions and I'm starting to think there's a deeper issue even though the code does work. The vertical lines drawn to represent the 'walls' are curved when they should be straight, I think it's caused by the rays coming from the player being different lengths when interacting with a straight wall. I'm still fairly new to python.

    # imports
    import turtle, math

    # variables

    raycastAngle = 90
    raycastRayNum = 100
    raycastRayRange = 100
    raycastRayStep = 2

    screenX, screenY = 800, 600
    screen = turtle.Screen()
    screen.screensize(screenX, screenY)
    screen.tracer(0)
    screen.bgcolor(0, 0, 0)

    raycaster = turtle.Turtle()
    raycaster.penup()
    raycaster.hideturtle()

    player = turtle.Turtle()
    player.penup()
    player.setheading(45)
    player.hideturtle()

    sceneStamp = turtle.Turtle()
    sceneStamp.penup()
    sceneStamp.hideturtle()

    walls = {

    'test wall1':{

    'x': 70,
    'y': 70,
    'width': 100,
    'height': 100
    },

    }

    # subprograms

    def distFromCoords(startCoord, endCoord):
    xDist = endCoord[0] - startCoord[0]
    yDist = endCoord[1] - startCoord[1]

    distance = math.sqrt((xDist * xDist) + (yDist * yDist))
    roundedDistance = round(distance)
    return roundedDistance

    def isInsideWall(turtle):
    turtleX, turtleY = turtle.xcor(), turtle.ycor()

    for wall in walls.values():
    wallX, wallY = wall['x'], wall['y']
    wallWidth, wallHeight = wall['width'], wall['height']

    left = wallX - wallWidth / 2
    right = wallX + wallWidth / 2
    bottom = wallY - wallHeight / 2
    top = wallY + wallHeight / 2

    if left <= turtleX <= right and bottom <= turtleY <= top:
    return True

    return False

    def raycast(angle, rayNum, rayRange, rayStep, showRay):
    raycaster.clear()
    startAngle = player.heading() - (angle / 2)

    rayLengths = []

    for i in range(rayNum):
    raycaster.penup()
    raycaster.goto(player.xcor(), player.ycor())
    raycaster.setheading(startAngle + (i * (angle / rayNum)))

    if showRay:
    raycaster.pendown()

    for j in range(rayRange // rayStep):
    raycaster.forward(rayStep)
    if isInsideWall(raycaster):
    break

    rayLengths.append(distFromCoords([player.xcor(), player.ycor()], [raycaster.xcor(), raycaster.ycor()]))

    return rayLengths

    def drawScreen(rayLengths):
    global screenX, screenY
    global raycastAngle, raycastRayNum, raycastRayRange, raycastRayStep

    sceneStamp.clear()
    sceneStamp.penup()
    sceneStamp.pensize(3)
    sceneStamp.goto(-(screenX // 2), 0)

    for i in range(len(rayLengths)):
    rayLength = rayLengths

    height = screenY * (1 - (rayLength / raycastRayRange))
    height = max(0, min(screenY, height))
    sceneStamp.color(0, 0, (0 + (height / screenY)))

    sceneStamp.sety(height / 2)
    sceneStamp.pendown()
    sceneStamp.sety(-height / 2)
    sceneStamp.penup()

    sceneStamp.setx(sceneStamp.xcor() + (screenX / raycastRayNum))

    def gameUpdate():
    screen.update()
    drawScreen(raycast(raycastAngle, raycastRayNum, raycastRayRange, raycastRayStep, True))
    turtle.ontimer(gameUpdate, 15)

    # main program
    gameUpdate()

    screen.listen()
    screen.mainloop()


    I've tried multiplying raw ray lengths by the cosine of player direction minus raycaster direction (or the other way around) and it did nothing (didn't appear to lessen the effect).

    An of the effect on a wall viewed at an angle, it should be straight lines : [​IMG]

    Continue reading...

Compartilhe esta Página