Is there a more accurate clock for pygame for a rhythm game I'm making

Viewed 55

I'm trying to get a series of lines to fall through the screen at exact tempo, for example, you input say 120 BPM and the result is the road lines hitting the bottom of the screen at 120 BPM.

I have tried using both pygame.clock.tick() and pygame.time.delay() (which I heard is more accurate), however when I use these as a clock to blit both the background and the road lines, against a metronome the clock seems very inconsistent.

For making an exact rhythm game which must stay in time for the entire song, is there another way to do this?

#GAMELOOP
while playing==True:
    
    win.blit(bg,(0,0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            playing = False
    #win.fill(WHITE)

    y1=y1+gameSpeed
    y2=y2+gameSpeed
    y3=y3+gameSpeed
    win.blit(track1,(x,y1))
    win.blit(track2,(x,y2))
    win.blit(track3,(x,y3))
    if y1>=1000:
        y1=-2000
    if y2>=1000:
        y2=-2000
    if y3>=1000:
        y3=-2000
    

    fpsClock.tick(30)
    pygame.display.update()
    
pygame.quit()
1 Answers

120 BPM (which I assume is "Beats Per Minute"), is only a per half-second timing, that's reasonably slow in computer terms. Most applications repaint the screen at 3600 frame-updates per minute (60Hz).

You can use the pygame.time object to return the number of milliseconds since the program started. This is really useful for timing things in the game:

clock = pygame.time.get_ticks()   # time now

So immediately on start-up, this time is "0 milliseconds", and grows from there, forever more.

This value can then be used in relative time comparisons. When you make the track1 fall, it's possible to update the y-position based on the clock. One way to do this is to calculate the future millisecond-time at which the track1 should next move:

clock = pygame.time.get_ticks() 
track1_move_next_time =  clock + 500    # 500 milliseconds = 120 BPM

The repeatedly check that time until it's in the past. Then move the track1:

# In the Main Loop:

clock = pygame.time.get_ticks() 

# ...

if ( clock > track1_move_next_time ):      # is it time to move?
    y1 += pixels_per_tick                  # move it 
    track1_move_next_time =  clock + 500   # set next move time
Related