Onze notas de estudo do Python: interface gráfica do usuário e desenvolvimento de pequenos jogos

1. GUI baseada no módulo tkinter

  • GUI é a abreviatura de Graphical User Interface. A interface gráfica do usuário não deve ser desconhecida para as pessoas que já usaram computadores, e não há necessidade de entrar em detalhes aqui.
  • O módulo de desenvolvimento de GUI padrão do Python é tkinter (chamado Tkinter na versão anterior do Python 3). A partir desse nome, pode-se ver que é baseado no Tk
    • Tk é um kit de ferramentas, originalmente projetado para Tcl e posteriormente portado para muitas outras linguagens de script, ele fornece controles de interface de usuário de plataforma cruzada;
    • Claro, Tk não é a escolha mais recente e melhor, e não há controles GUI particularmente poderosos.
  • Na verdade, desenvolver aplicativos GUI não é o melhor trabalho do Python. Se você realmente precisa usar Python para desenvolver aplicativos GUI, módulos como wxPython, PyQt, PyGTK, etc. são boas escolhas.

  • Basicamente, usar o tkinter para desenvolver aplicativos GUI requer as 5 etapas a seguir:
    • 1. Importe o que precisamos no módulo tkinter.
    • 2. Crie um objeto de janela de nível superior e use-o para hospedar todo o aplicativo GUI.
    • 3. Adicione componentes GUI ao objeto de janela de nível superior.
    • 4. Organize as funções desses componentes da GUI por meio de código.
    • * 5. Entre no loop de evento principal (loop principal).

Parâmetros comuns do módulo tkinter (python3)

Caso 1: use o tkinter para fazer um aplicativo GUI simples

import tkinter
import tkinter.messagebox


def main():
    flag = True

    # 修改标签上的文字
    def change_label_text():
        nonlocal flag  
        """ 
         此处使用:not flag,不能使用False
         如果使用了False,程序就只能执行一次,之后的flag全部都是False
         使得嵌套变量和nonlocal函数失去了意义
        """
        flag = not flag   
        # msg:提示信息
        color, msg = ('red', 'Hello, world!') \
            if flag else ('blue', 'Goodbye, world!') # flag为真设置红色,flag为假设置蓝色
        label.config(text=msg, fg=color)             #  重新配置

    # 确认退出
    def confirm_to_quit():
        if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'):
            top.quit()

    # 创建顶层窗口
    top = tkinter.Tk()
    # 设置窗口大小,geometry:几何图形
    top.geometry('240x160') 
    # 设置窗口标题
    top.title('小游戏')
    # 创建标签对象并添加到顶层窗口,bg:背景,fg:前景。
    label = tkinter.Label(top, text='Hello, world!', font='Arial -32', fg='red')
    label.pack(expand=1)    # 将标签添加到主窗口
    # 创建一个装按钮的容器
    panel = tkinter.Frame(top)
    # 创建按钮对象 指定添加到哪个容器中 通过command参数绑定事件回调函数
    button1 = tkinter.Button(panel, text='修改', command=change_label_text)  # 修改颜色和文本 
    button1.pack(side='left')
    button2 = tkinter.Button(panel, text='退出', command=confirm_to_quit)
    button2.pack(side='right')
    panel.pack(side='bottom')
    # 开启主事件循环
    tkinter.mainloop()


if __name__ == '__main__':
    main()
     
  • Deve-se notar que os aplicativos GUI são geralmente orientados a eventos. O motivo para entrar no loop de evento principal é monitorar a ocorrência de vários eventos, como o mouse e o teclado, e executar o código correspondente para processar o evento, porque o evento continuará para ocorrer. Portanto, esse loop precisa estar em execução e aguardando a ocorrência do próximo evento.
  • Por outro lado, Tk fornece três gerenciadores de layout para a colocação de controles. Os controles podem ser posicionados através do gerenciador de layout. Os três gerenciadores de layout são: Placer (o desenvolvedor fornece o tamanho e a localização do controle), Packer (preencher automaticamente o controle para a posição apropriada) e Grade (coloque o controle com base nas coordenadas da grade)

2. Use Pygame para desenvolvimento de jogos

  • Pygame é um módulo Python de código aberto especificamente para o desenvolvimento de aplicativos multimídia (como videogames), que inclui suporte para imagens, sons, vídeos, eventos, colisões, etc.
  • Pygame é construído com base em SDL. SDL é uma biblioteca de desenvolvimento multimídia de plataforma cruzada, implementada em linguagem C e é amplamente utilizada no desenvolvimento de jogos, simuladores, jogadores, etc.
  • O Pygame permite que os desenvolvedores de jogos não sejam mais limitados pela linguagem subjacente e possam prestar mais atenção à função e à lógica do jogo.

