Search code examples
textscrollpygamedisplaybottom-up

when adding new text it appears on bottom and rest of text goes up


I want to display text on the text box that says if I hit and how much damage I do and vice versa for the enemy, but I just can't figure out how to make the text to display in this manner.

Here is the code I'm working on:

def textBox(textv):
    lText = []
    text = font.render(str(textv),True,(1,1,1))
    lText.append(text)
    if len(lText) >= 10:
        lText.pop(9)
    screen.blit(lText[0],(20,400))
    screen.blit(lText[1],(20,380))

while True:

    battle_screen()
    for event in pygame.event.get():

        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    screen.blit(enemy_background,(20,20))
    player.drawPlayer()
    enemy.newEnemy()
    textBox("Daniel")
    textBox("Jenny")
    
    
    pygame.display.update()


Solution

  • Rendere the text an add the rendered text into a list:

    text_surf_list = []
    text_surf = font.render("Daniel", True, (255, 255, 0))
    text_surf_list.append(text_surf)
    text_surf = font.render("Jenny", True, (255, 255, 0))
    text_surf_list.append(text_surf)
    

    Define a rectangular area for the text box:

    text_box_rect = pygame.Rect(20, 20, 250, 360)
    

    Iterate through list in reversed order. Draw the text from the bottom up. Remove the text from the list if it is not in the box (see How to remove items from a list while iterating?):

    text_y = box_rect.bottom - font.get_height()
    for text_surf in reversed(text_surf_list[:]):
        if text_y <= box_rect.top: 
            text_surf_list.remove(text_surf)
        else:
            surf.blit(text_surf, (box_rect.left + 10, text_y))
        text_y -= font.get_height()
    

    Set a temporary clipping area while drawing the text box withpygame.Surface.set_clip:

    # set clipping
    surf.set_clip(box_rect)
    
    # draw text box
    # [...]
    
    # disable clipping
    surf.set_clip(None)
    

    Minimal example:

    import pygame, random
    
    pygame.init()
    window = pygame.display.set_mode((400, 400))
    clock = pygame.time.Clock()
    
    def draw_scroll_text_box(surf, font, box_rect, text_surf_list):
        surf.set_clip(box_rect)
        text_y = box_rect.bottom - font.get_height() - 10
        for text_surf in reversed(text_surf_list[:]):
            if text_y <= box_rect.top: 
                text_surf_list.remove(text_surf)
            else:
                surf.blit(text_surf, (box_rect.left + 10, text_y))
            text_y -= font.get_height()
        pygame.draw.rect(surf, (164, 164, 164), box_rect, 5)
        surf.set_clip(None)
    
    font = pygame.font.SysFont(None, 50)
    text_box_rect = pygame.Rect(20, 20, 250, 360)
    text_surf_list = []
    timer_event = pygame.USEREVENT+1
    pygame.time.set_timer(timer_event, 200)
    
    background = pygame.Surface(window.get_size())
    ts, w, h, c1, c2 = 50, *background.get_size(), (32, 32, 32), (64, 64, 64)
    tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
    [pygame.draw.rect(background, color, rect) for rect, color in tiles]
    
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False 
            if event.type == timer_event:
                names = ["Daniel", "Jenny", "Patrick", "Sandy", "Bob"]
                text_surf = font.render(random.choice(names), True, (255, 255, 0))
                text_surf_list.append(text_surf)
    
        window.blit(background, (0, 0))
        draw_scroll_text_box(window, font, text_box_rect, text_surf_list)
        pygame.display.flip()
        clock.tick(60)
    
    pygame.quit()
    exit()