How to display text from a pickled .txt file in a

2019-07-30 15:25发布

问题:

I have built a game that logs and saves the users score, using pickle, to a text file. When their lives are used up, they enter their name and their name and score are saved to a text file. Currently, if the "High Scores" section is selected on the main menu the high scores are simply printed in the python shell (or CMD if they're using that). I would like to create a separate window for just displaying the high scores. The window would simply display the scores and would refresh every time it is opened.

Currently I have the code to load the pickled file and create a new window. If I enter static text it works fine but when I try to display the text file contents I get the following error:

Traceback (most recent call last): File "C:\LearnArabic\Program\Test1.py", line 22, in textsurface = myfont.render(high_scores, False, (0, 0, 0)) TypeError: text must be a unicode or bytes

Here is my code:

import pygame
from operator import itemgetter
import pickle

pygame.font.init()

high_scores = []

with open("C:\\LearnArabic\\HighScores\\HighScores.txt", 'rb') as f:
    high_scores = pickle.load(f)

#Background color 
background_color = (255,255,255)
(width, height) = (400, 500)

HighScoreScreen = pygame.display.set_mode((width, height))
pygame.display.set_caption('High Scores')
HighScoreScreen.fill(background_color)

#Displaying text on window
myfont = pygame.font.SysFont('Comic Sans MS', 30)
textsurface = myfont.render(high_scores, False, (0, 0, 0))
HighScoreScreen.blit(textsurface,(0,0))

pygame.display.flip()

running = True
while running:
    for event in pygame.event.get():
        if event.type ==pygame.QUIT:
            running = False

Is there a different function from render that would allow me to display the results in a tabular form?

I'm relatively new to programming and am using python 3. Thanks for the help!

回答1:

You could blit the highscores onto another surface and then blit this surf onto the screen. To blit the highscore list, use a for loop and enumerate the list, so that you can multiply the y-offset by i. To toggle the highscore surface, you can just add a variable highscores_visible = False and then do highscores_visible = not highscores_visible, and in the main loop check if highscores_visible: # blit the surf (press 'h' to update and toggle the highscore table in the example below). Of course you need to make sure that the names and highscores fit onto the surface.

import pygame


pygame.font.init()

screen = pygame.display.set_mode((400, 500))
clock = pygame.time.Clock()

high_scores = [
    ('Carrie', 350),
    ('Arthur', 200),
    ('Doug', 100),
    ]

background_color = (255, 255, 255)

highscore_surface = pygame.Surface((300, 400))
highscore_surface.fill((90, 100, 120))

myfont = pygame.font.SysFont('Comic Sans MS', 30)
highscores_visible = False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_h:
                highscores_visible = not highscores_visible
                if highscores_visible:
                    highscore_surface.fill((90, 100, 120))
                    for i, (name, score) in enumerate(high_scores):
                        text = myfont.render('{} {}'.format(name, score), True, (0, 0, 0))
                        highscore_surface.blit(text, (50, 30*i+5))

    screen.fill(background_color)
    if highscores_visible:
        screen.blit(highscore_surface, (50, 50))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Regarding the TypeError, you can't pass a list to myfont.render only a string or byte string, so you have to convert the list, e.g. str(high_scores). However, if you just convert the high_scores list into a string before you pass it, pygame will render the whole list as one line. You need to use a for loop if you want several lines of text.