第八章:超级详细的pygame

第八章 游戏模块之Pygame

过年给自己放了一个假,玩王者农药感觉没啥意思了,想了一想能不能用python写一个游戏程序呢?然后找了相关教材,这两天一直在学游戏模块Pygame,今天分享给大家!

讲解之前借嵩天教授的一句话激励自己“无论学什么专业,从事什么工作,在世界的那里坚守着,即使我们不能仗剑天涯,即使要面对眼前的苟且,请学习Pygame,用技术让自己的心灵来趟“诗和远方”的旅行吧!”

一、pygame简介与安装

(一)简介:

1.pygame是python最经典的2D游戏开发第三方库,它也支持3D游戏开发;
2.Pygame是一个利用SDL库写的游戏库,SDL是Simple DirectMedia Layer的简称。
3.pygame适合用于游戏逻辑验证、游戏入门级系统演示验证。
4.pygame是一种游戏开发引擎,基本逻辑具有参考价值。
5.pygame有些‘过时’,但永远‘不过时’,使用pygame可以开发出优秀的游戏!

哪些人群不适合学习pygame?
1.不喜欢游戏或对游戏开发没兴趣的
2.希望使用pygame开发直接商用游戏的
3.只希望学习pygame语言或一般技术开发用于就业的

官网地址:http://www.pygame.org

(二)安装

安装:这里以Windows安装为例
1. windows+r进入命令行
2. pip install pygame 等待安装完成。
3. 输入python测试是否安装成功
4. 输入import pygame查看版本信息

在这里插入图片描述

图片1
在这里插入图片描述

图片2

(三) pygame自带小游戏

1.windows+r进入命令行
2.输入python -m pygame.examples.aliens
3.按回车键

在这里插入图片描述

图片3

二、游戏开发之框架

(一)最小游戏及最小框架

最小游戏

# Pygame的第一个程序
import pygame,sys

pygame.init()
screen = pygame.display.set_mode((600,500))
pygame.display.set_caption("Pygame入门游戏")

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    pygame.display.update()

详解

import pygame, sys     # 引入pygame和sys
'''
1.sys是python的标准库
2.sys提供python运行时环境变量的操控
3.sys.exit()用于退出结束游戏并退出
'''

pygame.init()    # 初始化init()及设置
# 对pygame内部各功能模块进行初始化创建及变量设置,默认调用

screen = pygame.display.set_mode((600,500))
# screen = pygame.display.set_mode(size)  size=(600,500)
# 初始化显示窗口,第一个参数size是一个二值元组,分别表示窗口的宽度和高度

pygame.display.set_caption("Pygame游戏之旅")   # 游戏名称
# 设置显示窗口的标题内容,参数title是一个字符串类型

while True:   # 无限循环,直到python运行时退出结束
    for event in pygame.event.get():    # 获取事件并逐类响应
        # 从pygame的事件队列中取出事件,并从队列中删除事件,例如:键盘按下是一个事件。

        if event.type == pygame.QUIT:    # 设置退出事件
            # 获取事件类型,并逐类响应;pygame.QUIT是pygame中定义的退出事件常量
            sys.exit()    # 用于退出结束游戏并退出

    pygame.display.update()   # 刷新屏幕
    # 对显示窗口进行更新,默认窗口全部重绘

# 虽然没有意义,但它反应了pygame最小开发框架
# 极简开发框架:引入及初始化、事件及刷新
# 最小开发框架:引入pygame和sys、初始化int()及设置、获取事件并逐类响应、刷新屏幕
# 获取事件并逐类响应<=>刷新屏幕

(二)壁球小游戏(展示型)与图像的基本使用

(1) 关键要素

从需求到实现的三个要素:
1.壁球:游戏需要一个壁球,通过图片引入
2.壁球运动:壁球要能够上下左右运动
3.壁球反弹:壁球要能够在上下左右边缘反弹

(2)壁球

注意事项:
1.注意大小写,PY和PYG大写;
2.下载图片保存为GIF格式
3.壁球的图片链接:https://python123.io/PY15/PYG02-ball.gif

(3) 壁球运动

1.壁球每次向右及向下移动1个像素
在这里插入图片描述

图片4

2.与默认窗口处理方法一致,pygame采用左上角坐标(0,0),横轴正向向右,纵轴正向向下
在这里插入图片描述

图片5

(4) 壁球反弹

图片每次碰到边缘,速度取反
在这里插入图片描述

图片6

(5)展示版代码

# 引用
import pygame, sys  
# sys是Python的标准库,提供Python运行时环境变量的操控。

# 初始化
pygame.init()
# 游戏窗口的大小
size = width, height = 600, 500  
# 速度为1像素
speed = [1, 1]
# RGB颜色为黑色
BLACK = 0, 0, 0  
# 设置游戏窗口大小
screen = pygame.display.set_mode(size)  
# 设置游戏标题
pygame.display.set_caption("壁球展示版")
ball = pygame.image.load("../ball.gif")
ballrect = ball.get_rect()
# pygame.image.load(filename)将filename路径下的图像载入游戏,支持JPG、PNG、GIF(非动画)等13种常用图片格式
# Surface对象 Pygame使用内部定义的Surface对象表示所有载入的图像,其中.get_rect()方法返回一个与图像外切的图形Rect对象
# Rect对象 有一些重要属性,例如:top,bottom,left,right表示上下左右;width,height表示宽度高度

# 事件处理
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    ballrect = ballrect.move(speed[0], speed[1])  # 矩形移动一个偏移量(x,y),即在横轴方向移动x像素,纵轴方向移动y像素,xy为整数
    # 球碰左右两侧,横向速度取反
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    # 球碰上下两侧,纵向速度取反
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    # 窗口刷新
    # 系统默认,图层移动之后,原来的位置将会被填充白色。因此,每一次都需要不断刷新背景色
    screen.fill(BLACK)     
    # screen.fill(color)显示窗口背景填充为color颜色,采用RGB色彩体系。由于壁球不断运动,运动后原有位置将默认填充白色,因此需要不断刷新背景色

    # 将一个图像绘制在另一个图像上,即将ball会知道ballrect位置上,通过Rect对象引导对壁球绘制
    screen.blit(ball, ballrect)  
    # screen.blit(src, dest)  # 将一个图像绘制在另一个图像上,即将src绘制到dest位置上。通过Rect对象引导对壁球绘制
    pygame.display.update()  # 窗口刷新

玩了一下发现小球运动太快了,接下来对小球的速度做改进。

(三)壁球小游戏(节奏型)与屏幕的帧率设置

(1) 关键要素

1.需求:壁球可以按照一定速度运动
2从需求到实现:如何控制壁球的运动速度呢?
3.壁球速度:
	每次循环壁球运动一次
    控制循环间隔即可控制速度
    (展示型)在尽最大能力运动

(2) 节奏版代码

# 引用
import pygame, sys
# sys是Python的标准库,提供Python运行时环境变量的操控。

