第十六章 图形
(1)寻求帮助——Pygame
(2)Pygame窗口
注意这里需要用到while做一个事件循环,否则pygame窗口没有办法关闭,并且窗口会处于死机状态。
(3)在窗口中画图
从画圆的几个属性,我们可以展开来学习:
(1)Pygame表面(surface)
可以有多个表面,其中这里用到的是screen。另外显示表面是双缓冲的(double-buffed),我们可以在缓冲区里画圆,然后“翻转”显示表面,以显示绘制好的图像以节省时间。
(2)Pygame的颜色
在自然课中我们知道,混合光的三原色(红绿蓝)可以得到任何颜色;在计算机中,我们也利用类似的方法,将不同程度的红绿蓝,对应数字0~255,由一个包含了三个整数的列表给出颜色:
1️⃣如果所有数字都是零,那么颜色全无→全黑
2️⃣如果三个都是255,那就是三种颜色以最大亮度混合在一起→全白
3️⃣如果是三个颜色都一样,如[155,155,155],你就会得到某种灰度
4️⃣Pygame提供了一个命名颜色的列表,可以先增加以下代码:
from pygame.color import THECOLORS
然后需要用到时可以这样:
pygame.draw.circle (scree, THECOLORS["red"], [100,100], .....)
(3)Pygame的位置——屏幕坐标
x轴:水平方向
y轴:垂直方向
假如说我们要将圆画在(640,480)大小的屏幕中间,可以将圆心放在(320,240)。
(4)形状大小
使用Pygame的draw函数画图像时,必须指定形状的尺寸。对于圆来说就是半径,对于另外的图形,以rect(方形)为例,则必须指定长和宽等其他尺寸:
Rect(left, top, width, height)
方形(距离x轴长度,距离y轴长度,长,宽)
画图时,可以直接指定,也可以将矩形的位置和大小封装到列表里:
my_list = [250, 150, 300, 200]
pygame.draw.rect(screen, [255,255,255], my_list, 0)
(5)线宽(线的宽度)
假如线宽=0:默认将整个图案填充满;
假如线宽=2或其他数字:给图案描边。
(6)让Python生成现代艺术:
另外,可以利用THECOLORS,随机生成里面的颜色,制作一幅彩色的现代艺术:
(4)单个像素
有时候我们不需要生成整个图像,只需要一个个的点或像素,我们就要像其他方法去解决,例如下面要画一个正弦曲线,其中一种解决方式是画很小的圆或矩形:
注意到这里线宽必须为1,因为为0的话,就什么都没有了。
连接多个点
我们可以发现,上面的结果是零散的、并不是完整的一条曲线,这是因为我们只是模拟正弦函数的位置,用一个一个像素点去画的。要填充间隔,其中一个方法是:
pygame.draw.lines()
它需要五个参数:
(1)划线的表面(surface)
(2)颜色(color)
(3)是否需要画另一条线使最后一个点与第一个点连接,使形状闭合(closed)
(4)要连接的点的列表(list)
(5)线宽(width)
所以,我们上面可以加上:
pygame.draw.lines(screen, [0,0,0], false, plotPoints, 1)
连接更多的点
我们还可以通过描点来画图,下面就是一个游戏例子,让我们看看将这些点连起来之后,会变成什么形状吧!
把下面的坐标打到dots列表中,注意缩进;另外假如你赶时间,可以直接粘贴进去,但最好还是打一下,巩固一下列表输入的方法:
[221,432], [225,331], [133,342], [141,310], [51,230], [74,217], [58,153], [114,164], [123,135], [176,190], [159,77], [193,93], [230,28], [267,93], [301,77], [284,190], [327,135], [336,164], [402,153], [386,217], [409,230], [319,310], [327,342], [233,331], [237,432]
逐点绘制
这里介绍一下只需绘制一个点的方法:
screen.set_at([x,y], [0,0,0])
(5)图像
以上的绘图方法只是制作图形的一种方式,还有其他获取图形的方法,其中最简便的就是利用pygame自带的image函数,将图片作为一个引入进来:
(1)在同一个文件夹内放进一张图片(例:ball.jpeg)
(2)在screen.fill后面加上这三行代码:
my_ball = pygame.image.load("ball.jpeg")
screen.blit(my_ball, [50,50])
pygame.display.flip()
(6/7)动起来——制作动画
既然是球,那么假如它不能动,必将失去很多乐趣。现在,我们就让它动起来吧!
在计算机中,制作一个动画,需要两个步骤:
(1)在新位置上画出图像
(2)把原来的图形擦掉
那么怎么擦掉原来的图形呢?我们在上面加上以下代码:
pygame.time.delay(2000)
screen.blit(my_ball, [150, 50])
pygame.draw.rect(screen, [255,255,255], [45,45,100,100], 0)
pygame.display.flip()
注意,这里我们只是简单地用了白色的背景覆盖住了原来的图片。假如背景不是白色,或是稍微复杂点的其他图案,则需要用其他方法解决。
(8)更流畅的动画
我们在原动画代码上进行加工,使之更为流畅:
(9)让球反弹
分解一下“反弹”动作,就是:检测图片右边缘是否在窗口右边界上,若是,则反方向前进。
进一步分析,我们希望:
(1)检测是否碰到边缘:使用screen.get_width()方法(检测图片右上角的距离)实现。检测边缘比较复杂,我们分为“左边碰到”和“右边碰到”两种情况:
(1)左边碰到:非常简单,直接用横坐标x<0来检测;
(2)右边碰到:判断依据是图片的右边界是否移动到了窗口边缘。不过,图片的位置x是按左边缘算的,所以我们用get_width()方法得出的距离,必须先减去图片的宽度(100),才能跟x进行比较。
(2)图片在边缘来回反弹,可以用while循环实现,直到点击退出才退出反弹;
(3)图片有加速和减速效果,可以设置变量speed,控制球的位置是+5还是+10。
新代码如下:
接下来,我们也希望它不要只在一条直线上反弹,而是在垂直的方向上也有变化。这时候,我们可以增加多一个变量y_speed,用以设置垂直方向的速度:
(10)让球在窗口滑动
这个效果是这样的:当球碰到了窗口边缘,不是反弹,而是在另一边重新出现,呈现一种“滑动”的效果。
具体过程略,思路:先实现只有x轴的情况,然后再实现x与y轴同时反弹。
你学到了什么?
(1)如何使用Pygame
(2)如何创建图形窗口,并画一些形状
(3)如何设置颜色、线宽等属性
(4)如何复制图像到窗口
(5)如何完成图像动画,并让其“反弹”、“翻转”
动手试一试
(1)使用help文档,获取pygame画其他形状的方式:
其实非常简单,只需要在交互模式下输入这两行代码:
>>> import pygame
>>> help()
就迎刃而解啦:
(2)试着修改示例程序的图像:
只需将123.jpg换成同名文件的不同图像即可。
(3)试着改变x_speed和y_speed:体验不同的速度。
(4)试着设置一堵隐形的“墙”,让图片在“墙”上反弹:
将get_width() - 100 的数值改变(如变为 - 200)即可
(5)修改“现代艺术”代码,将pygame.display.flip移到增加while循环,增加delay延迟,看看会发生什么:
小结
作为暑假末尾的课程,这节课学的很舒心,基本的框架逐渐上手,举一反三更是能够极大地帮助回忆以前的所学。学习从来不是一蹴而就的事情,继续加油~