the ball animation while running the program is very stuttery and i can't figure out why. this is just the beggining of the program so ignore the fact that the game isn't ready to play yet.
this is the code: https://www.codepile.net/pile/dqKZa8OG
i want the ball to move smoothly without stuttering. and in addition how do i make it so the program deletes the last location of the ball after each update?
It's not "junky" because of the timer, you can only see updates since you're probably moving the mouse in the meantime, then you're updating the ball position everytime you move it (which is wrong, as you're updating the position anytime any events is processed).
The problem is that you're using Clock
in the wrong way: the pygame.time.Clock
class creates an «object that can be used to track an amount of time», meaning that it is not a timer that can "react" once it times out. The tick
method you're calling only updates the current Clock returning how many milliseconds have passed since the last call to tick
itself, based on the fps argument you are providing.
What you need is to set a timer, possibly by using a specific eventid just for the updates. Also, since you're updating the ball position based on the events, you'll get more movements if you move the mouse (or any other event is called) making the ball move faster even if it shouldn't - and that's what you'll need the Clock object for.
# I'm using a smaller speed, otherwise it'll be too fast; it should
# depend on the window size to ensure that bigger windows don't get
# slower speeds
ball_velocity = .2
fps = 60
UPDATEEVENT = 24
[...]
def start_move_ball(angle):
ticks = clock.tick()
speed = ball_velocity * ticks
# "global ball" is not required, as you are assigning values to an
# existing object, not declaring it everytime.
# You can also use in-place operations to set the speeds, which is
# better for readability too.
ball[0] += angle[0] * speed
ball[1] += angle[1] * speed
def main_loop():
angle = choose_angle()
pygame.time.set_timer(UPDATEEVENT, 1000 // fps)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return False
# update only if necessary!
elif event.type == UPDATEEVENT:
window.fill((0,0,0))
start_move_ball(angle)
draw_mid(window)
draw_players(window)
draw_ball(window)
pygame.display.flip()
The timer is set outside the while
cycle, as it automatically sends the event each time interval. You could also leave it within the while
(the once=True
argument is not really required in this case, as it automatically updates the timer based on the same eventid), but wouldn't make much sense, since set_timer
always fires the event after the first time it's set.
I'm using 24 (pygame.USEREVENT
) as an eventid, but you can set its id up to pygame.NUMEVENTS - 1
, as suggested in the event documentation. If for any reason you want to stop the timer, just use pygame.time.set_timer(eventid, 0)
and the timer for that eventid (24 in this case) will not be fired up again.
A couple of suggestions, besides all:
pygame.display.update()
line in draw_mid(window)
, since it causes flickering while painting.