Consulte o documento do pygame em chinês

1. pygame.init (): inicializa todos os módulos importados do pygame
2. pygame.display.set_mode (): inicializa uma interface pronta para ser exibida
3. pygame.display.set_caption (): define a legenda da janela atual
4. pygame.quit (): desinstala todos os módulos pygame importados
5. screen.fill (): Defina a cor de fundo da janela
6. pygame.draw.circle (): desenhe um círculo
7. pygame.display.flip (): atualiza a janela atual (a janela de renderização apresentará a imagem desenhada)
8. screen.blit (): coloca uma imagem em cima de um objeto (dois parâmetros: imagem: a imagem a ser colocada, posição: as coordenadas da imagem)
注意:
	 1.blit()不会更新屏幕,它在缓冲区中绘制图像;
	 2.需要结合update()/flip()将缓冲区发送到视频卡,才能绘制出图像来。
9. pygame.time.delay (10): Altere a posição da bola a cada 10 milissegundos e atualize a janela

Caso 2: fazer pequenos jogos, bolas grandes e pequenas bolas

O primeiro passo: fazer a janela do jogo

import pygame


def main():
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    running = True
    # 开启一个事件"循环处理"发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False


if __name__ == '__main__':
    main()

Etapa 2: Desenhar na janela

  • Você pode desenhar na janela através da função do módulo de desenho no pygame. Os gráficos que podem ser desenhados incluem: linhas, retângulos, polígonos, círculos, elipses, arcos, etc.
  • O sistema de coordenadas da tela deve definir o canto superior esquerdo da tela para a origem da coordenada (0, 0), à direita é a direção positiva do eixo xe para baixo é a direção positiva do eixo y. expressando a posição ou definindo o tamanho, nossas unidades padrão são todas É um pixel (um pixel é um ponto na tela)
  • As cores no pygame são representadas pelas três cores primárias de cor e luz, ou seja, o valor RGB da cor é especificado por meio de uma tupla ou lista, e cada valor está entre 0 e 255, pois cada cor primária usa um 8 bits (bit) As três cores equivalem a um total de 24 bits, o que costuma ser chamado de "representação de cores de 24 bits".
import pygame


def main():
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    # 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
    screen.fill((242, 242, 242))
    # 绘制一个圆(参数分别是: 屏幕, 颜色, 圆心位置, 半径, 0表示填充圆)
    pygame.draw.circle(screen, (255, 0, 0,), (100, 100), 10, 0)
    # 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
    pygame.display.flip()
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False


if __name__ == '__main__':
    main()

Etapa 3: carregue a imagem

  • Se você precisa carregar uma imagem diretamente na janela, você pode usar a função do módulo de imagem no pygame para carregar a imagem e então renderizar a imagem através do método blit do objeto janela obtido anteriormente.
import pygame


def main():
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    # 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
    screen.fill((255, 255, 255))
    # 通过指定的文件名加载图像
    ball_image = pygame.image.load('D:/360Safe/ball.png')
    # 在窗口上渲染图像
    screen.blit(ball_image, (50, 50))
    # 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
    pygame.display.flip()
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False


if __name__ == '__main__':
    main()

Etapa 4: perceber o efeito de animação

  • Na verdade, para obter efeitos de animação, o próprio princípio também é muito simples, ou seja, a reprodução contínua de imagens descontínuas, desde que um certo número de quadros por segundo seja atingido, então um efeito de animação relativamente suave pode ser feito.
  • Se você quiser fazer a bola no código acima se mover, você pode usar uma variável para indicar a posição da bola e modificar a posição da bola no loop e então atualizar a janela inteira.
import pygame


def main():
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    # 定义变量来表示小球在屏幕上的位置
    x, y = 50, 50
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        screen.fill((255, 255, 255))
        pygame.draw.circle(screen, (255, 0, 0,), (x, y), 30, 0)
        pygame.display.flip()
        # 每隔50毫秒就改变小球的位置再刷新窗口
        pygame.time.delay(30)
        x, y = x + 5, y + 5


if __name__ == '__main__':
    main()