# 初始化
pygame.init()
# 游戏窗口的大小
size = width, height = 600, 500
# 速度为1像素
speed = [1, 1]
# RGB颜色为黑色
BLACK = 0, 0, 0
# 设置游戏窗口大小
screen = pygame.display.set_mode(size)
# 设置游戏标题
pygame.display.set_caption("壁球展示版")
# 加载小球
ball = pygame.image.load("../ball.gif")
ballrect = ball.get_rect()
# pygame.image.load(filename)将filename路径下的图像载入游戏,支持JPG、PNG、GIF(非动画)等13种常用图片格式
# Surface对象 Pygame使用内部定义的Surface对象表示所有载入的图像,其中.get_rect()方法返回一个与图像外切的图形Rect对象
# Rect对象 有一些重要属性,例如:top,bottom,left,right表示上下左右;width,height表示宽度高度
fps = 300   # Frams per Second 每秒帧率参数
fclock = pygame.time.Clock()  # 创建对象
# pygame.time.Clock()创建一个Clock对象,用于操作时间

# 事件处理
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    ballrect = ballrect.move(speed[0], speed[1])  # 矩形移动一个偏移量(x,y),即在横轴方向移动x像素,纵轴方向移动y像素,xy为整数
    # 球碰左右两侧,横向速度取反
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    # 球碰上下两侧,纵向速度取反
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    # 窗口刷新
    # 系统默认,图层移动之后,原来的位置将会被填充白色。因此,每一次都需要不断刷新背景色
    screen.fill(BLACK)
    # screen.fill(color)显示窗口背景填充为color颜色,采用RGB色彩体系。由于壁球不断运动,运动后原有位置将默认填充白色,因此需要不断刷新背景色

    # 将一个图像绘制在另一个图像上,即将ball会知道ballrect位置上,通过Rect对象引导对壁球绘制
    screen.blit(ball, ballrect)
    # screen.blit(src, dest)  # 将一个图像绘制在另一个图像上,即将src绘制到dest位置上。通过Rect对象引导对壁球绘制
    pygame.display.update()  # 窗口刷新
    fclock.tick(fps)
    # fclock.tick(framerate)控制帧速度,即窗口刷新速度,例如:
    # clock.tick(300)表示每秒钟300次帧刷新屏幕中每次展示的静态图像称为帧
    

这个程序能叫游戏吗?都不能操作,接下来讲解操作版!

(四)壁球小游戏(控制型)与键盘的基本使用

(1) 关键要素

1.需求:通过键盘的上下左右控制壁球运动速度,规则如下:
						纵向绝对速度增加1个像素(纵向加速)
								   ↑
	横向绝对速度减少1个像素(横向减速) ←    → 横向绝对速度增加1个像素(横向加速)
						  		   ↓
						纵向绝对速度减少1个像素(纵向减速)
2.从需求到实现的关键要素:
	2.1键盘使用:如何获取键盘的操作事件
    	pygame采用事件来对应键盘操作
        获取事件将得到键盘输入
        不同按键编写操作函数即可
    2.2速度调节:根据对应按键调节壁球运动速度
3.键盘控制操作:
pygame.KEYDOWN Pygame对键盘敲击的事件定义,键盘每个键对应一个具体定义:
↑:pygame.K_UP
↓:pygame.K_LEFT
←:pygame.K_DOWN
→:pygame.K_RIGHT

(2) 控制版代码

# 引用
import pygame, sys
# sys是Python的标准库,提供Python运行时环境变量的操控。

# 初始化
pygame.init()
# 游戏窗口的大小
size = width, height = 600, 500
# 速度为1像素
speed = [1, 1]
# RGB颜色为黑色
BLACK = 0, 0, 0
# 设置游戏窗口大小
screen = pygame.display.set_mode(size)
# 设置游戏标题
pygame.display.set_caption("壁球展示版")
# 加载小球
ball = pygame.image.load("../ball.gif")
ballrect = ball.get_rect()
# pygame.image.load(filename)将filename路径下的图像载入游戏,支持JPG、PNG、GIF(非动画)等13种常用图片格式
# Surface对象 Pygame使用内部定义的Surface对象表示所有载入的图像,其中.get_rect()方法返回一个与图像外切的图形Rect对象
# Rect对象 有一些重要属性,例如:top,bottom,left,right表示上下左右;width,height表示宽度高度
fps = 300   # Frams per Second 每秒帧率参数
fclock = pygame.time.Clock()  # 创建对象
# pygame.time.Clock()创建一个Clock对象,用于操作时间

# 事件处理
while True:
    for event in pygame.event.get():  # 获取事件并逐类响应
        # 从pygame的事件队列中取出事件,并从队列中删除事件,例如:键盘按下是一个事件。
        if event.type == pygame.QUIT:
            # 获取事件类型,并逐类响应;pygame.QUIT是pygame中定义的退出事件常量
            sys.exit()  # 用于退出结束游戏并退出
        # 添加按键控制
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0] / abs(speed[0]))
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else (abs(speed[1]) - 1) * int(speed[1] / abs(speed[1]))

    ballrect = ballrect.move(speed[0], speed[1])  # 矩形移动一个偏移量(x,y),即在横轴方向移动x像素,纵轴方向移动y像素,xy为整数
    # 球碰左右两侧,横向速度取反
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    # 球碰上下两侧,纵向速度取反
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    # 窗口刷新
    # 系统默认,图层移动之后,原来的位置将会被填充白色。因此,每一次都需要不断刷新背景色
    screen.fill(BLACK)
    # screen.fill(color)显示窗口背景填充为color颜色,采用RGB色彩体系。由于壁球不断运动,运动后原有位置将默认填充白色,因此需要不断刷新背景色

    # 将一个图像绘制在另一个图像上,即将ball会知道ballrect位置上,通过Rect对象引导对壁球绘制
    screen.blit(ball, ballrect)
    # screen.blit(src, dest)  # 将一个图像绘制在另一个图像上,即将src绘制到dest位置上。通过Rect对象引导对壁球绘制
    pygame.display.update()  # 窗口刷新
    fclock.tick(fps)
    # fclock.tick(framerate)控制帧速度,即窗口刷新速度,例如:
    # clock.tick(300)表示每秒钟300次帧刷新屏幕中每次展示的静态图像称为帧

三、游戏开发之机制(上):屏幕与事件

(一) pygame屏幕绘制机制简介

(1) 屏幕控制

pygame.display
	1.用来控制pygame游戏的屏幕
    2.pygame有且只有一个屏幕
    3.屏幕左上角坐标为(00)
    4.以像素为单位

(2) 屏幕控制需求

游戏全屏
游戏屏幕大小可调节
游戏屏幕无边框
更改游戏标题内容
更改游戏图标

(3) 屏幕控制的重要函数

屏幕尺寸和模式
	pygame.display.set_mode()
    pygame.display.Info()
    
窗口标题和图标
	pygame.display.set_caption()
    pygame.display.set_icon()
    pygame.display.get_caption()
    
窗口感知和刷新
	pygame.display.get_active()
    pygame.display.flip()
    pygame.display.update()    

(4) OpenGL和硬件加速

pygame.display
	可以采用OpenGL支持显示
    可以采用硬件加速显示
    绘制加速将带来更流畅的运行效果

更多内容可以参考官网:www.pygame.org

(二) pygame屏幕尺寸和模式设置

(1) 屏幕模式函数

