简体   繁体   中英

How to add parameters to Python Turtle screen.onTimer function

This seems like it should be simple but I'm new to python. I'm learning how to use Turtle so I decided to create pong. All the tutorials I found have you using screen.onkeypress but this creates a lag in movement which I couldn't find a fix for, so I instead set the movement direction inside of the onkeypress, and then have a recursive function that runs every 10 milliseconds like this:

def movePaddleB():
if (paddleBDirection != 0):
    y = paddleB.ycor()
    y += 1 * paddleBDirection * paddleSpeed
    paddleB.sety(y)
screen.ontimer(movePaddleB, 10)

movePaddleB()

This seems to work really well, but I want to make the function dynamic so that I don't have to create 2 functions, one for paddle A, and one for paddle B (see code below).

def movePaddle(paddle,direction):
if (direction != 0):
    y = paddle.ycor()
    y += 1 * direction * paddleSpeed
    paddle.sety(y)
#ADD DYNAMIC PARAMS TO RECURSIVE FUNCTION CALL
screen.ontimer(movePaddle(paddle,direction), 10)

movePaddle(paddleA,paddleADirection)
movePaddle(paddleB,paddleBDirection)

When I add parameters to the function called in screen.ontimer, I get this error: RecursionError: maximum recursion depth exceeded in comparison. I'm completely lost so any help would be great, even if I have to do this a completely different way.

First of all, your approach to handling the key retrigger is the right idea. Keys should only trigger movement during the game loop/update function, not immediately when the key is pressed.

For handling parameter differences, you can add a lambda wrapper:

def move_paddle(paddle, direction):
    if direction != 0:
        y = paddle.ycor()
        y += 1 * direction * paddle_speed
        paddle.sety(y)

    screen.ontimer(lambda: move_paddle(paddle, direction), 10)

move_paddle(paddle_a, paddle_a_direction)
move_paddle(paddle_b, paddle_b_direction)

Note that this function isn't really recursive because the call stack is cleared by the time the next timer is triggered asynchronously. If it was recursive, CPython would crash after 1k frames or so as you saw when you called it yourself rather than passing a reference to the function for the turtle library to call on your behalf.

Also, function and variable names should be snake_cased per PEP-8 .

That said, this design of having two ontimer s running isn't great. I'd prefer to run one rendering loop for the whole app, then call whichever movement/update functions you want from it:

def move_paddle(paddle, direction):
    if direction != 0:
        y = paddle.ycor()
        y += 1 * direction * paddle_speed
        paddle.sety(y)


def tick():
    move_paddle(paddle_a, paddle_a_direction)
    move_paddle(paddle_b, paddle_b_direction)
    turtle.update() # necessary if you used `tracer(0)`
    screen.ontimer(tick, 1000 // 30)


tick()
turtle.exitonclick()

See How to bind several key presses together in turtle graphics? for complete real-time turtle boilerplate that uses press and release handlers for smooth movement and the same tracer(0) + turtle.update() + screen.ontimer approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM