Once notas del estudio de Python: interfaz gráfica de usuario y desarrollo de juegos pequeños

1. GUI basada en el módulo tkinter

  • GUI es la abreviatura de Interfaz gráfica de usuario. La interfaz gráfica de usuario no debería ser desconocida para las personas que han usado computadoras, y no es necesario entrar en detalles aquí.
  • El módulo de desarrollo GUI predeterminado de Python es tkinter (llamado Tkinter en la versión anterior de Python 3). A partir de este nombre, se puede ver que se basa en Tk
    • Tk es un conjunto de herramientas, originalmente diseñado para Tcl, y luego adaptado a muchos otros lenguajes de scripting, proporciona controles GUI multiplataforma;
    • Por supuesto, Tk no es la mejor y más nueva opción, y no hay controles GUI particularmente poderosos.
  • De hecho, desarrollar aplicaciones GUI no es el mejor trabajo de Python. Si realmente necesita usar Python para desarrollar aplicaciones GUI, módulos como wxPython, PyQt, PyGTK, etc. son buenas opciones.

  • Básicamente, el uso de tkinter para desarrollar aplicaciones GUI requiere los siguientes 5 pasos:
    • 1. Importe lo que necesitemos en el módulo tkinter.
    • 2. Cree un objeto de ventana de nivel superior y utilícelo para alojar toda la aplicación GUI.
    • 3. Agregue componentes GUI al objeto de ventana de nivel superior.
    • 4. Organice las funciones de estos componentes GUI a través del código.
    • * 5. Ingrese al bucle de eventos principal (bucle principal).

Parámetros comunes del módulo tkinter (python3)

Caso 1: use tkinter para hacer una aplicación GUI simple

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()
     
  • Cabe señalar que las aplicaciones GUI generalmente están controladas por eventos. La razón para ingresar al bucle de eventos principal es monitorear la ocurrencia de varios eventos, como el mouse y el teclado, y ejecutar el código correspondiente para procesar el evento, porque el evento continuará. Por lo tanto, dicho bucle debe estar ejecutándose y esperando que ocurra el próximo evento.
  • Por otro lado, Tk proporciona tres administradores de diseño para la ubicación de los controles. Los controles se pueden colocar a través del administrador de diseño. Los tres administradores de diseño son: Placer (el desarrollador proporciona el tamaño y la ubicación del control), Packer (rellena automáticamente el control en la posición apropiada) y Cuadrícula (coloque el control según las coordenadas de la cuadrícula)

2. Utilice Pygame para el desarrollo de juegos

  • Pygame es un módulo de Python de código abierto específicamente para el desarrollo de aplicaciones multimedia (como videojuegos), que incluye soporte para imágenes, sonidos, videos, eventos, colisiones, etc.
  • Pygame está construido sobre la base de SDL. SDL es una biblioteca de desarrollo multimedia multiplataforma, implementada en lenguaje C, y se usa ampliamente en el desarrollo de juegos, simuladores, jugadores, etc.
  • Pygame permite que los desarrolladores de juegos ya no estén limitados por el lenguaje subyacente y pueden prestar más atención a la función y la lógica del juego.

Consulte el documento chino de Pygame

1. pygame.init (): inicializa todos los módulos de pygame importados
2. pygame.display.set_mode (): inicializa una interfaz lista para ser mostrada
3. pygame.display.set_caption (): establece el título de la ventana actual
4. pygame.quit (): desinstala todos los módulos de pygame importados
5. screen.fill (): establece el color de fondo de la ventana
6. pygame.draw.circle (): dibuja un círculo
7. pygame.display.flip (): actualiza la ventana actual (la ventana de renderizado presentará la imagen dibujada)
8. screen.blit (): coloca una imagen encima de un objeto (dos parámetros: imagen: la imagen a colocar, posición: las coordenadas de la imagen)
注意:
	 1.blit()不会更新屏幕,它在缓冲区中绘制图像;
	 2.需要结合update()/flip()将缓冲区发送到视频卡,才能绘制出图像来。
9. pygame.time.delay (10): cambia la posición de la bola cada 10 milisegundos y actualiza la ventana

Caso 2: Realización de juegos pequeños, pelotas grandes y pelotas pequeñas

El primer paso: hacer la ventana del juego

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()

Paso 2: Dibujar en la ventana

  • Puedes dibujar en la ventana a través de la función del módulo de dibujo en pygame.Los gráficos que se pueden dibujar incluyen: líneas, rectángulos, polígonos, círculos, elipses, arcos, etc.
  • El sistema de coordenadas de la pantalla es establecer la esquina superior izquierda de la pantalla en el origen de las coordenadas (0, 0), a la derecha está la dirección positiva del eje x, y hacia abajo es la dirección positiva del eje y. Cuando expresando la posición o estableciendo el tamaño, nuestras unidades predeterminadas son todas Es un píxel (un píxel es un punto en la pantalla)
  • Los colores en pygame están representados por los tres colores primarios de color y luz, es decir, el valor RGB del color se especifica a través de una tupla o lista, y cada valor está entre 0 y 255, porque cada color primario usa un 8-bit. (bit) Los tres colores equivalen a un total de 24 bits, lo que a menudo se denomina "representación de color 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()

Paso 3: carga la imagen

  • Si necesita cargar una imagen directamente en la ventana, puede usar la función del módulo de imagen en pygame para cargar la imagen, y luego renderizar la imagen a través del método blit del objeto de ventana obtenido previamente.
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()

Paso 4: darse cuenta del efecto de animación

  • De hecho, para lograr efectos de animación, el principio en sí también es muy simple, es decir, reproducción continua de imágenes discontinuas, siempre que se alcance un cierto número de cuadros por segundo, entonces se puede realizar un efecto de animación relativamente suave.
  • Si desea hacer que la bola se mueva en el código anterior, puede usar una variable para indicar la posición de la bola, modificar la posición de la bola en el bucle y luego actualizar toda la ventana.
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()

Paso 5: detección de colisiones

  • Por lo general, hay muchos objetos en un juego y la "colisión" entre estos objetos es inevitable, como un proyectil que golpea un avión, una caja que golpea el suelo, etc.
  • La detección de colisiones es un tema crucial que debe tratarse en la mayoría de los juegos.El módulo de sprites de pygame proporciona soporte para la detección de colisiones.
  • Para detectar si las dos bolas chocan, tan fácil:
    • Simplemente verifique si la distancia entre el centro de la esfera es menor que la suma de los radios de las dos esferas.
  • Para hacer más bolas pequeñas, podemos procesar los eventos del mouse para crear bolas pequeñas con colores, tamaños y velocidades de movimiento aleatorios en la posición del clic del mouse, de modo que podamos aplicar el conocimiento orientado a objetos que aprendimos 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)

Paso 6: manejo de eventos

  • Los eventos del mouse se pueden procesar en el bucle de eventos y el tipo de evento se puede determinar mediante el atributo de tipo del objeto de evento.
  • Luego puede obtener la posición del clic del mouse a través del atributo pos
  • Si desea manejar eventos de teclado en este lugar, el enfoque es similar al manejo de 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()
    
Nota: Este blog se basa en el blog de aprendizaje de Daniel en GitHub, además de mi propia comprensión superficial, para registrar mi proceso de aprendizaje de esta manera.

Enlace original de GitHub

Supongo que te gusta

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