pygame.display.set_mode(r=(0,0), flags=0)
	r是游戏屏幕的分辨率,采用(width、height)方式输入
    flags用来控制显示类型,可用|组合使用,常用显示标签如下:
    	pygame.RESIZEABLE  窗口大小可调
        pygame.NOFRAME  窗口没有边界显示
        pygame.FULLSCREEN  窗口全屏显示
    注意:每种显示方式要配合相应的处理机制

(2) 屏幕设置为大小可调

screen = pygame.display.set_mode(size,pygame.RESIZEABLE)
注意:大小可调是要有尺寸变化的响应
	对扩张显示界面的刷新
    对扩张/缩小显示界面的游戏相应

(3) 屏幕设置为无边框

screen = pygame.display.set_mode(size,pygame.NOFRAME)
注意:无边框时要添加其他退出方式

(4) 屏幕设置为全屏

screen = pygame.display.set_mode(size,pygame.FULLSCREEN)
注意:全屏时要考虑系统分辨率,否则将会按照用户设定被拉伸

(5) 屏幕信息函数

pygame.display.Info()
	产生一个显示信息对象videoInfo,表达当前屏幕的参数信息
    在.set_mode()之前调用,则显示当前系统显示参数信息
    参数很多,其中有两个十分重要,如下:
    	current_w:当前显示模式或窗口的像素宽度
        current_h:当前显示模式或窗口的像素高度

(6) 全屏版

# 引用
import pygame, sys
# sys是Python的标准库,提供Python运行时环境变量的操控。

# 初始化
pygame.init()
# 游戏窗口的大小
# size = width, height = 600, 500
vInfo = pygame.display.Info()
size = width, height = vInfo.current_w, vInfo.current_h
# 速度为1像素
speed = [1, 1]
# RGB颜色为黑色
BLACK = 0, 0, 0
# 设置游戏窗口大小
# screen = pygame.display.set_mode(size)
'''
注意:大小可调是要有尺寸变化的响应
   对扩张显示界面的刷新
    对扩张/缩小显示界面的游戏相应
'''
# screen = pygame.display.set_mode(size,pygame.RESIZABLE)
# 注意:无边框时要添加其他退出方式
# screen = pygame.display.set_mode(size,pygame.NOFRAME)
# 注意:全屏时要考虑系统分辨率,否则将会按照用户设定被拉伸
screen = pygame.display.set_mode(size,pygame.FULLSCREEN)
# 设置游戏标题
pygame.display.set_caption("壁球全屏版")
# 加载小球
ball = pygame.image.load("../ball.gif")
ballrect = ball.get_rect()
# pygame.image.load(filename)将filename路径下的图像载入游戏,支持JPG、PNG、GIF(非动画)等13种常用图片格式
# Surface对象 Pygame使用内部定义的Surface对象表示所有载入的图像,其中.get_rect()方法返回一个与图像外切的图形Rect对象
# Rect对象 有一些重要属性,例如:top,bottom,left,right表示上下左右;width,height表示宽度高度
fps = 300   # Frams per Second 每秒帧率参数
fclock = pygame.time.Clock()  # 创建对象
# pygame.time.Clock()创建一个Clock对象,用于操作时间

# 事件处理
while True:
    for event in pygame.event.get():  # 获取事件并逐类响应
        # 从pygame的事件队列中取出事件,并从队列中删除事件,例如:键盘按下是一个事件。
        if event.type == pygame.QUIT:
            # 获取事件类型,并逐类响应;pygame.QUIT是pygame中定义的退出事件常量
            sys.exit()  # 用于退出结束游戏并退出
        # 添加按键控制
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0] / abs(speed[0]))
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else (abs(speed[1]) - 1) * int(speed[1] / abs(speed[1]))
            elif event.key == pygame.K_ESCAPE:   # 添加Esc退出键
                sys.exit()

    ballrect = ballrect.move(speed[0], speed[1])  # 矩形移动一个偏移量(x,y),即在横轴方向移动x像素,纵轴方向移动y像素,xy为整数
    # 球碰左右两侧,横向速度取反
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    # 球碰上下两侧,纵向速度取反
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    # 窗口刷新
    # 系统默认,图层移动之后,原来的位置将会被填充白色。因此,每一次都需要不断刷新背景色
    screen.fill(BLACK)
    # screen.fill(color)显示窗口背景填充为color颜色,采用RGB色彩体系。由于壁球不断运动,运动后原有位置将默认填充白色,因此需要不断刷新背景色

    # 将一个图像绘制在另一个图像上,即将ball会知道ballrect位置上,通过Rect对象引导对壁球绘制
    screen.blit(ball, ballrect)
    # screen.blit(src, dest)  # 将一个图像绘制在另一个图像上,即将src绘制到dest位置上。通过Rect对象引导对壁球绘制
    pygame.display.update()  # 窗口刷新
    fclock.tick(fps)
    # fclock.tick(framerate)控制帧速度,即窗口刷新速度,例如:
    # clock.tick(300)表示每秒钟300次帧刷新屏幕中每次展示的静态图像称为帧

(7) 伸缩版

pygame.VIDEORESIZE
这是一种窗口大小更改的事件
事件发生后,返回event.size元组,包含新窗口的宽度和高度
	.size[0] 宽度,也可以用event.w
    .size[1] 高度,也可以用event.h
    返回参数仅在事件发生时有用
# 引用
import pygame, sys
# sys是Python的标准库,提供Python运行时环境变量的操控。

# 初始化
pygame.init()
# 游戏窗口的大小
size = width, height = 600, 500
# 速度为1像素
speed = [1, 1]
# RGB颜色为黑色
BLACK = 0, 0, 0
# 设置游戏窗口大小
screen = pygame.display.set_mode(size,pygame.RESIZABLE)
# 设置游戏标题
pygame.display.set_caption("壁球伸缩版")
# 加载小球
ball = pygame.image.load("../ball.gif")
ballrect = ball.get_rect()
# pygame.image.load(filename)将filename路径下的图像载入游戏,支持JPG、PNG、GIF(非动画)等13种常用图片格式
# Surface对象 Pygame使用内部定义的Surface对象表示所有载入的图像,其中.get_rect()方法返回一个与图像外切的图形Rect对象
# Rect对象 有一些重要属性,例如:top,bottom,left,right表示上下左右;width,height表示宽度高度
fps = 300   # Frams per Second 每秒帧率参数
fclock = pygame.time.Clock()  # 创建对象
# pygame.time.Clock()创建一个Clock对象,用于操作时间

