上节中在介绍 pygame的时候我们已经看到了如何绘制一个窗口并且显示图片动画
那么我们一步步来学习下 各个环节。
绘制一个窗口
我们在 Geany 中编写一个 showWin.py 文件
功能: 只显示一个窗口并且加入一个关闭窗口的事件,窗口的标题显示为 hello world!
绘制一个窗口的步骤
Step1: import pygame,sys
使用之前必须导入 pygame 模块,这里导入 sys 模块是因为 程序结束需要使用 sys.exit()
Step2: from pygame.locals import *
这行会导入 pygame下面的其他模块, 这样方便我们直接使用
Step3: pygame.init()
这个必须在 导入之后立马进行调用 初始化pygame下各个对象
Step4:win = pygame.display.set_mode(size) 获取 surface 对象
这个方法返回的是一个 pygame.Surface 对象 ,可以理解为 AWT 中的 frame
Surface对象是表示的一个矩形2D图像的对象,我们可以通过pygame函数来改变surface来显示到窗口
pygame.display.set_mode 方法接收一个 元组变量用于控制窗口的 宽和高 ,注意是一个元组变量而不是两个数字
这里有一个元组的使用方法:
并列写在一行的数字组成了元组
例如 x,y,z
或者 size = x,y,z=1,2,3
或者 size = 100,200
Step5: pygame.display.set_caption('hello world !')
设置标题 又是 pygame.display.set_XXX
Step6: for event in pygame.event.get():
pygame.event.Event 对象 是描述事件 ,它在 event 模块中 pygame.event
通过 pygame.event.get() 可以知道 从最后一次 该函数被调用之后哪些事件已经发生了。
Step7: if event.type == QUIT:
事件的属性 ,其中 type属性标志哪类事件发生,QUIT 事件定义在 pygame.locals 中
Step8: pygame.quit()
确保 这个quit的调用再 exit() 之前,这个如同C++中的析构函数一样
Step9: pygame.display.update()
就是把surface对象不断地显示到屏幕,一旦 surface 对象更新了就会不断的刷新
动画
动画的绘制遵循如下图:
学过java的swing知道 绘制的窗口叫 frame
pygame产生动画的原理就是不断地刷新图像,
比如我们用一个小图片来移动,我们只要把每一次图片放在不同位置然后反复刷新即可,这也是动画产生的原理
以一定的速度不停切换图片达到
像素坐标
Pixel Coordinates : 像素坐标
我们知道每一个窗口都由 像素组成 ,比如上面的例子中 是 400*300
下面是一个 8*8 的“”
这样一来屏幕上的点 就是一个 (x,y) 可以使用 元组来表示
元组我们之前的章节已经学过,你会发现它和笛卡尔坐标系中的点写法是一致的
Surface 对象
surface 对象,变现为一个 矩形的 2D图像 。也是由像素组成的。
可以通过改变像素来达到更改图片的目的
在 surface 对象上绘制的控件 在 pygame.display.update() 调用之后 被显示出来
颜色
这个就比较熟悉了,三原色 r,g,b 因此可以使用 元组来表示
pygame.Color 对象
可以构造一个 pygame.Color对象来表示颜色
颜色的透明度
surface并不能直接用颜色的透明度,可以通过,
another_surface = surface.convert_alpha()
来获取一个surface,然后 进行操作
矩形对象
坐标系中表示一个矩形 需要 两方面信息 : 左上角顶点坐标以及矩形的 长宽 , 这些信息仍然可以通过 元组来表示
可以使用 pygame.Rect 来构造一个矩形对象
复习下前面的知识: 想查看这个对象的属性怎么办?
使用 dir() 函数就可以了,我们可见常用的 属性 :
其中 left 和 right 以及 x和 y 表示了顶点的坐标
height ,h 以及 width ,w 表示了 宽和长
全部属性如下:
绘制二维几何图形
绘制图形使用 pygame.draw.方法名 来进行图形的绘制
其中 方法名我们可以使用 dir()来查看下 pygame.draw , 可以看到属性还是比较少的 ,
例如画线段 line
画圆 : circle
矩形: rect
多边形: polygon
多边形 polygon
pygame.draw.polygon(surface , color ,pointList ,width )
其中 surface 表示在哪个 surface 对象上进行绘制
color 表示 用什么样的颜色线段
pointList: 可以是一个元组或者是一个 点的列表 ,
多边形的绘制通过在pointList指定点列表的两点之间绘制线段
如果一个点只有一个坐标值将不会进行绘制
width :这个参数是可选的,描述了多边形的轮廓,如果不指定值,那么就是整个多边形将被color给填充
如果指定了值,表示了线段的粗细,但是此时多边形不会被颜色填充
意思就是将pointList中的点用color颜色宽度为width的线在surface上画多边形,当不添加width时,图形为填充的
线段 line
pygame.draw.line(surface , color ,start_point,end_point,width )
width 表示了线段的粗细
圆 circle
pygame.draw.circle(surface , color ,center_point,radius,width )
和上面一样,如果 width 为空,或者 传入一个 0 ,那么这个圆将会被指定的颜色填充
如果传入一个指定的值,那么圆将用 width 指定的线段 粗细程度画圆,但是没有颜色填充
拉伸的圆 ellipse
pygame.draw.ellipse(surface , color ,bounding_rectangle,width )
绘制一个拉伸的圆也就是椭圆,这样的圆有一个最小的外接矩形 , 可以使用前面的 pygame.Rect 对象 表示,
矩形 rect
pygame.draw.rect(surface , color ,rectangle_tuple,width )
pygame.Surface对象的fill方法
该方法就是填充用的,传入一个颜色值将颜色填充到整个对象
pygame.PixelArray
用来获取图像每一个像素点,返回一个像素数组,每一个值都是一个元组可以更改每一个像素的颜色
创建这个对象的时候,就收一个 surface 对象,当创建这个 surface 对象的 像素数组 时候,会锁定这个 surface 对象
锁定的 surface 对象,可以继续调用 各种绘制函数,但是不能有类似 PNG或JPG等图片用 bilt()函数进行绘制
例如 上节中 【pygame登场】 中有一行代码: screen.blit(ball, ballrect)
表示将当前的 图片复制到了矩形对象中
也就是 图片移动的原理: 不断重新绘制矩形的坐标区域,然后将静态的图片复制到新的矩形区域中去
一旦我们获取了 像素点之后,是不能 调用这个 bilt 函数的
可以通过 surface 对象的 get_locked() 方法查看 这个 surface 对象是否被锁定
实践
通过上面的知识我们创作一幅画,如下图
代码片段:
showWin.py
import pygame,sys
from pygame.locals import *
pygame.init()
size=400,300
win = pygame.display.set_mode(size)
pygame.display.set_caption('hello world !')
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
draw.py
import pygame , sys
from pygame.locals import *
pygame.init()
DISPLAYSURF = pygame.display.set_mode((500,400),0,32)
pygame.display.set_caption('Drawing')
# colors
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE= (0,0,255)
# background
DISPLAYSURF.fill(WHITE)
_draw = pygame.draw
#polygon
_draw.polygon(DISPLAYSURF,GREEN,((146,0),(291,106),(236,277),(56,277),(0,106)))
#line
_draw.line(DISPLAYSURF,BLUE,(60,60),(120,60),4)
_draw.line(DISPLAYSURF,BLUE,(120,60),(60,120))
_draw.line(DISPLAYSURF,BLUE,(60,120),(120,120),4)
#circle
_draw.circle(DISPLAYSURF,BLUE,(300,50),20,0)
#ellipse
_draw.ellipse(DISPLAYSURF,RED,(300,250,40,80),1)
#rect
_draw.rect(DISPLAYSURF,RED,(200,150,100,50))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()