python - 类似口袋妖怪的文字显示
问题描述
我正在尝试制作一个口袋妖怪风格的文本显示,当您单击一个键时,下一行文本会逐一显示。但是,我的代码似乎没有等我在退出序列之前按下键,并且我对序列的整个退出函数都没有运行。有没有办法做到这一点?
在访问列表中的文本时,是否还有一种方法可以做到这一点?编辑:抱歉,我已经在我的程序之外重新创建了代码以显示问题。抱歉,如果第一个代码有点乱:/
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()
解决方案
这是一个有趣的问题,这类事情有很多复杂性——字体大小、自动换行、易读性等怎么样?
我想了一会儿,如果没有各种状态处理代码,我想不出一个很好的方法将它合并到主循环中。因此,尽管我反对多个事件循环,但这里有一个示例,它以类似的方式实现您的建议。该playMessage()
函数有自己的事件循环,处理足够的空间通过消息,但也将重要事件(如退出)发送回主循环进行处理。
无论如何,以这种方式处理文本的关键点是计算按键的次数,space在这种情况下,每次按下时只显示一个新行。(也可以在按下最后一行后退出。)
每一行文本,当通过渲染成图像时pygame.font.render()
都会有自己的高度,随着绘图在屏幕上的进行,需要对其进行总结。所以实际上代码有两个“光标”:文本行列表中的位置,以及显示器上的 Y 像素位置。
由于代码阻塞了主窗口事件循环,它会抓取原始屏幕内容的副本并使用它来重新绘制背景。这个背景被变暗和平滑以使文本更清晰(尽管我选择了字体)。
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()
推荐阅读
- c# - 从字典中的一系列列表中删除值的最有效方法?
- go - 仅当我使用移动数据通过电话连接时出现 TLS 握手错误
- html - 使用materialize css创建一次弹出窗口
- php - 在php中从json获取数据
- python - Windows 上的 Python 可执行权限
- matlab - 将图形转换为 2D 图表
- django - Django - 导入导出 - 上传多个文件
- c# - 当 Window 具有带有 TabItem 的 TabControl 时的 C# WPF 内存泄漏(或延迟内存回收?)
- wordpress - 从 WooCommerce 中的 URL 中删除 /product-category/ 和 /shop/
- sql - 存储过程和数据导出自动化