# 事件处理
while True:
    for event in pygame.event.get():  # 获取事件并逐类响应
        # 从pygame的事件队列中取出事件,并从队列中删除事件,例如:键盘按下是一个事件。
        if event.type == pygame.QUIT:
            # 获取事件类型,并逐类响应;pygame.QUIT是pygame中定义的退出事件常量
            sys.exit()  # 用于退出结束游戏并退出
        # 添加按键控制
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0] / abs(speed[0]))
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else (abs(speed[1]) - 1) * int(speed[1] / abs(speed[1]))
            elif event.key == pygame.K_ESCAPE:   # 添加Esc退出键
                sys.exit()
        elif event.type == pygame.VIDEORESIZE:
            size = width, height = event.size[0], event.size[1]
            screen = pygame.display.set_mode(size, pygame.RESIZABLE)
    ballrect = ballrect.move(speed[0], speed[1])  # 矩形移动一个偏移量(x,y),即在横轴方向移动x像素,纵轴方向移动y像素,xy为整数
    # 球碰左右两侧,横向速度取反
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    # 球碰上下两侧,纵向速度取反
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    # 窗口刷新
    # 系统默认,图层移动之后,原来的位置将会被填充白色。因此,每一次都需要不断刷新背景色
    screen.fill(BLACK)
    # screen.fill(color)显示窗口背景填充为color颜色,采用RGB色彩体系。由于壁球不断运动,运动后原有位置将默认填充白色,因此需要不断刷新背景色

    # 将一个图像绘制在另一个图像上,即将ball会知道ballrect位置上,通过Rect对象引导对壁球绘制
    screen.blit(ball, ballrect)
    # screen.blit(src, dest)  # 将一个图像绘制在另一个图像上,即将src绘制到dest位置上。通过Rect对象引导对壁球绘制
    pygame.display.update()  # 窗口刷新
    fclock.tick(fps)
    # fclock.tick(framerate)控制帧速度,即窗口刷新速度,例如:
    # clock.tick(300)表示每秒钟300次帧刷新屏幕中每次展示的静态图像称为帧

(三) pygame窗口标题和图标设置

(1) 窗口标题和图标函数

pygame.display.set_caption(title, icontitle=None)
	title设置窗口的标题内容
	icontitle设置图表化后的小标题
pygame.display.get_caption()
	返回当前设置窗口的标题及大小标题内容
	返回结构为(title, incontitle)
	该函数与游戏交互逻辑配合,可以根据游戏情节修改标题内容
pygame.display.set_icon(surface)
	设置窗口的图标效果
	图标是一个surface对象
	图标地址:
		https://python123.io/PY15/PYG03-flower.png
		https://python123.io/PY15/PYG03-withered-flower.png
	
	

(2) 图标版

# 引用
import pygame, sys
# sys是Python的标准库,提供Python运行时环境变量的操控。

# 初始化
pygame.init()

# 游戏窗口的大小
size = width, height = 600, 500
# 速度为1像素
speed = [1, 1]
# RGB颜色为黑色
BLACK = 0, 0, 0
# 设置游戏窗口大小
screen = pygame.display.set_mode(size,pygame.RESIZABLE)
# 设置图标
icon = pygame.image.load('tb.png')
pygame.display.set_icon(icon)
# 设置游戏标题
pygame.display.set_caption("壁球图标版", "tb")
# 加载小球
ball = pygame.image.load("../ball.gif")
ballrect = ball.get_rect()
# pygame.image.load(filename)将filename路径下的图像载入游戏,支持JPG、PNG、GIF(非动画)等13种常用图片格式
# Surface对象 Pygame使用内部定义的Surface对象表示所有载入的图像,其中.get_rect()方法返回一个与图像外切的图形Rect对象
# Rect对象 有一些重要属性,例如:top,bottom,left,right表示上下左右;width,height表示宽度高度
fps = 300   # Frams per Second 每秒帧率参数
fclock = pygame.time.Clock()  # 创建对象
# pygame.time.Clock()创建一个Clock对象,用于操作时间

# 事件处理
while True:
    for event in pygame.event.get():  # 获取事件并逐类响应
        # 从pygame的事件队列中取出事件,并从队列中删除事件,例如:键盘按下是一个事件。
        if event.type == pygame.QUIT:
            # 获取事件类型,并逐类响应;pygame.QUIT是pygame中定义的退出事件常量
            sys.exit()  # 用于退出结束游戏并退出
        # 添加按键控制
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0] / abs(speed[0]))
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else (abs(speed[1]) - 1) * int(speed[1] / abs(speed[1]))
            elif event.key == pygame.K_ESCAPE:   # 添加Esc退出键
                sys.exit()
        elif event.type == pygame.VIDEORESIZE:
            size = width, height = event.size[0], event.size[1]
            screen = pygame.display.set_mode(size, pygame.RESIZABLE)

    ballrect = ballrect.move(speed[0], speed[1])  # 矩形移动一个偏移量(x,y),即在横轴方向移动x像素,纵轴方向移动y像素,xy为整数
    # 球碰左右两侧,横向速度取反
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    # 球碰上下两侧,纵向速度取反
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    # 窗口刷新
    # 系统默认,图层移动之后,原来的位置将会被填充白色。因此,每一次都需要不断刷新背景色
    screen.fill(BLACK)
    # screen.fill(color)显示窗口背景填充为color颜色,采用RGB色彩体系。由于壁球不断运动,运动后原有位置将默认填充白色,因此需要不断刷新背景色

    # 将一个图像绘制在另一个图像上,即将ball会知道ballrect位置上,通过Rect对象引导对壁球绘制
    screen.blit(ball, ballrect)
    # screen.blit(src, dest)  # 将一个图像绘制在另一个图像上,即将src绘制到dest位置上。通过Rect对象引导对壁球绘制
    pygame.display.update()  # 窗口刷新
    fclock.tick(fps)
    # fclock.tick(framerate)控制帧速度,即窗口刷新速度,例如:
    # clock.tick(300)表示每秒钟300次帧刷新屏幕中每次展示的静态图像称为帧

(四) pygame窗口感知和刷新运用

(1) 屏幕控制的重要函数

pygame.display.get_active()
	当窗口在系统中显示(屏幕绘制/非图表化)时返回True,否则返回False
    该函数可以用来判断是否游戏窗口被最小化
    进一步,判断后可以暂停游戏,改变响应模式等
pygame.display.flip()
	重新绘制整个窗口
pygame.display.update()
	仅重新绘制窗口中有变化的区域,相比.flip()执行更快
    
    

(2) 窗口感知版

# 引用
import pygame, sys
# sys是Python的标准库,提供Python运行时环境变量的操控。

# 初始化
pygame.init()

# 游戏窗口的大小
size = width, height = 600, 500
# 速度为1像素
speed = [1, 1]
# RGB颜色为黑色
BLACK = 0, 0, 0
# 设置游戏窗口大小
screen = pygame.display.set_mode(size,pygame.RESIZABLE)
# 设置图标
icon = pygame.image.load('tb.png')
pygame.display.set_icon(icon)
# 设置游戏标题
pygame.display.set_caption("壁球图标版", "tb")
# 加载小球
ball = pygame.image.load("../ball.gif")
ballrect = ball.get_rect()
# pygame.image.load(filename)将filename路径下的图像载入游戏,支持JPG、PNG、GIF(非动画)等13种常用图片格式
# Surface对象 Pygame使用内部定义的Surface对象表示所有载入的图像,其中.get_rect()方法返回一个与图像外切的图形Rect对象
# Rect对象 有一些重要属性,例如:top,bottom,left,right表示上下左右;width,height表示宽度高度
fps = 300   # Frams per Second 每秒帧率参数
fclock = pygame.time.Clock()  # 创建对象
# pygame.time.Clock()创建一个Clock对象,用于操作时间

