繁体   English   中英

如何使用 class 缩小 Pygame 中的此代码部分?

[英]How can I use a class to shrink this code section in Pygame?

我正在尝试制作 5 个屏幕来显示有关团队的信息,并且需要在每个屏幕中打印一些文本。 我怎样才能避免所有这些行?

fonte = pygame.font.SysFont('Times New Roman', 20)

nomeEquipe = fonte.render("Nome da Equipe", True, preto)
nomeDavid = fonte.render("David Waters Teixeira Rodrigues", True, preto)
nomeRafael = fonte.render("Rafael Pereira de Souza", True, preto)
nomeVicente = fonte.render("Vicente de Paulo Vidal Alencar", True, preto)
nomeVictor = fonte.render("Victor Jerrysson Gama Bastos", True, preto)
nomeWillian = fonte.render("Willian Alves Batista", True, preto)
funcaoDavid = fonte.render("Função: menu inicial", True, preto)
funcaoRafael = fonte.render("Função: tela da equipe", True, preto)
funcaoVicente = fonte.render("Função: tela sobre", True, preto)
funcaoVictor = fonte.render("Função: jogo", True, preto)
funcaoWillian = fonte.render("Função: jogo", True, preto)

我试图实现这一点:

class Fonte:

    def __init__(self, fonte, tamanho):
        pygame.font.SysFont.__init__(self)
        self.fonte = fonte
        self.tamanho = tamanho

class Tela:

    def __init__(self, texto, antialias, cor):
        Fonte.render.__init__(self)
        self.texto = texto
        self.antialias = antialias
        self.cor = cor

fonte = Fonte('Times New Roman', 20)
nomeEquipe = Tela("Nome da Equipe", True, preto)

但我收到此错误:

Traceback (most recent call last):
File "/home/rafael/teste.py", line 55, in <module>
nomeEquipe = Tela("Nome da Equipe", True, preto)
File "/home/rafael/teste.py", line 45, in __init__
Fonte.render.__init__(self)
AttributeError: type object 'Fonte' has no attribute 'render'

您可以将SysFont的单个实例作为 class 变量:


class Tela:
    fonte = pygame.font.SysFont('Times New Roman', 20)

    def __init__(self, texto, antialias, cor):
        self.surface = Tela.fonte.render(texto, antialias, cor)
        self.texto = texto
        self.antialias = antialias
        self.cor = cor


nomeEquipe = Tela("Nome da Equipe", True, preto)

但是,对于不同的文本,您仍然需要所有这些行。

但是,如果您可以默认最后两个参数:

class Tela:
    fonte = pygame.font.SysFont('Times New Roman', 20)

    def __init__(self, texto, antialias=True, cor=preto):
        self.surface = Tela.fonte.render(texto, antialias, cor)
        self.texto = texto
        self.antialias = antialias
        self.cor = cor

Nomes = ["Nome da Equipe", "David Waters Teixeira Rodrigues", "Rafael Pereira de Souza", "Vicente de Paulo Vidal Alencar", "Victor Jerrysson Gama Bastos", "Willian Alves Batista", "Função: menu inicial", "Função: tela da equipe", "Função: tela sobre", "Função: jogo", "Função: jogo"]

Equipes = [Tela(nome) for nome in Nomes]

我建议使用lambda表达式:

fonte = pygame.font.SysFont('Times New Roman', 20)
fr = lambda t: fonte.render(t, True, preto)

nomeEquipe = fr("Nome da Equipe")
nomeDavid = fr("David Waters Teixeira Rodrigues")
# [...]

但是,我建议将文本Surfaces保存在列表中。 定义字符串列表并使用列表推导创建 Surface 列表:

text_list = [
    "Nome da Equipe", 
    "David Waters Teixeira Rodrigues".
    "Rafael Pereira de Souza"
    # [...]
    ]

fonte = pygame.font.SysFont('Times New Roman', 20)
surf_list = [fonte.render(t, True, preto) for t in text_list]

可以通过订阅访问文本Surfces ( surf_list[0] , surf_list[1], ... )。


如果要使用 class 作为字体,请执行以下操作:

class Fonte:
    def __init__(self, fontname, size, antialias, cor):
        self.font = pygame.font.SysFont(fontname, size)
        self.antialias = antialias
        self.cor = cor
    def render(self, t):
        return self.font.render(t, self.antialias, self.cor)

fonte = Fonte('Times New Roman', 20, True, preto)

nomeEquipe = fonte.render("Nome da Equipe")
nomeDavid = fonte.render("David Waters Teixeira Rodrigues")
# [...]

首先,手头的错误。

render似乎是pygame.font.SysFont class 的一种方法,但您正试图在您的Fonte class 上调用它(类型本身,而不是实例)。 所以 Python 不知道该怎么做并抱怨。 为了让你的 class 做你在编写它时可能想要的意思,你应该继承SysFont (以及它的render定义)或自己定义一个合适的render方法,然后创建一个实例并调用该方法。

除此之外,您的Tela class 尝试在方法上调用__init__ ,这是没有意义的,同时还将该方法传递给Tela的实例。 那条线是一团糟。

下面是一个固定版本,它应该与您的原始代码相同,但使用类,有点本着给您错误的精神。 我不认为这是一个好主意,事实上我认为考虑到可用的上下文是不合适的。

免责声明:我没有用 PyGame 对此进行测试,我只是用玩具类启动解释器来检查super().__init__(...)调用。 这应该与您的“之前”代码具有相同的行为,我假设您对此感到满意并做了一些有用的事情。

class Fonte(pygame.font.SysFont):
    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)


class Tela:
    def __init__(self, texto, antialias, cor):
        self.texto = texto
        self.antialias = antialias
        self.cor = cor

    def render_with_font(self, fonte):
        return fonte.render(self.texto, self.antialias, self.cor)
        

fonte = Fonte('Times New Roman', 20)
nomeEquipe = Tela("Nome da Equipe", True, preto).render_with_font(fonte)
...

现在,用更实际的术语来说,请注意新类并没有减少我们必须编写的东西的数量! 我们本可以像在原始版本中一样首先使用SysFont并节省代码和精力。

到你可能想要做的事情上,即在没有一千个fonte.render(...)行的情况下获得你的“之前”代码的行为。

您的案例看起来很像您想要一些包含相当同质调用结果的变量。 如果您坚持使用单独的变量,无论您如何表达,这都是冗长的,但是如果您接受只有一个变量是某种集合的事实,例如listdict ,则很容易缩小:

# The data must still be declared somewhere, can't reduce this
text_list = [
    'Nome da Equipe',
    'David Waters Teixeira Rodrigues',
    # ...
]
rendered_text_list = []
for text in text_list:
    rendered_text_list.append(fonte.render(text, True, preto))
# nomeEquipe = rendered_text_list[0]
# nomeDavid = rendered_text_list[1]
# and so on, you can use the list instead of variables

最后一个for循环是列表推导的教科书案例,但我发现好的旧循环对于初学者来说更容易理解。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM