0

I created pong with the help of a youtube tutorial https://www.youtube.com/watch?v=XGf2GcyHPhc&ab_channel=freeCodeCamp.org , and everything works, except the ball goes really fast, and then really slow and so on. The speed of the ball is inconsistent and this makes it hard to play. I did some research and found this, How to fix inconsistent frame rate (speed) in python turtle , I think I did what I had to do, but now the program runs for a couple of seconds, and then stops and gives this error: RecursionError: maximum recursion depth exceeded in instancecheck , what do I do? This is my code right now:

import turtle

window = turtle.Screen()
window.title("Pong by @Ubevg")
window.bgcolor("black")
window.setup(width=800, height=600)
window.tracer(0)

# score
score_A = 0
score_B = 0

# paddle A
paddle_A = turtle.Turtle()
paddle_A.speed(0)
paddle_A.shape("square")
paddle_A.shapesize(stretch_wid=5, stretch_len=1)
paddle_A.color("white")
paddle_A.penup()
paddle_A.goto(-350, 0)

# paddle B
paddle_B = turtle.Turtle()
paddle_B.speed(0)
paddle_B.shape("square")
paddle_B.shapesize(stretch_wid=5, stretch_len=1)
paddle_B.color("white")
paddle_B.penup()
paddle_B.goto(350, 0)

# ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 0.5
ball.dy = 0.5

# pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player A: " + str(score_A) + "  " + "Player B: " + str(score_B), align="center", font=("Courier", 24, "normal"))

# function
def paddle_A_up():
    y = paddle_A.ycor()
    y += 20
    paddle_A.sety(y)

def paddle_A_down():
    y = paddle_A.ycor()
    y -= 20
    paddle_A.sety(y)

def paddle_B_up():
    y = paddle_B.ycor()
    y += 20
    paddle_B.sety(y)

def paddle_B_down():
    y = paddle_B.ycor()
    y -= 20
    paddle_B.sety(y)

# keybind
window.listen()

window.onkeypress(paddle_A_up, ("w"))
window.onkeypress(paddle_A_down, ("s"))

window.onkeypress(paddle_B_up, ("Up"))
window.onkeypress(paddle_B_down, ("Down"))


# main game loop
def move_balls():
    global score_A, score_B
    window.update()

    # move the ball
    ball.setx(ball.xcor() + ball.dx)
    ball.sety(ball.ycor() + ball.dy)

    # border checking
    if ball.ycor() > 290:
        ball.sety(290)
        ball.dy *= -1
    elif ball.ycor() < -290:
        ball.sety(-290)
        ball.dy *= -1

    if ball.xcor() > 390:
        ball.goto(0, 0)
        ball.dx *= -1
        score_A += 1
        pen.clear()
        pen.write("Player A: " + str(score_A) + "  " + "Player B: " + str(score_B), align="center",
                  font=("Courier", 24, "normal"))
    elif ball.xcor() < -390:
        ball.goto(0, 0)
        ball.dx *= -1
        score_B += 1
        pen.clear()
        pen.write("Player A: " + str(score_A) + "  " + "Player B: " + str(score_B), align="center",
                  font=("Courier", 24, "normal"))

    # paddle and ball collisions
    if ball.xcor() > 340 and ball.xcor() < 350 and (ball.ycor() < paddle_B.ycor() + 40 and ball.ycor() > paddle_B.ycor() -40):
        ball.setx(340)
        ball.dx *= -1

    elif ball.xcor() < -340 and ball.xcor() > -350 and (ball.ycor() < paddle_A.ycor() + 40 and ball.ycor() > paddle_A.ycor() -40):
        ball.setx(-340)
        ball.dx *= -1

    window.ontimer(move_balls(), 100)

move_balls()
  • `move_balls` has `window.ontimer(move_balls(), 100)` in it, which is likely the problem. You could try putting the `window.ontimer` call outside of that function, to avoid possible infinite recursion, and see how that helps. Since right now it seems like the function is going to call itself every 100ms, and each call will then call itself again every 100ms, and that's going to multiply until your program crashes. – Random Davis Jan 26 '21 at 17:10
  • Thanks! I put it inside a while True:, and put the timer to 10ms, and it now works perfectly :) – Ube Van Grimbergen Jan 26 '21 at 17:21
  • Okay I'll post my solution as an answer so you can accept it/upvote it if you want. – Random Davis Jan 26 '21 at 17:24
  • Perfect, I will do that, thanks again for the help – Ube Van Grimbergen Jan 26 '21 at 17:26

2 Answers2

1

i got the same problem with tkinter when trying to implement the timer. i think u should remove the brackets from the function when passing it to window.ontimer , like so window.ontimer(move_balls,100) rather not window.ontimer(move_balls(),100)

Kith Stack
  • 11
  • 1
0

move_balls has window.ontimer(move_balls(), 100) in it, which is the problem. You need to put the window.ontimer call outside of that function, to avoid infinite recursion. Otherwise the function is going to call itself every 100ms, and each call will then call itself again every 100ms, and that's going to multiply until the program crashes.

Random Davis
  • 6,662
  • 4
  • 14
  • 24
  • This isn't quite accurate. The problem is that the code calls `move_balls()` immediately, _before_ passing it to `ontimer`. This causes another call to `move_balls()` which causes another call to `move_balls()` etc, without ever being called by the timer. – Bryan Oakley Aug 30 '22 at 00:32