# 事件处理
while True:
    for event in pygame.event.get():  # 获取事件并逐类响应
        # 从pygame的事件队列中取出事件,并从队列中删除事件,例如:键盘按下是一个事件。
        if event.type == pygame.QUIT:
            # 获取事件类型,并逐类响应;pygame.QUIT是pygame中定义的退出事件常量
            sys.exit()  # 用于退出结束游戏并退出
        # 添加按键控制
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0] / abs(speed[0]))
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else (abs(speed[1]) - 1) * int(speed[1] / abs(speed[1]))
            elif event.key == pygame.K_ESCAPE:   # 添加Esc退出键
                sys.exit()
        elif event.type == pygame.VIDEORESIZE:
            size = width, height = event.size[0], event.size[1]
            screen = pygame.display.set_mode(size, pygame.RESIZABLE)
    if pygame.display.get_active():
        ballrect = ballrect.move(speed[0], speed[1])  # 矩形移动一个偏移量(x,y),即在横轴方向移动x像素,纵轴方向移动y像素,xy为整数
    # 球碰左右两侧,横向速度取反
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    # 球碰上下两侧,纵向速度取反
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    # 窗口刷新
    # 系统默认,图层移动之后,原来的位置将会被填充白色。因此,每一次都需要不断刷新背景色
    screen.fill(BLACK)
    # screen.fill(color)显示窗口背景填充为color颜色,采用RGB色彩体系。由于壁球不断运动,运动后原有位置将默认填充白色,因此需要不断刷新背景色

    # 将一个图像绘制在另一个图像上,即将ball会知道ballrect位置上,通过Rect对象引导对壁球绘制
    screen.blit(ball, ballrect)
    # screen.blit(src, dest)  # 将一个图像绘制在另一个图像上,即将src绘制到dest位置上。通过Rect对象引导对壁球绘制
    pygame.display.update()  # 窗口刷新
    fclock.tick(fps)
    # fclock.tick(framerate)控制帧速度,即窗口刷新速度,例如:
    # clock.tick(300)表示每秒钟300次帧刷新屏幕中每次展示的静态图像称为帧

(五) pygame事件处理机制简介

(1) 事件处理需求

响应用户键盘、鼠标等外设操作
响应屏幕尺寸和模式变化
响应游戏情节的特定触发条件
产生一些触发条件

(2) pygame事件队列

鼠标、屏幕和键盘  -------------- 事件队列------------> 用户对事件逐一处理
缓存并派发所有事件
原则上先到先处理

(3) pygame事件

pygame.event. EventType
	事件本质上是一种封装后的数据类型(对象)
	EventType是Pygame的一个类,表示事件类型
	事件类型只有属性,没有方法
	用户可自定义新的事件类型

(4) 事件类型及属性
在这里插入图片描述

图8

(5) 事件处理的重要函数
在这里插入图片描述

图9

(六) 键盘事件及类型的使用

(1) 键盘事件及属性

pygame.event.KEYDOWN             pygame.event.KEYUP
键盘按下事件                          键盘释放事件
event. unicode  按键的unicode,平台有关,不推荐使用
event.key       按键的常量名称         event.key
event.mod       按键修饰符的组合值      event.mod

(2) 按键的常量名称
在这里插入图片描述

图10
在这里插入图片描述

图11
在这里插入图片描述

图12

(3) 按键的修饰符
在这里插入图片描述

图13

event.mod
	修饰符的按位或运算
    event.mod = KMOD_ALT | KMOD_SHIFT

(4) 键盘事件代码

import pygame,sys

pygame.init()
screen = pygame.display.set_mode((600,500))
pygame.display.set_caption("Pygame入门游戏")

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        # 添加按键事件
        elif event.type == pygame.KEYDOWN:
            if event.unicode == "":
                print("#",event.key, event.mod)
            else:
                print(event.unicode, event.key, event.mod)
    pygame.display.update()

(七) 鼠标事件及类型的使用

(1) 鼠标事件及属性

pygame. event. MOUSEMOTION 鼠标移动事件
pygame.event. MOUSEBUTTONUP 鼠标鍵释放事件
pygame. event. MOUSEBUTTONDOWN 鼠标键按下事件
pygame.event.MOUSEMOTION            鼠标移动事件
  event.pos                     鼠标当前坐标值(x,y) ,相对于窗口左上角
  event.rel                     鼠标相对运动距离(x,Y) ,相对于上次事件
  event. buttons                鼠标按钮状态(a,b,c) ,对应于鼠标的三个键
    
pygame.event.MOUSEBUTTONUP 	鼠标键释放事件
  event.pos           鼠标当前坐标值(x,y) ,相对于窗口左上角
  event.button        鼠标按下键编号n
					 取值0/1/2,分别对应三个键

pygame.event.MOUSEBUTTONDOWN 	鼠标键按下事件
  event.pos 				鼠标当前坐标值(x,y),相对于窗口左上角
  event.button			鼠标按下键编号n
						取值为整数,左键为1,右键为3,设备相关
    

(2) 鼠标事件代码

import pygame,sys

pygame.init()
screen = pygame.display.set_mode((600,500))
pygame.display.set_caption("Pygame入门游戏")

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.MOUSEMOTION:
            print("[MOUSEMOTION]:", event.pos, event.rel, event.buttons)
        elif event.type == pygame.MOUSEBUTTONUP:
            print("[MOUSEBUTTONUP]:", event.pos, event.button)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            print("[MOUSEBUTTONDOWN]:", event.pos, event.button)
    pygame.display.update()

(八) 鼠标型

(1) 需求

需求:
    鼠标可以通过左键摆放壁球,当释放按键时壁球运动
从需求到实现的关键要素:
    鼠标事件:对于鼠标键按下和释放的合理处置

(2) 原理

鼠标左键按下
	左键按下拖拽小球
鼠标左键释放
	左键释放小球继续运动

(3) 局部处理

增加一种交互方式要考虑额外的局部处理和游戏逻辑的调试

(4) 代码实现

import pygame
import sys

pygame.init()

vInfo = pygame.display.Info()
size = width, height = 600, 500
speed = [1, 1]
BLACK = 0, 0, 0

screen = pygame.display.set_mode((600, 400), pygame.RESIZABLE)
# 设置图标
icon = pygame.image.load('tb.png')
pygame.display.set_icon(icon)
pygame.display.set_caption('PyGame 游戏之旅')
ball = pygame.image.load('ball.gif')
ballrect = ball.get_rect()

fps = 300   # frames per second
fclock = pygame.time.Clock()
still = False

while True:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            sys.exit()
        elif e.type == pygame.KEYDOWN:
            if e.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0]/abs(speed[0]))
            elif e.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif e.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else (abs(speed[1]) - 1) * int(speed[1] / abs(speed[1]))
            elif e.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif e.key == pygame.K_ESCAPE:
                sys.exit()
        elif e.type == pygame.VIDEORESIZE:
            size = width, height = e.size[0], e.size[1]
            screen = pygame.display.set_mode(size, pygame.RESIZABLE)
        # 设置鼠标按钮
        elif e.type == pygame.MOUSEBUTTONDOWN:
            if e.button == 1:
                still = True
        elif e.type == pygame.MOUSEBUTTONUP:
            still = False
            if e.button == 1:
                ballrect = ballrect.move(e.pos[0] - ballrect.left, e.pos[1] - ballrect.top)
        elif e.type == pygame.MOUSEMOTION:
            if e.buttons[0] == 1:
                ballrect = ballrect.move(e.pos[0] - ballrect.left, e.pos[1] - ballrect.top)

    if pygame.display.get_active() and not still:
        ballrect = ballrect.move(speed[0], speed[1])
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = - speed[0]
        if ballrect.right > width and ballrect.right + speed[0] > ballrect.right:
            speed[0] = -speed[0]
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = - speed[1]
        if ballrect.bottom > height and ballrect.bottom + speed[1] > ballrect.bottom:
            speed[1] = - speed[1]

    screen.fill(BLACK)
    screen.blit(ball, ballrect)
    pygame.display.update()
    fclock.tick(fps)

