如何将文本输出到屏幕,同时还输出 Object 方向按钮 - Pygame

How to output text to a screen, while also outputting Object Orientated buttons - Pygame

#Importing Modules
import pygame
import sys
import random

#All pygame stuff under here
pygame.init()

#Font definitions
backFont = pygame.font.SysFont("monospace",40)
titleFont = pygame.font.SysFont("garamond", 100)
buttonFont = pygame.font.SysFont("garamond", 25)
bigFont = pygame.font.SysFont("garamond",100)

#Colour definitions
BackGray = pygame.Color('gray60')
screenGray = pygame.Color('gray80')
buttonGray1 = pygame.Color('gray40')
buttonGray2 = pygame.Color('gray50')
buttonGray3 = pygame.Color('gray30')
textColour = pygame.Color('navy')

#Screen size set
screen = pygame.display.set_mode((800, 600))

#Class for the buttons set here
class Button:
    def __init__(self, x, y, width, height, colour, surface):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.colour = colour
        self.surface = surface

    def isPressed(self):
        mouse_position = pygame.mouse.get_pos()
        mouse_x = mouse_position[0]
        mouse_y = mouse_position[1]
        if mouse_x > self.x:
            if mouse_x < self.x + self.width:
                if mouse_y > self.y:
                    if mouse_y < self.y + self.height:
                        mouse_click = pygame.mouse.get_pressed()
                        left_click = mouse_click[0]
                        if left_click:
                            self.colour = (0,0,0)
                            return True
        self.colour = (230, 230, 230)
        return False

    def drawButton(self):
        pygame.draw.rect(self.surface, self.colour,  (self.x, self.y, self.width, self.height))
        pygame.display.flip()

def FrontPage():
    #Back screen
    screen.fill(screenGray)

    #The background is defined here
    BinaryPage = []
    for i in range(0,15):
        BinaryString = ""
        for j in range(0,33):
            BinaryString += random.choice(["0","1"])
        BinaryPage.append(BinaryString)

    for i in range(0,15):
        screen.blit(backFont.render(BinaryPage[i], 1, BackGray), (0,i * 40))

    #The title is defined and printed here
    Title1 = titleFont.render("The Six", 10, textColour)
    Title2 = titleFont.render("Cipher", 10, textColour)
    Title3 = titleFont.render("Simulator", 10, textColour)
    screen.blit(Title1, (100, 100))
    screen.blit(Title2, (100, 200))
    screen.blit(Title3, (100, 300))

    #Text for the button
    buttonText = buttonFont.render("Continue", 10, textColour)
    screen.blit(buttonText, (115,405))

    #Where the buttons are defined and drawn
    ButtonBig = Button(100, 450, 120, 60, buttonGray1, screen)
    ButtonSmall = Button(105, 455, 110, 50, buttonGray2, screen)
    ButtonBig.drawButton()
    ButtonSmall.drawButton()


    #Pygame While loop
    clock = pygame.time.Clock()
    while True:
        for event in pygame.event.get():
            if ButtonBig.isPressed():
                print("Hello")
                break
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        clock.tick(60)

上面的代码运行一个 window,它以随机顺序排列 0 和 1 作为背景,中间是我的程序的标题。

然后,底部应该有一个按钮,或者一个灰色的矩形。但是,当我尝试将某些内容 .blit 或打印到按钮框架上时,在我将按钮绘制到屏幕上之后,它并没有出现。

谁能告诉我为什么以及如何解决它? 或者关于如何将文本输出到按钮的任何替代方法。

提前致谢

我首先创建一个单独的 background 表面,然后将所有永远不会改变的背景图形 blit 到它上面(下例中的数字)。在主循环中,你可以只 blit 这个背景来清除屏幕。

将文本 blit 到按钮上:

  1. 将文本传递给 __init__ 方法
  2. 创建按钮图像(pygame.Surface)
  3. 渲染文本
  4. 为图像和文本创建矩形(将图像矩形的中心传递给文本矩形以使文本居中)
  5. 将文本表面 blit 到图像上。

对于按钮,我会使用 sprites and put them into a sprite group, so that you can draw them simply by calling sprite_group.draw(screen). Sprites need an image and a rect 属性来工作。 Pygame rects 有碰撞检测方法,你应该使用而不是自己写。在这种情况下,我们可以使用 collidepoint 方法并将 event.pos 传递给它。

import random
import pygame as pg


pg.init()

screen = pg.display.set_mode((800, 600))

FONT = pg.font.SysFont('garamond', 25)
SCREEN_GRAY = pg.Color('gray80')
BUTTON_GRAY = pg.Color('gray40')
TEXT_COLOUR = pg.Color('navy')


# Inherit from pg.sprite.Sprite. That will allow you to
# put the instances into a sprite group.
class Button(pg.sprite.Sprite):

    def __init__(self, text, x, y, width, height, colour):
        super().__init__()
        # Create the image of the button.
        self.image = pg.Surface((width, height))
        self.image.fill(colour)
        # A pygame.Rect will serve as the blit position.
        self.rect = self.image.get_rect()
        # Render the text.
        txt = FONT.render(text, True, TEXT_COLOUR)
        # This txt_rect is used to center the text on the image.
        txt_rect = txt.get_rect(center=self.rect.center)
        self.image.blit(txt, txt_rect)
        # Set the position of the image rect.
        self.rect.topleft = x, y

    def is_pressed(self, event):
        if event.type == pg.MOUSEBUTTONDOWN:
            # MOUSE... events have an event.pos attribute (the mouse position)
            # which you can pass to the collidepoint method of the rect.
            if self.rect.collidepoint(event.pos):
                return True
        return False


def main():
    button_big = Button('big button', 100, 250, 120, 60, BUTTON_GRAY)
    button_small = Button('small button', 105, 455, 120, 50, BUTTON_GRAY)
    buttons_group = pg.sprite.Group(button_big, button_small)

    background = pg.Surface(screen.get_size())
    background.fill(SCREEN_GRAY)

    for i in range(screen.get_height()//40):
        for j in range(screen.get_width()//40):
            n = random.choice(['0', '1'])
            background.blit(FONT.render(n, True, BUTTON_GRAY), (j*40, i*40))

    clock = pg.time.Clock()
    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                return
            if button_big.is_pressed(event):
                print('big')
            elif button_small.is_pressed(event):
                print('small')

        screen.blit(background, (0, 0))
        # Blit the images of the contained sprites onto the screen.
        buttons_group.draw(screen)

        pg.display.flip()
        clock.tick(60)


if __name__ == '__main__':
    main()
    pg.quit()