1、开始绘制图形需要先绘制一个窗口,创建一个pygame窗口,但是窗口并未交互。
1.1 pygame 有一个事件循环(event loop)不断在检查用户在做什么,如按键、移动鼠标或关闭窗口。要想保持pygame事件循环一直运行,需要使用while循环
import pygame pygame.init() screen = pygame.display.set_mode([640,480]) # 使用pygame窗口正常工作 import pygame pygame.init() screen = pygame.display.set_mode([640,480]) running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running =False pygame.quit()
2、在窗口中画图
2.1 如果希望让动画尽可能流畅,不必在每次对图形进行修改都更新显示,可以做很多修改后在“翻转”(flip)到图形的新版本。这样会一次显示所有的修改,而不会只显示画了一半的圆(或者其他)
2.2 当前屏幕与下一屏幕,做完下一屏的所有修改后,再翻转到下一屏,就能看到这些改变。
建立一个圆:2.3 :在哪个表面进行画圆 2.4 :用什么颜色来画 2.5: 在什么位置画 2.6:圆的大小 2.7 线宽
2.3.1:pygame 表面 :在缓冲区进行画图,然后“翻转显示表面”,来显示完全绘制的图像。
2.4.1:pygame颜色:[R,G,B] [255,255,255]
2.5.1 位置:对应X轴及对应Y轴
2.6.1 形状的大小:指定长宽,圆心,半径(left,top,width,height)
2.7.1 线宽 :0 代表整个填充,
# 在窗口中画一个圆 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) # 用白色背景填充窗口 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 pygame.quit()
# 在窗口的中心位置画圆 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) # 用白色背景填充窗口 pygame.draw.circle(screen,[0,255,0],[320,240],30,0) # 在中心位置画一个圆 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running =False pygame.quit()
# 在窗口画一个矩形 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) # 用白色背景填充窗口 pygame.draw.rect(screen,[0,0,255],[250,150,300,200],0) # 画一个矩形 # my_list =[250,150,300,200] # pygame.draw.rect(screen,[0,0,255],my_list,0) # 矩形的位置与大小可以是一个简单的的数字列表或元组 # my_rect= pygame.Rect(250,150,300,200) # pygame.draw.rect(screen,[0,0,255],my_rect,0) # 可以是一个pyganme 的 rect 对象 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running =False pygame.quit()
# 使用draw.rect 实现艺术创作 import pygame,sys,random pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) for i in range(100): width = random.randint(0,250) height = random.randint(0,100) left = random.randint(0,500) top = random.randint(0,400) pygame.draw.rect(screen,[0,0,0],[left,top,width,height],1) pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False pygame.quit()
# 用大量很小的矩形来画曲线 import pygame,sys import math pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) for x in range (640): y = int(math.sin(x/640.0 * 4 * math.pi)*200+240) # 计算每个点的y坐标(垂直坐标) pygame.draw.rect(screen,[0,0,0],[x,y,1,1],1) # 使用小矩形来画点 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.quit()
3、连接多个点
3.1 画线的表面,颜色,是否要将第一个点和最后一个点连接起来,使形状闭合(closed),正弦曲线不闭合(FALSE); 要连接点的列表;线宽
# 连接多个点 import pygame,sys import math pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) PlotPoints =[] for x in range (640): y = int(math.sin(x/640.0 * 4 * math.pi)*200+240) PlotPoints.append([x,y]) # 将各个点的x,y 的值添加至列表中 pygame.draw.lines(screen,[255,0,0],False,PlotPoints,2) # 使用pygame.draw.lines()画线 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.quit()
3.2 连接多个点
# 神秘图片 import pygame,sys pygame.init() 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 = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) pygame.draw.lines(screen,[255,0,0],True,dots,2) pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.quit()
4、图像
4.1 如需显示一个图像,需要将图像文件复制到保存python程序的同一位置上。这样程序运行时很容易找到这个文件,不然容易出错。
# 在pygame窗口中显示沙滩球图像 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") # 运用pygame.image.load()函数从硬盘加载一个图像,并命名为my_ball的对象my_ball 对象是一个表面,不过我们看不到这个表面,它只在内存中。我们唯一能看到的表面是显示表面,名为screen (第三行创建)。 screen.blit(my_ball,[100,100]) # 把my_ball表面复制到screen表面上,然后通过display.flip()调用显示使它可见 running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.quit()
my_ball 对象只是一个表面,我们看不到这个表面,它只存在内存中,我们需要用screen.blit(),将像素从一个表面复制或块移到另一个表面,这是将像素my_ball表面复制到screen表面。
术语:块移
4.2 改变它的位置,进行移动
import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") screen.blit(my_ball,[100,100]) pygame.display.flip() pygame.time.delay(2000) #时间的推移 screen.blit(my_ball,[250,100]) # 像素水平方向向右移动150 pygame.display.flip() # 调用函数pygame.display.flip()显示 running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.quit()
4.3 动画
4.3.1 计算机进行动画时,完成两个步骤 (1)在新的位置画出图形 (2) 把原来的图形擦掉(要“擦掉”某个东西,你实际要做的是把它‘盖住“),背景是白色的,所以必须用白色覆盖沙滩球原来的图像。
# 动画,将原位置的图像擦掉 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") screen.blit(my_ball,[100,100]) pygame.display.flip() pygame.time.delay(2000) screen.blit(my_ball,[250,100]) pygame.draw.rect(screen,[255,255,255],[50,50,200,200],0) # python中擦掉图形,采用是在其位置重新画图形覆盖的办法。 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.quit()
4.4 更流畅的动画
# 更流畅的动画 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") x = 50 y = 50 screen.blit(my_ball,[x,y]) # 使用x,y 变量表示球行的初始位置变量 pygame.display.flip() for i in range (100): # 对球进行100次移动循环 pygame.time.delay(20) # 每隔20的延迟就开始下一步操作 pygame.draw.rect(screen,[255,255,255],[x,y,90,90],0) # 根据球行的初始位置,进行初始位置覆盖,然后跟着变量进行移动 x = x+5 # 将球的初始位置进行每次增加5个位的移动 screen.blit(my_ball, [x, y]) # 球的新位置表面,进行复制到screen表面 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.quit()
4.5 让球进行反弹
1、需知道球什么时候碰到窗口边界,然后让它朝反方向移动。左边界:只需检查球的位置是不是等于0(<0);右边界:要看球的边界是不是在窗口的右边界上,但是球的位置是按左上角位置定的,需减去球的宽度。
2、我们希望球永远来回反弹(直到我们关闭pygame窗口)所以需要将显示球的代码放进循环内部。
3、设置一个新的变量 :来确定球移动的速度。
# 让沙滩球反弹 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") x = 50 y = 50 x_speed = 10 screen.blit(my_ball,[x,y]) # 使用x,y 变量表示球行的初始位置变量 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.time.delay(20) # 每隔20的延迟就开始下一步操作 pygame.draw.rect(screen,[255,255,255],[x,y,90,90],0) # 根据球行的初始位置,进行初始位置覆盖,然后跟着变量进行移动 x = x+x_speed if x > screen.get_width()-90 or x < 0 : # 球的直径为90,检查球是否在窗口边界上 x_speed = -x_speed screen.blit(my_ball, [x, y]) # 球的新位置表面,进行复制到screen表面 pygame.display.flip() pygame.quit()
# 让球在2D空间反弹 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") x = 50 y = 50 x_speed = 10 y_speed = 10 screen.blit(my_ball,[x,y]) # 使用x,y 变量表示球行的初始位置变量 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.time.delay(20) # 每隔20的延迟就开始下一步操作 pygame.draw.rect(screen,[255,255,255],[x,y,90,90],0) # 根据球行的初始位置,进行初始位置覆盖,然后跟着变量进行移动 x = x+x_speed y = y+y_speed if x > screen.get_width()-90 or x < 0 : # 球的直径为90,检查球是否在窗口边界上 x_speed = -x_speed if y > screen.get_height()-90 or y <0 : y_speed = -y_speed screen.blit(my_ball, [x, y]) # 球的新位置表面,进行复制到screen表面 pygame.display.flip() pygame.quit()
3.1 让球的速度慢下来(1):可以减少速度变量(speed) ; (2) 增加时间延迟。
4.6 让球进行翻转
当球在最右边的时候,让位置为0,重新从最左边开始
# 让球进行翻转 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") x = 50 y = 50 x_speed = 10 y_speed = 10 screen.blit(my_ball,[x,y]) # 使用x,y 变量表示球行的初始位置变量 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.time.delay(20) # 每隔20的延迟就开始下一步操作 pygame.draw.rect(screen,[255,255,255],[x,y,90,90],0) # 根据球行的初始位置,进行初始位置覆盖,然后跟着变量进行移动 x = x+x_speed if x > screen.get_width() : # 如果球在最右边,则重新到左边开始 x =0 screen.blit(my_ball, [x, y]) # 球的新位置表面,进行复制到screen表面 pygame.display.flip() pygame.quit()
4.7 课后习题操作
# 习题2 让 车子运行 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("doc1.gif") x = 50 y = 50 x_speed = 10 y_speed = 10 screen.blit(my_ball,[x,y]) # 使用x,y 变量表示球行的初始位置变量 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.time.delay(20) # 每隔20的延迟就开始下一步操作 pygame.draw.rect(screen,[255,255,255],[x,y,90,90],0) # 根据球行的初始位置,进行初始位置覆盖,然后跟着变量进行移动 x = x + x_speed screen.blit(my_ball, [x, y]) pygame.display.flip() pygame.quit() # 习题3-1 将time.delay()参数跳整,参数越小,速度越快 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") x = 50 y = 50 x_speed = 10 y_speed = 10 screen.blit(my_ball,[x,y]) # 使用x,y 变量表示球行的初始位置变量 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.time.delay(10) # 每隔10的延迟就开始下一步操作 pygame.draw.rect(screen,[255,255,255],[x,y,90,90],0) # 根据球行的初始位置,进行初始位置覆盖,然后跟着变量进行移动 x = x+x_speed y = y+y_speed if x > screen.get_width()-90 or x < 0 : # 球的直径为90,检查球是否在窗口边界上 x_speed = -x_speed if y > screen.get_height()-90 or y <0 : y_speed = -y_speed screen.blit(my_ball, [x, y]) # 球的新位置表面,进行复制到screen表面 pygame.display.flip() pygame.quit() # 习题3-2 将time.delay()参数跳整,参数越小,速度越快 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") x = 0 y = 0 x_speed = 10 y_speed =x_speed * 1.5 screen.blit(my_ball,[x,y]) # 使用x,y 变量表示球行的初始位置变量 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.time.delay(100) # 每隔10的延迟就开始下一步操作 pygame.draw.rect(screen,[255,255,255],[x,y,90,90],0) # 根据球行的初始位置,进行初始位置覆盖,然后跟着变量进行移动 x = x+x_speed y = y+y_speed if x > screen.get_width()-140 or x < 0 : # 球的直径为90,检查球是否在窗口边界上 x_speed = -x_speed if y > screen.get_height()-90 or y <0 : y_speed = -y_speed screen.blit(my_ball, [x, y]) # 球的新位置表面,进行复制到screen表面 pygame.display.flip() pygame.quit() # 习题4 让球在隐形的墙或地板上反弹 import pygame,sys pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) my_ball = pygame.image.load("beach_ball.png") x = 50 y = 50 x_speed = 10 y_speed = 10 screen.blit(my_ball,[x,y]) # 使用x,y 变量表示球行的初始位置变量 pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running=False pygame.time.delay(20) # 每隔20的延迟就开始下一步操作 pygame.draw.rect(screen,[255,255,255],[x,y,90,90],0) # 根据球行的初始位置,进行初始位置覆盖,然后跟着变量进行移动 x = x+x_speed y = y+y_speed if x > screen.get_width()-250 or x < 0 : x_speed = -x_speed if y > screen.get_height()-210 or y <0 : y_speed = -y_speed screen.blit(my_ball, [x, y]) # 球的新位置表面,进行复制到screen表面 pygame.display.flip() pygame.quit() # 习题5 import pygame,sys,random pygame.init() screen = pygame.display.set_mode([640,480]) screen.fill([255,255,255]) for i in range(100): width = random.randint(0,250) height = random.randint(0,100) left = random.randint(0,500) top = random.randint(0,400) pygame.draw.rect(screen,[0,0,0],[left,top,width,height],1) pygame.display.flip() pygame.time.delay(30) running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False pygame.quit()