Search code examples
pythonpygame

Pygame "pop up" text - How to show an image only for a period of time?


Im learning pygame at the moment and was wondering, how can i make a "pop up" text that say "+1 coin" (or basiclly anything) on the screen for a few seconds, without having to use pygame.time.delay() or time.sleep() since those stop the game, but i want the player to be able to keep playing, while the text is displaying on the screen.


Solution

  • If you want to control something over time in Pygame you have two options:

    1. Use pygame.time.get_ticks() to measure time and implement logic that controls the visibility of the text depending on the time. pygame.time.get_ticks() returns the number of milliseconds since pygame.init(). Get the current time the text pops up and calculate the time the text must disappear:

      draw_text = true
      hide_text_time = pygame.time.get_ticks() + 1000 # 1 second
      
      if draw_text and pygame.time.get_ticks() > hide_text_time:
          draw_text = false 
      
    2. Use the timer event. Use pygame.time.set_timer() to repeatedly create a USEREVENT in the event queue. The time has to be set in milliseconds. Start a timer event when the text pops up and hide the text when the event occurs:

      draw_text = true
      hide_text_event = pygame.USEREVENT + 1
      pygame.time.set_timer(hide_text_event, 1000, 1) # 1 second, one time
      
      # applicaition loop
      while True:
      
          # event loop
          for event in pygame.event.get():
              if event.type == hide_text_event:
                  draw_text = False
      

    For some complete examples, see the answers to the questions:


    Minimal example (the pop up time can be controlled with the variable pop_up_seconds):

    PYGBAG demo

    import pygame
    
    pygame.init()
    window = pygame.display.set_mode((400, 200))
    font = pygame.font.SysFont(None, 40)
    clock = pygame.time.Clock()
    
    text = font.render("+1", True, (0, 255, 0))
    text_pos_and_time = []
    pop_up_seconds = 1
    
    player = pygame.Rect(0, 80, 40, 40)
    coins = [pygame.Rect(i*100+100, 80, 40, 40) for i in range(3)]
    
    run = True
    while run:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        keys = pygame.key.get_pressed()
        player.x = (player.x + (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 3) % 300    
    
        current_time = pygame.time.get_ticks()
        for coin in coins[:]:
            if player.colliderect(coin):
                text_pos_and_time.append((coin.center, current_time + pop_up_seconds * 1000))
                coins.remove(coin)
    
        window.fill(0)    
        pygame.draw.rect(window, "red", player)
        for coin in coins:
            pygame.draw.circle(window, "yellow", coin.center, 20)
        for pos_time in text_pos_and_time[:]:
            if pos_time[1] > current_time:
                window.blit(text, text.get_rect(center = pos_time[0]))
            else:
                text_pos_and_time.remove(pos_time)    
        pygame.display.flip()
    
    pygame.quit()
    exit()