Search code examples
pythontextprintingpygame

Why does Pygame text print doesn't fully cover the last text print, and leaves weird aura around the text?


I have 2 functions that are part from a program I have where I print a number of balls that is constantly changing, so I print it, but every time before I print it (calling set_text() and then printing), I call the set_text2() function so that the previous text will disappear, however that doesn't work and it leaves a weird aura around the number.

These are the 2 functions in Python:

def set_text(string, coord_x, coord_y, font_size):
    """
    This is a function to set the text of the amount of balls (white)
    :param string: The text to display (in this case the amount of current balls)
    :type string: string
    :param coord_x: The x coordinate of the text
    :type coord_x: int
    :param coord_y: The y coordinate of the text
    :type coord_y: int
    :param font_size: The size of the text
    :type font_size: int
    :return: The text
    :rtype: tuple
    """

    font = pygame.font.Font('freesansbold.ttf', font_size)
    # (255, 255, 255) is black, to make black text
    text = font.render(string, True, (255, 255, 255))
    text_rect = text.get_rect()
    text_rect.center = (coord_x, coord_y)
    return text, text_rect


def set_text2(string, coord_x, coord_y, font_size):
    """
    This is a function to set the text of the amount of balls (black)
    :param string: The text to display (in this case the amount of current balls)
    :type string: string
    :param coord_x: The x coordinate of the text
    :type coord_x: int
    :param coord_y: The y coordinate of the text
    :type coord_y: int
    :param font_size: The size of the text
    :type font_size: int
    :return: The text
    :rtype: tuple
    """

    # font_size+2 - trying to make the black text cover the white text
    font = pygame.font.Font('freesansbold.ttf', font_size)
    # (0, 0, 0) is black, to make black text
    text = font.render(string, True, (0, 0, 0))
    text_rect = text.get_rect()
    text_rect.center = (coord_x, coord_y)
    return text, text_rect

How do I fix it?

Also, this is where I actually print the text:

    # Printing to the screen the current amount of balls on the screen
    print_amount = current_amount
    totalText = set_text(str(print_amount), 350, 20, 35)
    screen.blit(totalText[0], totalText[1])

    # If the amount of balls has changed, covering the previous amount (Black text)
    if print_amount != current_amount:
        totalText = set_text2(str(print_amount), 350, 20, 35)
        screen.blit(totalText[0], totalText[1])

Solution

  • The problem is that you are using antialising. This means that some pixels are not actually the color you originally selected, but essentially a smoothing pass was made that also bleeds into surrounding pixels.1 You can check this for yourself by passing False as the second parameter to font.render instead of True. Then the effect should be gone.

    However, it is probably better to use antialiasing, and instead change the method by which you are overdrawing the previous image:

    • I assume you specially don't want to redraw the entire screen. You might want to reconsider that, since it will completely remove the possibility of these artifacts.
    • Use the background parameter of font.render. This will not only overdraw the numbers, but also what is around them, so that might not be an option.

    1 I am not entirely sure why the antialising is not applied to the black pixels in the same way. I assume this is caused by the transparent background also having color value (0, 0, 0) See below


    After a bit more fiddling and investigation, I figured it out: AA pixels have an alpha value set, to allow for blending with the background. However, applying an alpha for black and for white have different results: While blending with white makes the pixel visible for sure, blending with black does not make fully black. I don't think there is really a way around this unless someone knows a way to make any non zero alpha behave like 255 Alpha.