Etapa 5: detecção de colisão

  • Normalmente existem muitos objetos em um jogo, e a "colisão" entre esses objetos é inevitável, como uma granada atingindo um avião, uma caixa atingindo o solo, etc.
  • A detecção de colisão é uma questão crucial que deve ser tratada na maioria dos jogos.O módulo sprite do pygame fornece suporte para detecção de colisão.
  • Para detectar se as duas bolas colidem, tão fácil:
    • Basta verificar se a distância entre o centro da esfera é menor que a soma dos raios das duas esferas.
  • Para fazer mais bolas pequenas, podemos processar eventos do mouse para criar bolas pequenas com cores, tamanhos e velocidades de movimento aleatórios na posição do clique do mouse, para que possamos aplicar o conhecimento orientado a objetos que aprendemos antes.
from enum import Enum, unique
from math import sqrt
from random import randint
import tkinter

import pygame

@unique
class Color(Enum):
    """颜色"""

    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)
    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)
    GRAY = (242, 242, 242)

    @staticmethod
    def random_color():
        """获得随机颜色"""
        r = randint(0, 255)
        g = randint(0, 255)
        b = randint(0, 255)
        return (r, g, b)


class Ball(object):
    """球"""

    def __init__(self, x, y, radius, sx, sy, color=Color.RED):
        """初始化方法"""
        self.x = x
        self.y = y
        self.radius = radius
        self.sx = sx
        self.sy = sy
        self.color = color
        self.alive = True

    def move(self, screen):
        """移动"""
        self.x += self.sx
        self.y += self.sy
        if self.x - self.radius <= 0 or \
                self.x + self.radius >= screen.get_width():
            self.sx = -self.sx
        if self.y - self.radius <= 0 or \
                self.y + self.radius >= screen.get_height():
            self.sy = -self.sy

    def eat(self, other):
        """吃其他球"""
        if self.alive and other.alive and self != other:
            dx, dy = self.x - other.x, self.y - other.y
            distance = sqrt(dx ** 2 + dy ** 2)
            if distance < self.radius + other.radius \
                    and self.radius > other.radius:
                other.alive = False
                self.radius = self.radius + int(other.radius * 0.146)

    def draw(self, screen):
        """在窗口上绘制球"""
        pygame.draw.circle(screen, self.color,
                           (self.x, self.y), self.radius, 0)

Etapa 6: tratamento de eventos

  • Os eventos de mouse podem ser processados ​​no loop de eventos e o tipo de evento pode ser determinado por meio do atributo type do objeto de evento
  • Então você pode obter a posição do clique do mouse através do atributo pos
  • Se você deseja manipular eventos de teclado neste local, a abordagem é semelhante a manipular eventos de mouse
def main():
    # 定义用来装所有球的容器
    balls = []
    # 初始化导入的pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption('大球吃小球')
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            # 处理鼠标事件的代码
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 获得点击鼠标的位置
                x, y = event.pos
                radius = randint(10, 100)
                sx, sy = randint(-10, 10), randint(-10, 10)
                color = Color.random_color()
                # 在点击鼠标的位置创建一个球(大小、速度和颜色随机)
                ball = Ball(x, y, radius, sx, sy, color)
                # 将球添加到列表容器中
                balls.append(ball)
        screen.fill((255, 255, 255))
        # 取出容器中的球 如果没被吃掉就绘制 被吃掉了就移除
        for ball in balls:
            if ball.alive:
                ball.draw(screen)
            else:
                balls.remove(ball)
        pygame.display.flip()
        # 每隔50毫秒就改变球的位置再刷新窗口
        pygame.time.delay(50)
        for ball in balls:
            ball.move(screen)
            # 检查球有没有吃到其他的球
            for other in balls:
                ball.eat(other)
                
    def confirm_to_quit():
        if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'):
            top.quit()
        
#     # 创建顶层窗口
#     top = tkinter.Tk()
#     # 创建一个装按钮的容器
#     panel = tkinter.Frame(top)
#     # 创建按钮对象 指定添加到哪个容器中 通过command参数绑定事件回调函数
#     button1 = tkinter.Button(panel, text='退出', command=confirm_to_quit)
#     button1.pack(side='right')
#     panel.pack(side='bottom')
#     # 开启主事件循环
#     tkinter.mainloop()

if __name__ == '__main__':
    main()
    
Observação: este blog é baseado no blog de aprendizado de Daniel no GitHub, além de meu próprio entendimento superficial, para registrar meu processo de aprendizado dessa forma.

Link original do GitHub

Acho que você gosta

Origin blog.csdn.net/amyniez/article/details/104588168
Recomendado
Clasificación