How To Fix Inconsistent Frame Rate (speed) In Python Turtle
Solution 1:
Your while True:
has no place in an event-driven environment like turtle. The first level replacement would be to put the body of your loop into a function that you invoke with ontimer()
. This will call your routine at fixed intervals (make sure to include the ontimer()
call as the last step as it's a one-shot.) Something like:
def move_balls():
global score_a, score_b
wn.update()
# Moving Ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking
if ball.ycor() > 290 or ball.ycor() < -290:
winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
ball.dy *= -1
if ball.xcor() > 390:
winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
ball.goto(0, 0)
ball.dx *= -1
score_a += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))
elif ball.xcor() < -390:
winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
ball.goto(0, 0)
ball.dx *= -1
score_b += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align='center', font=('Courier', 24, 'bold'))
# Paddle and ball collisions
if (340 < ball.xcor() < 350) and (paddle_b.ycor() - 60 < ball.ycor() < paddle_b.ycor() + 60):
winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
ball.setx(340)
ball.dx *= -1
elif (-350 < ball.xcor() < -340) and (paddle_a.ycor() - 60 < ball.ycor() < paddle_a.ycor() + 60):
winsound.PlaySound('bounce.wav', winsound.SND_ASYNC)
ball.setx(-340)
ball.dx *= -1
wn.ontimer(move_balls, 100)
move_balls()
However, the timer only controls the time between the end of one call to move_balls()
and the start of another. It doesn't account for the time spent in the method itself. If you need more precise control, then something like this high precision frames per second code might be what you're looking for.
Solution 2:
When animating, especially if you want control the speed of animation, you need stick to the principle of model-view separation. This means you have one part of program that controls the state of objects (model), and the other part that draws the objects (view). State of objects may include position, heading, color, and other properties. This part of program that changes objects’ states is not concerned with drawing of the objects. The drawing is done by separate part of program that checks the states of the objects and render them on the screen.
cdlane's answer mixed model and view. Within one single timer function, objects' states are changed and also rendered (which could take lots of CPU time). This will cause delay to the next time this function will be called.
My solution is to make move_balls()
functions change the positions of the balls only (without drawing it), which will return with virtually no delay keeping the time interval consistent. Then you put code for drawing the objects into a timer handler with minimal possible delay. To avoid unnecessary drawing make a should_draw global variable and returns immediately when it is false, without wasting CPU time. After move_balls()
function executes the objects will need drawing. So make sure set should_draw to true before returning from move_balls()
. Also, after finished drawing is done, make sure set should_draw
to False
. (this part edited after discussion with cdlane)
This should allow you draw a lot of objects with smooth animation. Check out this Youtube video that draws hundreds of fireflies lighting up every (almost precisely) 5'th second. There is also a tutorial in the video description.
https://www.youtube.com/watch?v=K9D-wO4w_k0
Here is tutorial with complete code: https://pythonturtle.academy/tutorial-fireflies/
Post a Comment for "How To Fix Inconsistent Frame Rate (speed) In Python Turtle"