(九) pygame事件处理函数

(1) 事件处理的重要函数
在这里插入图片描述

图14

(2) 事件处理函数解析

pygame.event.get()
	从事件队列中获得事件列表,即获得所有被队列的事件
    	for event in pygaem.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
    可以添加参数,获得某类或某些类事件
    	pygame.event.get(type)
        pygame.event.get(typelist)
        
pygame.event.poll()
	从事件队列中获得一个事件
    while True:
        event = pygame.event.poll()
    事件获取将从事件队列中删除
    如果事件队列为空,则返回 event.NOEVENT
    
pygame. event.clear()
	从事件队列中删除事件,默认删除所有事件
	该函数与pygame. event.get()类似,区别仅是不对事件进行处理
	可以增加参数,删除某类或某些类事件:
   		pygame.event. clear (type)
   		pygame.event.clear (typelist)
        
pygame. event. set_blocked(type or typelist)
	控制哪些类型事件不允许被保存到事件队列中
    
pygame.event. set_allowed(type or typelist)
	控制哪些类型事件允许被保存到事件队列中
    
pygame. event.get_blocked(type)
	测试某个事件类型是否被事件队列所禁止
	如果事件类型被禁止,则返回True ,否则返回False
    
pygame . event.post (Event)
	产生一个事件,并将其放入事件队列
	一般用于放置用户自定义事件(pygame.USEREVENT )
	也可以用于放置系统定义事件(如鼠标或键盘等) ,给定参数
    
pygame. event.Event(type, dict)
	创建一个给定类型的事件
	其中,事件的属性和值采用字典类型复制,属性名采用字符串形式
	如果创建已有事件,属性需要一致

(3) pygame事件队列

事件队列 pygame. event.set_blocked()
事件队列 pygame. event.set_allowed()
事件队列 pygame. event.get_blocked()
设置事件队列能够缓存事件的类型

**注意:**同时仅能存储128个事件,当队列满时,更多事件将被丢弃

(4) 代码实现

import pygame,sys

pygame.init()
screen = pygame.display.set_mode((600,500))
pygame.display.set_caption("事件处理")
fps = 1
fclock = pygame.time.Clock()
num = 1

while True:
    uevent = pygame.event.Event(pygame.KEYDOWN, {
    
    "unicode":123, "key":pygame.K_SPACE, 'mod':pygame.KMOD_ALT})
    pygame.event.post(uevent)
    num = num + 1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.unicode == "":
                print("[KEYDOWN {}]:".format(num), "#", event.key, event.mod)
            else:
                print("[KEYDOWN {}]:".format(num), event.unicode, event.key, event.mod)

    pygame.display.update()
    fclock.tick(fps)

四、游戏开发之机制(下):色彩与绘图

(一) pygame色彩机制

(1) 色彩表达

色彩表达
pygame. Colorcolor
类用于表达色彩,使用RGB或RGBA色彩模式, A可选
Color类可以用色彩名字、RGBA值、HTML色彩格式等方式定义
	color(name)例如: Color ("grey")
    color(r,g,b,a) 例如: Color (190, 190, 190, 255)
    Color (rgbvalue) 例如: Color ("#BEBEBEFF")

(2) RGB色彩模式
在这里插入图片描述

图7

RGB色彩模式之外增加了第四维度: alpha通道
alpha通道表示不透明度,取值0-255 , 默认255
alpha通道值越大,不透明度越高, 255表示不透明

(3) pygame.Color类

pygame.Color.r 获得Color类的红色值r
pygame.Color. g 获得Color类的绿色值g
pygame.Color.b 获得Color类的蓝色值b
pygame.Color.a 获得Color类的不透明度值a
pygame. Color.normalize 将RGBA各通道值归一到0-1之间

(4) 色彩版

1.需求:根据小球移动状态修改游戏的背景颜色
2.设计:
	RGB颜色分别定义如下:             
        R:壁球水平距离     
        G:壁球垂直距离     
        B:壁球水平和垂直速度差别  
3.具体实现:
	R:水平距离/窗体宽度,取值0-255
    G:垂直距离/窗体高度,取值0-255
    B:最小速度/最大速度,取值0-255

在这里插入图片描述

图15

(5) 代码实现

import sys
import pygame

pygame.init()
# icon = pygame.image.load("biu.jpg")
# pygame.display.set_icon(icon)          #设置窗口图标
# Vinfo = pygame.display.Info()       #获取当前操作系统的屏幕尺寸
# size = width, height = Vinfo.current_w, Vinfo.current_h     #将系统的屏幕尺寸作为显示窗口的尺寸
size = width, height = 900, 600  # 设置屏幕的长度和宽度
speed = [1, 1]  # 设置移动速度[x,y]
BLACK = 0, 0, 0  # 设置背景颜色
# screen = pygame.display.set_mode(size)       #初始化显示窗口
screen = pygame.display.set_mode(size, pygame.RESIZABLE)  # 将屏幕设置为大小可调
# screen = pygame.display.set_mode(size,pygame.NOFRAME)         #将屏幕设置为无边框
# screen = pygame.display.set_mode(size,pygame.FULLSCREEN)       #将屏幕设置为全屏模式
pygame.display.set_caption("壁球游戏")  # 将窗口命名为“壁球游戏”
ball = pygame.image.load("ball.gif")  # 加载图片
ballrect = ball.get_rect()  # 返回一个覆盖图像的矩形Rect对象,载入图像的外切矩形
"""Rect对象有一些重要的属性,比如top、bottom、left、right表示上下左右
width、height表示宽度和高度"""
fps = 300
fclock = pygame.time.Clock()
still = False
bgcolor = pygame.Color("black")


def RGBChannel(a):
    return 0 if a < 0 else (255 if a > 255 else int(a))


