Search code examples
pythonpython-3.xtkinter2d

RecursionError when calling math.dist()


When calling math.dist() to find the distance between two points, I get a RecursionError. This is the error:

Traceback (most recent call last):
  File "/Users/myName/Desktop/2D Renderer.py", line 76, in <module>
    mainLoop()
  File "/Users/myName/Desktop/2D Renderer.py", line 74, in mainLoop
    canvas.after(10,mainLoop())
  File "/Users/myName/Desktop/2D Renderer.py", line 74, in mainLoop
    canvas.after(10,mainLoop())
  File "/Users/myName/Desktop/2D Renderer.py", line 74, in mainLoop
    canvas.after(10,mainLoop())
  [Previous line repeated 1018 more times]
  File "/Users/myName/Desktop/2D Renderer.py", line 71, in mainLoop
    result, color, x = checkRay([0,5],100)
  File "/Users/myName/Desktop/2D Renderer.py", line 48, in checkRay
    result, color = checkPoint(position)
  File "/Users/myName/Desktop/2D Renderer.py", line 56, in checkPoint
    result = sdCircle(position,shape.radius,shape.position)
  File "/Users/myName/Desktop/2D Renderer.py", line 66, in sdCircle
    return math.dist(position,circlePosition) - circleRadius;
RecursionError: maximum recursion depth exceeded while calling a Python object

I tried changing my code to run canvas.after(10,mainLoop()) in a infinite while loop but this caused a freeze. Here is my code:

from tkinter import *
from tkinter import ttk
from enum import Enum
import math
root = Tk()
root.title("2D Renderer")
canvas = Canvas(root, width=500, height=50, background='gray75')
canvas.grid(column=0,row=0)

class Player:
    def __init__(self,position,rotation):
        self.position = position
        self.rotation = rotation

player = Player([0,0],[0,1])

def setPixel(x,y,color):
    canvas.create_rectangle(x+3, y+3, x+3, y+3, outline="",fill=color)

def setPixel1D(x,color):
    canvas.create_line(x+3, 0, x+3, 50,fill='red')

class Shapes(Enum):
    CIRCLE = 1
    SQUARE = 2

class Shape:
    def __init__(self,shape: Shapes,position,radius,color):
        self.shape = shape
        self.position = position
        self.radius = radius
        self.color = color

shapes = [Shape(Shapes.CIRCLE,[0,100],50,'ff0000')]

def normalizeVector(vector):
    length = math.sqrt(vector[0] * vector[0] + vector[1] * vector[1])
    vector[0] /= length
    vector[1] /= length
    return vector

def checkRay(vector,max_steps):
    vector = normalizeVector(vector)
    position = player.position
    for i in range(max_steps):
        position[0] += vector[0]
        position[1] += vector[1]
        result, color = checkPoint(position)
        if result:
            return True, color, position[0] / position[1] - player.position[1]
    return False, None, None

def checkPoint(position):
    for shape in shapes:
        if shape.shape == Shapes.CIRCLE:
            result = sdCircle(position,shape.radius,shape.position)
            if result <= 0:
                return True, shape.color
            else:
                return False, None
        else:
            return False, None
                

def sdCircle(position, circleRadius, circlePosition):
    return math.dist(position,circlePosition) - circleRadius;



def mainLoop():
    result, color, x = checkRay([0,5],100)
    if result:
        setPixel1D(x, color)
    canvas.after(10,mainLoop())

mainLoop()

I am trying to get mainLoop() to run infinitely while giving canvas enough time to update.


Solution

  • There is a infinite recursion in your code on this line: canvas.after(10,mainLoop()). Canvas.after() (or the .after() method of any tkinter object, for that matter) is supposed to take 2 arguments:

    1. the time to wait before executing the callable (argument 2)
    2. the callable object to be called after the waiting time.

    The second argument passed should be a callable object, not the returned value of the callable object, which is what you did in the line canvas.after(10,mainLoop()). Consider changing it to this:

    canvas.after(10,mainLoop)
    

    It will solve your problem.