Search code examples
pythoninputtextpygamecoordinates

Python Pygame Font x coordinate


I am trying to make a 2d password generator in pygame and I have to ask the user and take text input from the user about how many length in numbers he wants his password to be. I know that the text input will be short but what if the user types a big string that the text input passes my screen width so my question is how do I detect if the font passes my screen width so from now on whatever the user inputs will get displayed on a new Line because if the text is not in a newline my user wont be able to see what he is entering now.

Here is my text input function:

def text_input(x, y, color, char=None, char_x=None, char_y=None, char_color=None, fill=(0, 0, 0), thing=None,
               thing_x=None, thing_y=None):
    """

    :param x: Defines the x axis or the width position where the text input should be drawn.
    :param y: Defines the y axis or the height position where the text input should be drawn.
    :param color: Defines the color of the text input.
    :param char: If the parameter char in not entered it does not do anything otherwise it display's the the parameter
                 char's text on the screen
    :param char_x: If the parameter char is entered char_x Defines the x axis or the width position where the text
                   should be drawn.
    :param char_y: If the parameter char is entered char_y Defines the y axis or the height position where the text
                   should be drawn.
    :param char_color: Defines the color of the text of the parameter char in rgb color pixels.
    :param fill: If the parameter fill is entered it fills the display with the tuple of the rgb color pixels which the
                 user entered. But if the parameter fill is not entered it fills the display with the rgb color code
                 black.
    :param thing: If the user wants some thing to been drawn on the display the fill the parameter thing with the object
                  they want to draw. But if the parameter thing is not entered. The thing parameter should be a pygame
                  Surface.
    :param thing_x: If the parameter thing is entered thing_x Defines the x axis or the width position where the
                    parameter thing should be drawn
    :param thing_y: If the parameter thing is entered thing_y Defines the y axis or the height position where the
                    parameter thing should be drawn.
    :return: It Display's the text input and the other parameters which were entered on the window and the updates it.
    """

    characters = ""
    WINDOW.fill(fill)
    if thing is not None:
        draw(thing, thing_x, thing_y)
    if char is not None:
        char_text = str(char)
        char_text_surface = FONT.render(char_text, True, char_color)
        draw(char_text_surface, char_x, char_y, True)
    pygame.display.update()

    while True:
        for detect in pygame.event.get():
            if detect.type == QUIT:
                exit()

            elif detect.type == KEYDOWN:
                if detect.key == K_BACKSPACE:
                    characters = characters[:-1]
                elif detect.key == K_RETURN:
                    global text
                    text = characters
                    return text

                else:
                    characters = characters + detect.unicode

                WINDOW.fill(fill)
                if thing is not None:
                    draw(thing, thing_x, thing_y)
                if char is not None:
                    char_text = str(char)
                    char_text_surface = FONT.render(char_text, True, char_color)
                    draw(char_text_surface, char_x, char_y, True)

                text = FONT.render(f"{characters}", True, color)
                print(char_x)
                draw(text, x, y, True)

If you wonder what the draw function is here is the code for it:

def draw(thing, x, y, update=None):
    """

    :param thing: The object what needs to be drawn on the screen
    :param x: Defines the x axis or the width position where the object should be drawn.
    :param y: Defines the y axis or the height position where the object should be drawn.
    :param update: If the parameter update is not passed we don't update the display.
                   But if the parameter update is passed as True we update the display.
    :return: It returns the object on the display at its specific place or it returns
            the object on the display at its specific place and updates and updates the display based on the parameter
            update.
    """

    if update is True:
        WINDOW.blit(thing, (x, y))
        return pygame.display.update()

    else:
        return WINDOW.blit(thing, (x, y)

If you want to know my full code just ask me I will edit this post:


Solution

  • Use pygame.font.Font.size to determine the amount of space needed to render text:

    text_width, text_height = FONT.size(text)
    

    The line space of the font can be get with get_linesize

    Use this methods to render the text line by line:

    def render_text(font, text, color, x, y, max_length = 100, update=False):
    
        line_y = y
        si = 0
        ei = 1
        while ei < len(text)+1:
            text_width, text_height = font.size(text[si:ei])
            if text_width > max_length:
                text_surf = font.render(text[si:ei-1], True, color)
                WINDOW.blit(text_surf, (x, line_y))
                line_y += font.get_linesize()
                si = ei-1
            ei += 1
        if si < len(text):
            text_width, text_height = font.size(text[si:])
            text_surf = font.render(text[si:], True, color)
            WINDOW.blit(text_surf, (x, line_y))
        
        if update:
            pygame.display.update()
    
    def text_input(x, y, color, char=None, char_x=None, char_y=None, char_color=None, fill=(0, 0, 0), thing=None,
                   thing_x=None, thing_y=None):
        # [...]
    
        while True:
            for detect in pygame.event.get():
                if detect.type == QUIT:
                    exit()
    
                elif detect.type == KEYDOWN:
                    # [...]
    
                    render_text(FONT, characters, color, x, y, 100, True)