while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            # 按左键改变壁球左右移动方向,按一次方向取反
            if event.key == pygame.K_LEFT:
                speed[0] = -speed[0]
            # 按上键改变壁球上下移动方向,按一次方向取反
            elif event.key == pygame.K_UP:
                speed[1] = -speed[1]
            elif event.key == pygame.K_ESCAPE:
                sys.exit("游戏结束!")
        elif event.type == pygame.VIDEORESIZE:
            size = width, height = event.size[0], event.size[1]
            screen = pygame.display.set_mode(size, pygame.RESIZABLE)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                still = True
                """当鼠标左键按下时,将控制壁球移动的变量设置为True,
                让壁球停止移动,因为后边是用if pygame.display.get_active() and not still:
                来控制壁球移动的,将still取反了"""
        elif event.type == pygame.MOUSEBUTTONUP:
            still = False
            if event.button == 1:
                ballrect = ballrect.move(event.pos[0] - ballrect.left, event.pos[1] - ballrect.top)
                """当鼠标按键释放时,让壁运动的相对球移动到鼠标所在的位置,同时让壁球继续运动
                move函数的参数是指两次距离,将两个位置的相对距离赋值给函数
                """
        elif event.type == pygame.MOUSEMOTION:
            if event.buttons[0] == 1:  # 当鼠标左键按下的时候
                ballrect = ballrect.move(event.pos[0] - ballrect.left, event.pos[1] - ballrect.top)
                """当鼠标左键处于按下状态并且在移动时,使壁球的图片跟随着鼠标一起移动"""

    if pygame.display.get_active() and not still:
        ballrect = ballrect.move(speed[0], speed[1])  # 在横轴和纵轴移动x,y像素
        """ 设置窗口感知,当显示为界面的时候,返回True,图标化的时候返回False
        这样设置如果将窗口最小化,壁球会停止运动
        当打开的时候壁球将会继续运动"""
    # 判断图像的边缘位置,如果碰到上下左右边缘,使其速度取反
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
        # sys.exit("Game Over!")
        if ballrect.right > width and ballrect.right + speed[0] > ballrect.right:
            speed[0] = - speed[0]
            """如果壁球的右边缘的坐标位置大于屏幕宽度,则让壁球改变运动方向"""

    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]
        # sys.exit("Game Over")
        if ballrect.bottom > height and ballrect.bottom + speed[1] > ballrect.bottom:
            speed[1] = - speed[1]

    bgcolor.r = RGBChannel(ballrect.left * 255 / width)
    bgcolor.g = RGBChannel(ballrect.top * 255 / height)
    bgcolor.b = RGBChannel(min(speed[0], speed[1]) * 255 / max(speed[0], speed[1], 1))

    screen.fill(bgcolor)  # 填充背景颜色
    screen.blit(ball, ballrect)
    """将一个图像绘制在另一个图像上,即将ball绘制到ballrect位置上。
    通过Rect对象引导对移动图像的绘制,让图像跟着外切矩形的移动而移动
    这样就形成了图像的移动"""
    pygame.display.update()  # 刷新屏幕,仅仅重新绘制窗口中有变化的地方,比flip函数速度更快,flip函数重新绘制整个窗口
    fclock.tick(fps)

(二) pygame图形绘制机制

(1) 图形绘制

pygame. draw
	向屏幕上制一些简单的图形,如直线、圆形、椭圆等
    任何一个图形绘制后,会返回一个矩形Rect类表示该形状
rect()	矩形		.polygon() 边形		.circle() 圆形
.ellipse()	椭圆形		.arc()	椭圆弧形		.line()	直线
.lines() 连续多线		.aaline) 无锯齿线
.aalines() 连续无锯齿线 

(2) Rect类

pygame.Rect
	表达一个矩形区域的类,用于存储坐标和长度信息
    pygame利用Rect类来操作图形/图像等元素
    四个参数:left、top、width、height
    Rect类提供了如下属性,返回一个数值或一个代表坐标的元组
    	x, y, w, h, size, width, height, top, left, tottom, right
        topleft, tottomleft, topright, bottomright, midtop, midleft, 
        midbottom, midright, center, centerx, centery
    Rect类提供了如下方法,用来操作Rect类:
    	.copy(), .move(), .inflate(), .clamp(), .clip(), union(), unionall(), 
        .fit() .normalize(), .contains(), .collidepoint(), .colliderect(), 
        .collidelist(), .collidelistall().collidedict(), .collidedictall()

(3) 矩形绘制

pygame.draw.rect(Surface, color, Rect, width=0)
Surface 矩形的绘制屏幕
color 矩形的绘制颜色
Rect 矩形的绘制区域
width=0 绘制边缘的宽度,默认为e,即填充图形
import pygame,sys

pygame.init()
size = widht, height = 800,500
screen = pygame.display.set_mode(size)
pygame.display.set_caption('图形绘制')
GOLD = 255, 251, 0
RED = pygame.Color('red')

r1rect = pygame.draw.rect(screen, GOLD, (100, 100, 200, 100), 5)
r2rect = pygame.draw.rect(screen, RED, (210, 210,200,100), 0)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    pygame.display.update()

(4) 多边形绘制

pygame.draw.polygon(Surface, color, pointlist, width=0)
Surface		 	多边形的绘制屏幕
color 			多边形的绘制颜色
pointlist		多边形顶点坐标列表
width-0 		绘制边缘的宽度,默认为e,即填充图形

(5) 圆形绘制

pygame.draw.circle(Surface, color, pos, radius, width=0)
Surface		 圆形的绘制屏幕
color 		 圆形的绘制颜色
pos			 圆形的圆心坐标
radius 		 圆形的半径
width=0 	 绘制边缘的宽度,默认为e,即填充图形

(6) 椭圆形绘制

pygame.draw. ellipse (Surface, color, Rect, width=0)
Surface 			椭圆形的绘制屏幕
color 				椭圆形的绘制颜色
Rect				椭圆形的绘制区域
width-0 			绘制边缘的宽度,默认为e,即填充图形

(7) 椭圆弧型绘制

pygame.draw.arc (Surface, color, Rect, start_angle, stop_angle, width=0)
Surface 	椭圆弧形的绘制屏幕
Color 		椭圆弧形的绘制颜色
Rect		椭圆弧形的绘制区域
start_angle, stop_angle 	弧形绘制起始和结束弧度值(横向右侧为0)
width=0 	绘制边缘的宽度,默认为e,即填充图形

(8) 直线绘制

pygame.draw.line (Surface, color, start_pos, end_pos, width=1)
Surface 	直线的绘制屏幕
Color 		直线的绘制颜色
start_pos, end-pos 		直线的起始和结束坐标
width=1 		直线的宽度,默认值为1

(9) 连续多线绘制

pygame.draw.lines (Surface, color, closed, pointlist, width=1)
Surface 	连续多线的绘制屏幕
Color 		连续多线的绘制颜色
closed 		如果为True,起止节点间自动增加封闭直线
pointlist	连续多线的顶点坐标列表
width=1 	连续多线的宽度,默认值为1

(10) 无锯齿先绘制

pygame. draw.aaline(Surface, color, start_pos, end_pos, blend=1)
Surface 	无锯齿线的绘制屏幕
Color 		无锯齿线的绘制颜色
start_pos, end_pos 		无锯齿线的起始和结束坐标
blend-1 		不为时,与线条所在背景颜色进行混合

(11) 连续无锯齿先绘制

pygame.draw.aalines(Surface, color, closed, pointlist, blend=1)
Surface 	连续无锯齿线的绘制屏幕
Color 		连续无锯齿线的绘制颜色
closed 		如果为True,起止节点间自动增加封闭直线
pointlist	连续无锯齿线的顶点坐标列表
blend-1 	不为e时,与线条所在背景颜色进行混合

(12) 代码实现

import pygame, sys
from math import pi

