【发布时间】:2022-07-28 23:12:55
【问题描述】:
有没有办法可以使用 python 在 pygame 窗口上显示文本?
我需要显示一堆更新的实时信息,而不是为我需要的每个角色制作图像。
我可以将文本 blit 到屏幕吗?
【问题讨论】:
有没有办法可以使用 python 在 pygame 窗口上显示文本?
我需要显示一堆更新的实时信息,而不是为我需要的每个角色制作图像。
我可以将文本 blit 到屏幕吗?
【问题讨论】:
是的。可以在 pygame 中绘制文本:
# initialize font; must be called after 'pygame.init()' to avoid 'Font not Initialized' error
myfont = pygame.font.SysFont("monospace", 15)
# render text
label = myfont.render("Some text!", 1, (255,255,0))
screen.blit(label, (100, 100))
【讨论】:
font.SysFont 的文档,它从系统字体 (pygame.org/docs/ref/font.html#pygame.font.SysFont) 加载字体。
pygame.font.Font("path/to/font.ttf",size)。
您可以通过使用pygame.font.Font设置字体路径来使用您自己的自定义字体
pygame.font.Font(filename, size): return Font
例子:
pygame.font.init()
font_path = "./fonts/newfont.ttf"
font_size = 32
fontObj = pygame.font.Font(font_path, font_size)
然后使用 fontObj.render 渲染字体并 blit 到表面,如上面的 veiset 的回答。 :)
【讨论】:
我的游戏中有一些代码可以显示实时比分。它具有快速访问功能。
def texts(score):
font=pygame.font.Font(None,30)
scoretext=font.render("Score:"+str(score), 1,(255,255,255))
screen.blit(scoretext, (500, 457))
我在我的 while 循环中使用它来调用它:
texts(score)
【讨论】:
有两种可能性。在任何一种情况下,PyGame 都必须由 pygame.init 初始化。
import pygame
pygame.init()
使用 pygame.font 模块并创建一个 pygame.font.SysFont 或 pygame.font.Font 对象。 render()pygame.Surface正文和blit表面到屏幕:
my_font = pygame.font.SysFont(None, 50)
text_surface = myfont.render("Hello world!", True, (255, 0, 0))
screen.blit(text_surface, (10, 10))
或者使用 pygame.freetype 模块。创建一个 pygame.freetype.SysFont() 或 pygame.freetype.Font 对象。 render()pygame.Surface带文字或直接render_to()将文字显示到屏幕上:
my_ft_font = pygame.freetype.SysFont('Times New Roman', 50)
my_ft_font.render_to(screen, (10, 10), "Hello world!", (255, 0, 0))
最小 pygame.font 示例: repl.it/@Rabbid76/PyGame-Text
import pygame
pygame.init()
window = pygame.display.set_mode((500, 150))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
text = font.render('Hello World', True, (255, 0, 0))
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *window.get_size(), (128, 128, 128), (64, 64, 64)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
for rect, color in tiles:
pygame.draw.rect(background, color, rect)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.blit(background, (0, 0))
window.blit(text, text.get_rect(center = window.get_rect().center))
pygame.display.flip()
pygame.quit()
exit()
最小 pygame.freetype 示例: repl.it/@Rabbid76/PyGame-FreeTypeText
import pygame
import pygame.freetype
pygame.init()
window = pygame.display.set_mode((500, 150))
clock = pygame.time.Clock()
ft_font = pygame.freetype.SysFont('Times New Roman', 80)
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *window.get_size(), (128, 128, 128), (64, 64, 64)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
for rect, color in tiles:
pygame.draw.rect(background, color, rect)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.blit(background, (0, 0))
text_rect = ft_font.get_rect('Hello World')
text_rect.center = window.get_rect().center
ft_font.render_to(window, text_rect.topleft, 'Hello World', (255, 0, 0))
pygame.display.flip()
pygame.quit()
exit()
【讨论】:
我写了一个包装器,它将缓存文本表面,只有在变脏时才重新渲染。 googlecode/ninmonkey/nin.text/demo/
【讨论】:
我写了一个 TextBox 类。它可以相对容易地使用许多自定义字体并指定颜色。 我想在屏幕上的几个地方显示文字,其中一些会更新例如生命、分数(所有玩家的)高分、经过的时间等等。
首先,我在项目中创建了一个 fonts 文件夹并加载了我想使用的字体。例如,我的 fots 文件夹中有“arcade.ttf”。在制作 TextBox 的实例时,我可以使用字体位置(可选)arg 指定该字体。
例如
self.game_over_text = TextBox("GAME OVER", 100, 80, 420, RED, 'fonts/arcade.ttf')
我发现制作文本并在每次“笨拙”时更新它,所以我的解决方案是 update_text 方法。
例如,更新玩家得分:
self.score1_text.update_text(f'{self.p1.score}')
它可以重构为接受 str 列表,但它适合我编写“S”版本的需要
# -*- coding: utf-8 -*-
'''
@author: srattigan
@date: 22-Mar-2022
@project: TextBox class example
@description: A generic text box class
to simplify text objects in PyGame
Fonts can be downloaded from
https://www.dafont.com/
and other such sites.
'''
# imports
import pygame
# initialise and globals
WHITE = (255, 255, 255)
pygame.font.init() # you have to call this at the start
class TextBox:
'''
A text box class to simplify creating text in pygame
'''
def __init__(self, text, size, x=50, y=50, color=WHITE, fontlocation=None):
'''
Constuctor
text: str, the text to be displayed
size: int, the font size
x: int, x-position on the screen
y: int, y-position on the screen
color: tuple of int representing color, default is (255,255,255)
fontlocation: str, location of font file. If None, default system font is used.
'''
pygame.font.init()
self.text = text
self.size = size
self.color = color
self.x = x
self.y = y
if fontlocation == None:
self.font = pygame.font.SysFont('Arial', self.size)
else:
self.font = pygame.font.Font(fontlocation, self.size)
def draw(self, screen):
'''
Draws the text box to the screen passed.
screen: a pygame Surface object
'''
text_surface = self.font.render(f'{self.text}', False, self.color)
screen.blit(text_surface, [self.x, self.y])
def update_text(self, new_text):
'''
Modifier- Updates the text variable in the textbox instance
new_text: str, the updated str for the instance.
'''
if not isinstance(new_text, str):
raise TypeError("Invalid type for text object")
self.text = new_text
def set_position(self, x, y):
'''
Modifier- change or set the position of the txt box
x: int, x-position on the screen
y: int, y-position on the screen
'''
self.x = x
self.y = y
def __repr__(self):
rep = f'TextBox instance,
text: {self.text}
FontFamly:{self.font}
Color: {self.color}
Size: {self.size}
Pos: {self.x, self.y}'
return rep
if __name__ == "__main__":
test = TextBox("Hello World", 30, 30, 30)
print(test)
在我的游戏类中使用它
from textbox import TextBox
在游戏的初始化部分,是这样的:
self.time_text = TextBox("Time Left: 100", 20, 20, 40)
self.cred_text = TextBox("created by Sean R.", 15, 600, 870)
self.score1_text = TextBox("0", 100, 40, 650)
self.score2_text = TextBox("0", 100, 660, 650)
self.lives1_text = TextBox("[P1] Lives: 3", 20, 40, 750)
self.lives2_text = TextBox("[P2] Lives: 3", 20, 660, 750)
self.game_over_text = TextBox("GAME OVER", 100, 80, 420, RED)
self.textbox_list = []
self.textbox_list.append(self.time_text)
self.textbox_list.append(self.cred_text)
self.textbox_list.append(self.score1_text)
self.textbox_list.append(self.score2_text)
self.textbox_list.append(self.lives1_text)
self.textbox_list.append(self.lives2_text)
这样当我想在屏幕上绘制所有内容时:
for txt in self.textbox_list:
txt.draw(screen)
在游戏的更新部分,我只使用 update_text 方法直接更新已更新文本的框 - 如果没有要更新的内容,文本将保持不变。
【讨论】:
我写了一个TextElement 类来处理文本放置。它仍有改进的余地。要改进的一件事是使用 SysFont 添加后备字体,以防字体资源不可用。
import os
from typing import Tuple, Union
from pygame.font import Font
from utils.color import Color
class TextElement:
TEXT_SIZE = 50
def __init__(self, surface, size=TEXT_SIZE, color=Color('white'), font_name='Kanit-Medium') -> None:
self.surface = surface
self._font_name = font_name
self._size = size
self.color = color
self.font = self.__initialize_font()
@property
def font_name(self):
return self._font_name
@font_name.setter
def font_name(self, font_name):
self._font_name = font_name
self.font = self.__initialize_font()
@font_name.deleter
def font_name(self):
del self._font_name
@property
def size(self):
return self._size
@size.setter
def size(self, size):
self._size = size
self.font = self.__initialize_font()
@size.deleter
def size(self):
del self._size
def write(self, text: str, coordinates: Union[str, Tuple[int, int]] = 'center'):
rendered_text = self.font.render(text, True, self.color)
if isinstance(coordinates, str):
coordinates = self.__calculate_alignment(rendered_text, coordinates)
self.surface.blit(rendered_text, coordinates)
return self
def __calculate_alignment(self, rendered_text, alignment):
# https://www.pygame.org/docs/ref/surface.html#pygame.Surface.get_rect
# Aligns rendered_text to the surface at the given alignment position
# e.g: rendered_text.get_rect(center=self.surface.get_rect().center)
alignment_coordinates = getattr(self.surface.get_rect(), alignment)
return getattr(rendered_text, 'get_rect')(**{alignment: alignment_coordinates}).topleft
def __initialize_font(self):
return Font(os.path.join(
'assets', 'fonts', f'{self._font_name}.ttf'), self._size)
以下是如何使用它:
TextElement(self.screen, 80).write('Hello World!', 'midtop')
TextElement(self.screen).write('Hello World 2!', (250, 100))
# OR
text = TextElement(self.screen, 80)
text.size = 100
text.write('Bigger text!', (25, 50))
text.write('Bigger text!', 'midbottom')
我希望这可以帮助别人!干杯!
【讨论】: