Python graphical user interface and game development

The graphical user interface and game development

Module-based GUI tkinter

GUI is an acronym for graphical user interface, graphical user interface for people who used a computer should not unfamiliar, this need not be repeated here. The default Python GUI development module is tkinter (named in previous versions of Python 3 in Tkinter), from the name you can see that it is based on Tk and Tk is a toolkit for Tcl was originally designed, was later transplanted to many other scripting language, it provides a cross-platform GUI controls. Tk certainly not the latest and the best choice, nor particularly powerful GUI controls, in fact, the development of GUI applications are not Python do best, if you really need to develop GUI applications using Python, wxPython, PyQt, PyGTK, etc. module is a good choice.

Tkinter basically used to develop GUI application requires the following five steps:

  1. Import tkinter module what we need.
  2. Create a top-level window object and use it to carry the entire GUI applications.
  3. Adding GUI components on the top-level window object.
  4. By the code of these functions GUI components organized.
  5. Enter the main event loop (main loop).

The following code demonstrates how to use tkinter make a simple GUI application.

import tkinter
import tkinter.messagebox


def main():
    flag = True

    # 修改标签上的文字
    def change_label_text():
        nonlocal flag
        flag = not flag
        color, msg = ('red', 'Hello, world!')\
            if flag else ('blue', 'Goodbye, world!')
        label.config(text=msg, fg=color)

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

    # 创建顶层窗口
    top = tkinter.Tk()
    # 设置窗口大小
    top.geometry('240x160')
    # 设置窗口标题
    top.title('小游戏')
    # 创建标签对象并添加到顶层窗口
    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()

It should be noted, GUI applications typically are event-driven, the reason to enter the main event loop is to monitor the occurrence of various events of mouse, keyboard and executes the corresponding code to handle the event, because the event will continue to occur, Therefore, the need for such a cycle has been running at an event waiting to happen. On the other hand, Tk provide for the placed controls three layout manager, the controls can be positioned by the layout manager, three layout managers are: Placer (developers provide controls the size and placement) , Packer (control automatically filled into the appropriate position) and the grid (to display grid coordinates based controls), not repeated here.

Use Pygame game development

Pygame is an open source Python module designed for the development of multimedia applications (such as video games), which includes support for images, sounds, videos, events, collision, etc. Pygame built on SDL based on, SDL is a cross-platform multimedia development library, using C language, is widely used in the development game, simulator, players, etc.. And let Pygame game developers are no longer bound by the underlying language, may be more concerned about the game's features and logic.

Let's complete a simple little game, the game is called the "big ball eat small ball", of course, to complete this game is not the focus, learn to use Pygame is not the focus, the most important we have to understand how to use earlier in the process explain the object-oriented programming, learn how to use this programming ideas to solve real-world problems.

Making the game window

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

Drawing in the window

Can draw on the window by the function module in the pygame draw, drawing pattern can include: lines, rectangles, polygons, circles, ellipses, arcs and the like. It should be noted that the screen coordinate system is set to the upper left corner of the screen coordinate origin (0, 0), to the right is a forward, down the y-axis is the x-axis positive, representing the position or size of the set, we default units are It is pixels . The so-called pixel is a dot on the screen, you can try the software will browse pictures to enlarge a picture several times, you can see these points. pygame color represented by the color lights of three primary colors notation, i.e., RGB value specified by a tuple or list, each value between 0 and 255, each primary color are used because an 8-bit (bit) the value represented consists of three colors is equivalent to a total of 24, which is often said that the "24-bit color representation."

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

Loading image

If the image needs to be loaded directly onto the window function may be used in image pygame module to load an image window object obtained through the previous blitmethod of rendering an image, the code is shown below.

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('./res/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()

Achieve animation effects

When it comes to animation of the word we are not unfamiliar, in fact, to achieve animation effects, the principle itself is very simple, is not continuous picture of continuous play, as long as a certain number of frames per second to achieve, then you can do a relatively smooth animation. If you want the code above to move the ball, the ball position may be represented by the variables, and modify the ball position in the cycle to refresh the entire window.

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(50)
        x, y = x + 5, y + 5


if __name__ == '__main__':
    main()

Impact checking

Usually a game there will be many objects appear, and "collision" between these objects is inevitable, such as artillery shells hit the aircraft, the box hit the ground and so on. Collision detection is crucial problems in the vast majority of the game is a must have handled, pygame of sprite (animated sprites) module provides support for collision detection, and here we do not introduce functional sprite module provides, to detect because there is no collision of two balls is very simple, just check from the center of the sphere has a radius of no less than two and a ball. In order to create more small ball, we can handle mouse events to create color, size and speed of movement of the ball in both random clicks of the mouse position, of course, to do this, we can learn before Object-oriented knowledge to apply it.

from enum import Enum, unique
from math import sqrt
from random import randint

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)

Event Processing

Mouse events can be processed in the event loop, through the event object typecan determine the type of event properties, and through the posproperty can obtain the location of a mouse click. If you want to deal with keyboard events it is in this place, and handle mouse events similar approach.

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)


if __name__ == '__main__':
    main()

The above two pieces of code together, we've had the "big ball eat small ball" game (shown below), it is not really accurate a game, but do a little basic knowledge of the game we've been through this example tells you, with this knowledge can start your tour of small game development. In fact, after the above code, there are many worthwhile improvements, such as refresh the window and let the ball move up the code should not be placed in the event loop, and other learning multithreading knowledge, with a background thread to handle these things possible It is the better choice. If you want to get a better user experience, we can also add background music in the game and play a sound when the ball collides with the ball, using the pygame's mixer and music module, we can easily do that, we can own knowledge of this area. In fact, want to know more about the pygame, the best tutorial is pygame's official website , English is nothing wrong if you can quickly go Kanla. If you want to develop 3D games , pygame becomes insufficient, if for 3D game developers interested readers may wish to look at Panda3D .


I welcome the attention of the public number, reply keyword " Python ", there will be a gift both hands! ! ! I wish you a successful interview ! ! !

Published 95 original articles · won praise 0 · Views 3067

Guess you like

Origin blog.csdn.net/weixin_41818794/article/details/104257947