我正在使用 pygame 创建一个游戏,当您键入该字母时,该字母的颜色会发生变化。像nitrotype.com。但是问题是我不知道如何更改单个字母的颜色。
我无法清除屏幕然后执行此操作,因为那样会改变整行的颜色。
因此,要么我需要一种方法来更改单个字母的颜色,要么需要一种方法一次只在屏幕上放置一个字母。但是我不知道如何统一放置字母(使得结尾句居中)。请有人可以在这里帮助我。要么告诉我如何改变单个字母的颜色,要么告诉我如何以完美的方式放置单个字母然后改变它们的颜色。
import pygame as pg
import pygame
pg.init()
screenHeight, screenWidth = 600, 800
gameDisplay = pg.display.set_mode((screenWidth, screenHeight))
pg.display.set_caption("Nitrotype")
black = (255, 255, 255)
white = (0, 0, 0)
gameDisplay.fill(white)
pg.display.update()
gameOn = True
with open("text.txt", "r") as f:
contents = f.read()
def msgToScreen(msg, color, size):
cur = []
strings = []
words = msg.split(" ")
for i in words:
cur.append(i)
if len(" ".join(cur)) >= 35:
strings.append(" ".join(cur))
cur = []
if cur != []:strings.append(" ".join(cur))
curY = 20
for string in strings:
font = pg.font.SysFont(None, size)
text = font.render(string, True, color)
text_rect = text.get_rect(center=(screenWidth/2, curY))
gameDisplay.blit(text, text_rect)
curY += 40
return text
textOnScreen = msgToScreen(contents, black, 50)
pg.display.update()
curIdx = 0
keyCombination = {"a":pg.K_a, "b":pg.K_b, "c":pg.K_c, "d":pg.K_d, "e":pg.K_e, "f":pg.K_f,
"g":pg.K_g, "h":pg.K_h, "i":pg.K_i, "j":pg.K_j, "k":pg.K_k, "l":pg.K_l,
"m":pg.K_m, "n":pg.K_n, "o":pg.K_o, "p":pg.K_p, "q":pg.K_q, "r":pg.K_r,
"s":pg.K_s, "t":pg.K_t, "u":pg.K_u, "v":pg.K_v, "w":pg.K_w, "x":pg.K_x,
"y":pg.K_y, "z":pg.K_z}
while gameOn:
for event in pygame.event.get():
if event.type == pg.QUIT:
gameOn = False
if event.type == pg.KEYDOWN:
if event.key == keyCombination[contents[curIdx].lower()]:
#Here is where the color of the current letter should change
curIdx += 1
pg.quit()
最佳答案
在字体渲染过程中不能改变单个字母的颜色;您必须逐个字母地呈现您的文本。
您可以使用 render()
将每个字母渲染到自己的表面并将它们blit到您的屏幕上,但是您必须手动计算每个字母应该去哪里。
如果你使用新的 freetype
会更容易一些。模块,在 Font
中有很多方便的功能类如 origin
, get_rect
和 get_metrics
它可以计算每个字母有多大。
这是我一起破解的一个简单示例。它并不完美,但你会明白的。
import pygame
import pygame.freetype
from itertools import cycle
def main():
pygame.init()
screen = pygame.display.set_mode((800, 600))
# just some demo data for you to type
data = cycle(['This is an example.', 'This is another, longer sentence.'])
current = next(data)
current_idx = 0 # points to the current letter, as you have already guessed
font = pygame.freetype.Font(None, 50)
# the font in the new freetype module have an origin property.
# if you set this to True, the render functions take the dest position
# to be that of the text origin, as opposed to the top-left corner
# of the bounding box
font.origin = True
font_height = font.get_sized_height()
# we want to know how much space each letter takes during rendering.
# the item at index 4 is the 'horizontal_advance_x'
M_ADV_X = 4
# let's calculate how big the entire line of text is
text_surf_rect = font.get_rect(current)
# in this rect, the y property is the baseline
# we use since we use the origin mode
baseline = text_surf_rect.y
# now let's create a surface to render the text on
# and center it on the screen
text_surf = pygame.Surface(text_surf_rect.size)
text_surf_rect.center = screen.get_rect().center
# calculate the width (and other stuff) for each letter of the text
metrics = font.get_metrics(current)
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.KEYDOWN:
if e.unicode == current[current_idx].lower():
# if we press the correct letter, move the index
current_idx += 1
if current_idx >= len(current):
# if the sentence is complete, let's prepare the
# next surface
current_idx = 0
current = next(data)
text_surf_rect = font.get_rect(current)
baseline = text_surf_rect.y
text_surf = pygame.Surface(text_surf_rect.size)
text_surf_rect.center = screen.get_rect().center
metrics = font.get_metrics(current)
# clear everything
screen.fill('white')
text_surf.fill('white')
x = 0
# render each letter of the current sentence one by one
for (idx, (letter, metric)) in enumerate(zip(current, metrics)):
# select the right color
if idx == current_idx:
color = 'lightblue'
elif idx < current_idx:
color = 'lightgrey'
else:
color = 'black'
# render the single letter
font.render_to(text_surf, (x, baseline), letter, color)
# and move the start position
x += metric[M_ADV_X]
screen.blit(text_surf, text_surf_rect)
pygame.display.flip()
if __name__ == '__main__':
main()
使用第二个 Surface
使文本居中很容易并使用 Rect
类(class)' center
属性(property)。关于python - 如何在pygame中更改一段文本的颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64966471/