Покемон как текстовый дисплей - PullRequest
3 голосов
/ 05 марта 2020

Я пытаюсь отобразить текст в стиле покемонов, где при нажатии клавиши следующая строка текста отображается одна за другой. Однако мой код, похоже, не ждет, когда я нажму клавишу, прежде чем выйти из последовательности, и вся моя функция выхода в последовательность не запускается. Есть ли способ сделать это?

Есть ли способ сделать это при доступе к тексту из списка? РЕДАКТИРОВАТЬ: Извинения, я воссоздал код за пределами моей программы, чтобы показать проблему. Извините, если первый код был немного грязным: /

import pygame

pygame.init()

screen = pygame.display.set_mode((640, 480))
text_bg = pygame.Surface((640, 180))

game_messages = pygame.font.Font("fonts/Connection.otf", 30)

text1 = game_messages.render("Text number 1", False, (255,0,0))
text2 = game_messages.render("text number 2", False, (255,0,0))

text_list = [text1, text2]

running = 1
playing_text = 2
quits = 0
current_state = 1

def draw_text(text):
    screen.blit(text, (40, 360))

while current_state != quits:
    if current_state == running:
        screen.fill((255,255,255))
        pygame.display.flip()
        print("update")

    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                current_state = playing_text
                screen.blit(text_bg, (0,300))

                for text in text_list:  # iterates over the list with all the messages
                        if event.type == pygame.KEYDOWN:
                            if event.key == pygame.K_ESCAPE:
                                quit()
                            elif event.key == pygame.K_SPACE:
                                draw_text(text)
                                pygame.time.delay(50)

                                screen.blit(text_bg, (0, 300))
                                pygame.display.flip()

                                for t in range(len(text_list)):
                                    screen.blit(text_bg, (0, 300))
                                    draw_text(text)

                                    pygame.display.flip()

                                    pygame.event.clear(pygame.KEYDOWN)

                            if event.type == pygame.KEYDOWN:
                                print("exit")
                                if event.key == pygame.K_SPACE:
                                    current_state = 1

                pygame.display.flip()

1 Ответ

2 голосов
/ 05 марта 2020

Это интересный вопрос, в этом есть много сложностей - как насчет размера шрифта, переноса слов, разборчивости и т. Д. c. et c.?

Я думал об этом некоторое время, и я не мог придумать хороший способ включить это в основной l oop без всяких различий кода обработки состояния повсюду. Поэтому, несмотря на мое несогласие с несколькими циклами событий, вот пример, который реализует то, что вы предлагаете аналогичным образом. Функция playMessage() имеет свое собственное событие l oop, которое обрабатывает достаточно для прохождения сообщения через пробел, но также отправляет важные события (например, Quit) обратно на главный l oop для обработки.

В любом случае Ключевым моментом при обработке текста таким способом является подсчет количества нажатий клавиш, пробел в этом случае, и отображение только новой строки при каждом нажатии. (Также выходите после последней строки при нажатии.)

Каждая строка текста при визуализации в изображение с помощью pygame.font.render() будет иметь свою собственную высоту, которую необходимо суммировать по мере продвижения чертежа вниз по экран. Таким образом, в действительности в коде есть два «курсора»: позиция в списке строк текста и позиция пикселя Y на дисплее.

Поскольку код блокирует событие главного окна l oop он захватывает копию исходного содержимого экрана и использует его для перекраски фона. Этот фон затемняется и сглаживается, чтобы сделать текст более разборчивым (несмотря на мой выбор шрифта).

import pygame

# Window size
WINDOW_WIDTH    = 700
WINDOW_HEIGHT   = 300
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE

DARK_BLUE = (   3,   5,  54 )
WHITE_ISH = ( 230, 230, 197 )

def playMessage( window, font, message, start_point=( 20, 20 ) ):
    line_separation = 3   # pixels between lines
    line_cursor     = 0

    # Make a blurred copy of the background for updating, by shrinking then
    # expanding the current content of the window, oh and darken it too
    # for better constrast
    skrinked   = pygame.transform.smoothscale( window, ( window.get_width()//4, window.get_height()//4 ) )
    dark       = pygame.Surface( ( skrinked.get_width(), skrinked.get_height() ), flags=pygame.SRCALPHA )
    dark.fill( ( 100, 100, 100, 0 ) )
    skrinked.blit( dark, (0,0), special_flags=pygame.BLEND_RGBA_SUB )
    background = pygame.transform.smoothscale( skrinked, ( window.get_width(), window.get_height() ) )

    # cleanup messages, remove blank lines, et.al
    message_lines = []
    for line in message.split( '\n' ):
        line = line.strip()
        if ( len( line ) > 0 ):
            message_lines.append( line )

    # Make every text line into a bitmap 
    for i,line in enumerate( message_lines ):
        message_lines[i] = font.render( line, True, WHITE_ISH )

    # Start the render
    clock = pygame.time.Clock()
    done = False
    while not done:

        window.blit( background, ( 0,0 ) )
        x_pos, y_pos = start_point
        for i in range( 0, line_cursor ):
            text_rect = message_lines[i].get_rect()
            text_rect.x = x_pos
            text_rect.y = y_pos
            window.blit( message_lines[i], text_rect )
            # offset next line
            y_pos += text_rect.height + line_separation
        pygame.display.flip()

        # Handle user-input
        for event in pygame.event.get():
            if ( event.type == pygame.QUIT ):
                pygame.event.post( pygame.event.Event( pygame.QUIT ) )      # re-post this to handle in the main loop
                done = True
            elif ( event.type == pygame.KEYDOWN ):
                if ( event.key == pygame.K_ESCAPE ):
                    done = True
                elif ( event.key == pygame.K_SPACE ):
                    line_cursor += 1
                    if ( line_cursor > len( message_lines ) ):
                        done = True   # space at end to dismiss

        clock.tick_busy_loop( 16 )   # don't need big FPS for read




### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("text player")

### Message Text For Displaying
poke_font = pygame.font.Font( 'Pokemon Solid.ttf', 24  )    # ref: https://fontmeme.com/fonts/pokmon-font/
message   = "You were eated all up by a Wild Wampus!\nAnd you never found the Key in the Dark Forest!\nRedo From Start."

### Background image
grassy_background = pygame.image.load( "grassy.jpg" )  # ref: http://www.plaintextures.com/
grassy_background = pygame.transform.smoothscale( grassy_background, ( WINDOW_WIDTH, WINDOW_HEIGHT ) )

### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            # On mouse-click
            playMessage( window, poke_font, message )

    # Movement keys
    #keys = pygame.key.get_pressed()
    #if ( keys[pygame.K_UP] ):
    #    print("up")

    # Update the window, but not more than 60fps
    window.blit( grassy_background, ( 0, 0 ) )
    pygame.display.flip()

    # Clamp FPS
    clock.tick_busy_loop(60)


pygame.quit()

demo animation

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...