pygame.init()
screen = pygame.display.set_mode((600,400))
pygame.display.set_caption("Pygame图形绘制")
GOLD = 255, 251, 0
RED = pygame.Color('red')
WHITE = 255, 255, 255
GREEN = pygame.Color('green')

#r1rect = pygame.draw.rect(screen, GOLD, (100,100,200,100), 5)
#r2rect = pygame.draw.rect(screen, RED, (210,210,200,100), 0)

e1rect = pygame.draw.ellipse(screen, GREEN, (50,50,500,300), 3)
c1rect = pygame.draw.circle(screen, GOLD, (200,180), 30, 5)
c2rect = pygame.draw.circle(screen, GOLD, (400,180), 30)
r1rect = pygame.draw.rect(screen, RED, (170, 130, 60, 10), 3)
r2rect = pygame.draw.rect(screen, RED, (370, 130, 60, 10))
plist = [(295,170), (285,250), (260,280), (340,280), (315,250), (305,170)]
# l1rect = pygame.draw.lines(screen, GOLD, True, plist, 2)
al1rect = pygame.draw.aalines(screen, GOLD, True, plist, 2)
a1rect = pygame.draw.arc(screen, RED, (200,220,200,100), 1.4*pi, 1.9*pi, 3)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    pygame.display.update()

(三) pygame文字绘制机制

(1) 文字绘制

pygame.freetype
	向屏幕上绘制特定字体的文字
	文字不能直接print() ,而是用像素根据字体点阵图绘制
pygame.freetype
	pygame.freetype是绘制文字的增强方法,建议使用
	必须额外增加import引用,如下:
    	import pygame, sys 
   		import pygame.freetype

(2) Font类

pygame.freetype.Font(file, size=0)
file		字体类型名称或路径
size		字体的大小

(3) Font类的绘制方法(1)

Font.render_to(surf, dest, text, fgcolor=None,bgcolor=None, rotation=8, size=0)> Rect
	surf		绘制字体的平面, Surface对象
	dest		在平面中的具体位置, (x,y)
	text		绘制的文字内容
	fgcolor 	文字颜色
	bgcolor 	背景颜色
    rotation	逆时针的旋转角度,取值0-359,部分字体可旋转
    size		文字大小,赋值该参数将覆盖Font中的设定值
    Rect		返回一个Rect对象

(4) 系统中的字体

windows系统的字体路径
	C:\Windows\Fonts
        
字体文化的扩展名
	*.ttf   *.ttc

(5) 文字绘制机制简介

pygame.freetype
    								Font.render_to()
	pygame.freetype.Font
									Font.render()
    
	根据字体和字号生成一个Font对象		用Font对象的render*方法绘制具体文字


(6) 代码实现

import pygame,sys
import pygame.freetype

pygame.init()
size = width,height = 900,600
screen = pygame.display.set_mode(size)
pygame.display.set_caption("文字绘制")
GOLD = 255, 251, 0
f1 = pygame.freetype.Font('C:\Windows\Fonts\\msyh.ttc', 36)   # 微软雅黑
f1rect = f1.render_to(screen,(200,160),"生活是一场有去无回的旅行", fgcolor=GOLD, size=50)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    pygame.display.update()

(7) Font类的绘制方法(2)

Font.render(text, fgcolor=None, bgcolor=None,rotation=8, size=0) -> (Surface, Rect)
	text		绘制的文字内容
	fgcolor, bgcolor 		字体颜色、背景颜色
	rotation 		逆时针的旋转角度,取值0-359,部分字体可旋转
	size		文字大小,赋值该参数将覆盖Font中的设定值
	返回一个元组,包含Surface对象和Rect对象

(8) 代码实现

import pygame,sys
import pygame.freetype

pygame.init()
size = width,height = 900,600
screen = pygame.display.set_mode(size)
pygame.display.set_caption("文字绘制")
GOLD = 255, 251, 0

f1 = pygame.freetype.Font('C:\Windows\Fonts\\msyh.ttc', 36)   # 微软雅黑
f1surf,f1rect = f1.render("生活是一场有去无回的旅行", fgcolor=GOLD, size=50)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    screen.blit(f1surf, (200,160))
    pygame.display.update()


(四) pygame绘图机制原理精髓

(1) 理解pygame的两个重要类型

pygame. Surface			绘图层,或绘图平面,或图层
						用于表示图形、文字或图像的绘制效果
						与当前屏幕主图层可以并列存在
						如果不绘制在主图层上,则不会被显示

(2) 主图层

由pygame.diaplay.set_mode()生成的Surface对象
	size = width, height =  600, 500
	sceen = pygame.display.set_mode(size)
在主图层上绘制其他图层使用.blit()方法
	screen.blit(ball, ballrect)
    	ball --> pygame.Surface			ballrect --> pygame.Rect

(五) 壁球小游戏(文字版)

(1) 知识储备

需求:
	把小球改为一段文字,可以进行移动
从需求到实现的关键要素:
	文字移动:文字的移动绘制及刷新
    
PygameWallBallv 10.py采用render to()方法
PygameWallBallv 11.py采用render()方法

(2) 文字版part01

import pygame, sys
import pygame.freetype

pygame.init()
size = width, height = 600, 400
speed = [1,1]
GOLD = 255, 251, 0
BLACK = 0, 0, 0
pos = [230, 160]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Pygame文字绘制")
f1 = pygame.freetype.Font("C://Windows//Fonts//msyh.ttc", 36)
f1rect = f1.render_to(screen, pos, "世界和平", fgcolor=GOLD, size=50)
fps = 300
fclock = pygame.time.Clock()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    if pos[0] < 0 or pos[0] + f1rect.width > width:
        speed[0] = - speed[0]
    if pos[1] <0 or pos[1] + f1rect.height > height:
        speed[1] = - speed[1]
    pos[0] = pos[0] + speed[0]
    pos[1] = pos[1] + speed[1]

    screen.fill(BLACK)
    f1rect = f1.render_to(screen, pos, "世界和平", fgcolor=GOLD, size=50)
    pygame.display.update()
    fclock.tick(fps)

(2) 文字版part02

import pygame, sys
import pygame.freetype

pygame.init()
size = width, height = 600, 400
speed = [1,1]
GOLD = 255, 251, 0
BLACK = 0, 0, 0
pos = [230, 160]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Pygame文字绘制")
f1 = pygame.freetype.Font("C://Windows//Fonts//msyh.ttc", 36)
f1surf, f1rect = f1.render("吴常文", fgcolor=GOLD, size=50)
fps = 300
fclock = pygame.time.Clock()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    if pos[0] < 0 or pos[0] + f1rect.width > width:
        speed[0] = - speed[0]
    if pos[1] <0 or pos[1] + f1rect.height > height:
        speed[1] = - speed[1]
    pos[0] = pos[0] + speed[0]
    pos[1] = pos[1] + speed[1]

    screen.fill(BLACK)
    f1surf, f1rect = f1.render("吴常文", fgcolor=GOLD, size=50)
    screen.blit(f1surf, (pos[0], pos[1]))
    pygame.display.update()
    fclock.tick(fps)

作者:吴常文
出处:https://blog.csdn.net/qq_41405475
本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

猜你喜欢

转载自blog.csdn.net/qq_41405475/article/details/113823712