1

So I have been reading files lately and a challenge was to read a file and then screen.blit all of the text in pygame.

import pygame
import sys
pygame.init()

screenSizeX = 1080
screenSizeY = 720
screenSize = (screenSizeX,screenSizeY)

screen = pygame.display.set_mode(screenSize,0)
pygame.display.set_caption("Display Text")

WHITE = (255,255,255)
GREEN = (0,255,0)
BLUE = (0,0,255)
RED = (255,0,0)
YELLOW = (255,255,0)
BLACK = (0,0,0)
x = 100
y = 100


file = input("Enter the name of the file you want to display(no quotes) ")
file = str(file)

inputedFile = open(file, "r")

def textOutput(line):
    fontTitle = pygame.font.SysFont("Arial", 72)
    textTitle = fontTitle.render(line, True, GREEN)
    screen.blit(textTitle, (x,y))

pygame.display.update()
for line in inputedFile:
    text = line

go = True
while go:
    for event in pygame.event.get():
        if event.type ==pygame.QUIT:
            go = False
        screen.fill(WHITE)
        fontTitle = pygame.font.SysFont("Arial", 72)
        textTitle = fontTitle.render(text, True, GREEN)
        screen.blit(textTitle, (x,y))

        pygame.display.update()

inputedFile.close()

pygame.quit()
sys.exit()

So this kind of works. It will display the last line of the file you input for it to read. So I was wondering if there was a way to make it display every single line from a text file. It also display a rectangle after the line, which I think has something to do with a \n at the end of the line of text.

Fifer
  • 51
  • 1
  • 6
  • This is a good question. Normally pygame code would create a font, then use the font to create a bitmap, then paint that bitmap to screen. But it's not possible to use `~font.render()` with a multi-line string, it only handles single lines, and thus there's no justification either. – Kingsley Nov 18 '18 at 23:04
  • how could i take each line and turn it into an individual string? If I did that I would be able to blit each line individually right? – Fifer Nov 18 '18 at 23:22

2 Answers2

1

In this loop

for line in inputedFile:
    text = line

you actually overwrite text all the times with the last line. You would actually want to append the new lines. Like this:

text = []
for line in inputedFile:
    text.append(line)
text = '\n'.join(text)

You can also try to use the read function, as described here.

zsomko
  • 581
  • 2
  • 6
  • When I tried what you suggested it did allow me to have all lines on the screen, but there are still little boxes after each line. Is there a way I can have the text on different lines when you screen.blit it? – Fifer Nov 18 '18 at 22:35
  • I would suggest that you read [this](https://stackoverflow.com/questions/42014195/rendering-text-with-multiple-lines-in-pygame?rq=1) for more advanced text output, like nicely printing multiple lines. – zsomko Nov 18 '18 at 22:43
1

It's not too hard to to work through the lines of text, justifying each one. The multilineRender() function presented below does this. It first generates bitmaps of each line, and determines the maximum line-width. Once this width is known it becomes easy to left/right/centre justify by adjusting the x-coordinate.

Each of the bitmaps is then blitted to the pygame screen in turn. Obviously the y-coordinate is increased by the height of each bitmap as we go.

import sys
import pygame
from pygame.locals import *

mline_text="The Scroobious Pip went out one day\nWhen the grass was green, and the sky was grey.\nThen all the beasts in the world came round\nWhen the Scroobious Pip sat down on the ground.\n"

WIDTH = 600
HEIGHT= 500
WHITE = 255,255,255
BLUE  = 0,0,200

###
### Draw a multi-line block of text to the screen at (x,y)
### With optional justification
###
def multilineRender(screen, text, x,y, the_font, colour=(128,128,128), justification="left"):
    justification = justification[0].upper()
    text = text.strip().replace('\r','').split('\n')
    max_width = 0
    text_bitmaps = []
    # Convert all the text into bitmaps, calculate the justification width
    for t in text:
        text_bitmap = the_font.render(t, True, colour)
        text_width  = text_bitmap.get_width()
        text_bitmaps.append((text_width, text_bitmap))
        if (max_width < text_width):
            max_width = text_width
    # Paint all the text bitmaps to the screen with justification
    for (width, bitmap) in text_bitmaps:
        xpos = x
        width_diff = max_width - width
        if (justification == 'R'):  # right-justify
            xpos = x + width_diff
        elif (justification == 'C'): # centre-justify
            xpos = x + (width_diff // 2)
        screen.blit(bitmap, (xpos, y) )
        y += bitmap.get_height()

#start pygame, create a font for the text
pygame.init()
screen = pygame.display.set_mode((600,500))
pygame.font.init
myfont = pygame.font.Font(None,14)
screen.fill(BLUE)
# three copies of the same text, different justificaiton
multilineRender(screen, mline_text, 20, 20, myfont, WHITE)
multilineRender(screen, mline_text, 20,100, myfont, WHITE, justification="right")
multilineRender(screen, mline_text, 20,180, myfont, WHITE, justification="centre")
pygame.display.update()

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

pygame screenshot

Kingsley
  • 14,398
  • 5
  • 31
  • 53
  • 1
    Obviously instead of using a constant `mline_text`, a simple `mline_text = open("my_file.txt", "rt").readlines()` would be fine. – Kingsley Nov 18 '18 at 23:46