【问题标题】:how to change the color a section of text in pygame如何在pygame中更改一段文本的颜色
【发布时间】:2020-11-23 10:19:10
【问题描述】:

我正在使用 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()

【问题讨论】:

    标签: python pygame textcolor text-formatting


    【解决方案1】:

    在字体渲染过程中不能改变单个字母的颜色;您必须逐个字母地呈现您的文本。

    您可以使用render() 将每个字母渲染到它自己的表面并将它们blit 到您的屏幕上,但是您必须手动计算每个字母的位置。

    如果你使用新的freetype 模块会更容易一些,它在Font 类中有很多方便的函数,如originget_rectget_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 类的center 属性可以轻松使文本居中。

    【讨论】:

      猜你喜欢
      • 2017-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多