学了python,想做游戏?一起学习pygame模块
程序员文章站
2022-03-16 08:42:01
...
欢迎关注我的公众号【次烦】
基本结构
先上代码,然后解释
#导入pygame和sys
import pygame
import sys
#导入pygame里面的常量(QUIT等)(不这样导入的话,在使用时就需要加上pygame. ,如pygame.QUIT)
from pygame.locals import *
#初始化,调用pygame的任何函数之前都要确保调用了这个函数(后面会详解)
pygame.init()
#创建窗口的Pygame.Surface对象,传入的参数(400,300)为窗口的宽高
screen = pygame.display.set_mode((400,300)) #screen接受此函数返回的Surface对象
#设置窗口顶部的标题名称
pygame.display.set_caption('hello world')
#设置一个死循环作为整个游戏的主体,只有当遇到break或者sys.exit()时才会终止游戏(如果循环在一个函数里面,使用return语句也可以退出训话并退出函数的执行)
while True: #游戏的主循环,执行三件事-处理事件,更新游戏状态(变量),在屏幕上绘制游戏状态
#检测键盘或鼠标事件
#当用户按下一个键或者动用鼠标等时,Pygame库就会创建一个pygame.event.Event对象来记录这个动作,也就是事件
#Event对象存在于event模块中(pygame.event)
#我们可以调用pygame.event.get()函数来搞清楚发生了什么事件,此函数返回pygame.event.Event对象的一个列表
#此列表包含上次调用pygame.event.get()函数之后所发生的的所有事件(如果没有调用,返回的就是从程序开始记录的所有事件
for event in pygame.event.get(): #如果没有事件,返回的就是一个空白的列表,则循环不会进行
#Event对象的属性type,用于表示对象为什么类型的事件
if event.type == QUIT: #如果Event对象是一个QUIT事件。就执行下列语句
pygame.quit() #pygame.quit()是和pygame.init()相反的函数,此函数会使pygame库停止工作
sys.exit() #sys.exit()退出程序
#此函数将pygame.display.set_mode()所返回的Surface对象绘制到屏幕上
pygame.display.update()
#Surface对象是表示一个矩形的2D图像的对象,可以通过调用函数改变Surface对象的像素,然后再绘制到屏幕上
#窗口的边框,标题栏和按钮不是Surface对象的一部分
#对于pygame.display.set_mode()返回的Surface对象叫做显示Surface
#绘制到Surface上的任何内容,当调用pygame.display.update()函数时,都会显示到窗口上
#在一个Surface上绘制(在计算机内存中修改Surface)其他的Surface 比 在屏幕上绘制所有的Surface(修改屏幕像素)要快
pass
- 首先
import pygame
和import sys
导入模块
导入sys模块主要用于退出程序(见后面的sys.exit()
) -
from pygame.locals import *
导入locals里面的一些常量 -
pygame.init()
用于初始化pygame(必须有,不然会报错) -
screen = pygame.display.set_mode((400,300))
此函数会返回一个窗口的Surface对象(由这里的变量screen接收),里面的(400,300)为窗口的大小(必须是元组形式,这个元组告诉set_mode()函数要创建一个宽度和高度分别为多少像素的窗口)
在pygame中,surface(外观)是屏幕的一部分,每个元素(如下面的图像,字体等)都是一个surface,display.set.mode()返回的surface表示整个游戏窗口
-
pygame.display.set_caption('hello world')
此函数用于设置窗口的标题(就是窗口左上角的那个文本) - 游戏主循环
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
-
while True:
设置一个死循环(即让游戏界面不会关闭(前提是没有其他指令让它关闭)) -
for event in pygame.event.get():
遍历Event对象,每当用户按下按键或者动用鼠标等类似行为后,pygame都会创建一个Event对象来记录,这些对象都储存的pygame.event模块中,此时可以使用它的get()方法来获取event中储存的所有Event对象(严格来说是自上次调用get()方法后里面新增的所有Event对象) -
if event.type == QUIT:
,type是event的一个属性,当鼠标点击右上角的红叉按钮时,产生的Event对象的type属性就是QUIT (locals的一个常量,因为我们把所有的常量都导入了,所以可以直接使用) -
pygame.quit()
和sys.exit()
结合上面的语句,当用户单击关闭按钮,就会执行这两个语句,pygame.quit()
使pygame代码库停止工作(虽然程序退出之前会自动关闭pygame,但是在IDEL中有一个bug,如果一个pygame程序在调用pygame.quit()
之前就终止了,就会导致IDEL挂起);sys.exit()
表示的就是退出程序了 -
pygame.display.update()
会把pygame.display.set_mode((400,300))
返回的Surface对象绘制到屏幕,这里让它每执行一次循环就绘制一次(想要绘制其他Surface,需要将要绘制的Surface复制到set_mode)创建的Surface(称为显示Surface)上,然后用update()来绘制显示Surface)
颜色与绘制
代码
import pygame
import sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((500,400),0,32)
pygame.display.set_caption("Draw")
#设置颜色
Black = (0,0,0)
White = (255,255,255)
Red = (255,0,0)
Green = (0,255,0)
Blue = (0,0,255)
#对Surface对象进行颜色填充
screen.fill(White)
#绘制多边形
#pylygon(surface,color,pointlist,width)pointlist参数是一个元组或者点的列表,即多边形的顶点,width为多边形边的宽度,若为0或者不填
pygame.draw.polygon(screen,Green,((146,0),(291,106),(236,277),(56,277),(0,106)))
#画线,参数为 surface,color,起始位置,终止位置,粗细
pygame.draw.line(screen,Blue,(60,60),(120,60),4)
pygame.draw.line(screen,Blue,(120,60),(60,120))
pygame.draw.line(screen,Blue,(60,120),(120,120),4)
#画圆,参数为surface,color,圆心,半径,边粗细(0填充)
pygame.draw.circle(screen,Blue,(300,50),20,0)
#画椭圆,参数为surface,color,边界矩形(以矩形的位置来画椭圆),边粗细
pygame.draw.ellipse(screen,Red,(300,250,40,80),1)
#画矩形,参数为surface,color,矩形(左上角x坐标,左上角y坐标,宽,高),边粗细
pygame.draw.rect(screen,Red,(200,150,100,50))
#创建Surface对象的pygame.PixArray对象。此对象创建后,将锁定该Surface对象,即不能在上面绘制图像(png,jpg之类)
pixobj = pygame.PixelArray(screen)
pixobj[480,380] = Black #PixelArray对象创建后,就可以根据坐标改变对应坐标的像素的颜色
pixobj[482,382] = Black
pixobj[484,384] = Black
pixobj[486,386] = Black
pixobj[488,388] = Black
#删除此对象,解除Surface对象的锁定
del pixobj
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
#此函数只能将pygame.display.set_mode()创建的Surface对象显示到屏幕上
#要想显示其他Surface对象上的图像显示到屏幕上,需要使用blit方法将之复制到 显示Surface对象上
pygame.display.update()
-
颜色,pygame里面的颜色用元组来表示,里面的三个值为rgb值,如(0,255,255)表示的就是绿色,也可以创建一个
pygame.Color()
对象,如White = pygame.Color(255,255,255)
; -
矩形区域,pygame有两种方式表示矩形区域,第一种是四个整数的元组,依次表示矩形的左上角x,y坐标,宽度,高度,如(0,0,100,100)表示的就是左上角坐标为(0,0),宽高都为100的矩形,第二种方法是创建一个
pygame.Rect()
对象,如myrect =pygame.Rect(0,0,100,100)
screen.fill(White)
-
pygame.draw.polygon(screen,Green,((146,0),(291,106),(236,277),(56,277),(0,106)))
表示在screen
上面画多边形,颜色为Green
,多边形的顶点分别为((146,0),(291,106),(236,277),(56,277),(0,106))
,边粗细为0(即填充) -
pygame.draw.line(screen,Blue,(60,60),(120,60),4)
表示在screen
上画一条颜色为Blue
,起点坐标为(60,60)
,终点坐标为(120,60)
,4
像素粗的线 -
pygame.draw.circle(screen,Blue,(300,50),20,0)
表示在screen上画一个颜色为Blue,圆心坐标为(300,50),半径为20,的一个圆(最后的0表示颜色填充) -
pygame.draw.ellipse(screen,Red,(300,250,40,80),1)
表示在screen
上画一个在矩形(300,250,40,80)
内的最大椭圆,边粗细为1
-
pygame.draw.rect(screen,Red,(200,150,100,50))
表示在screen
上画一个颜色为Red
的矩形(300,250,40,80)
,因为粗细参数省略,所以默认填充 -
设置单个像素的颜色,没有单个的函数来设置单个像素的颜色,除非使用
pygame.draw.line()
函数设置起点与终点相同(这样很慢),一般设置单个像素的方法如下 -
pixobj = pygame.PixelArray(screen)
创建(screen的)Surface对象的一个pygame.PixelArray对象(创建这个对象后,将会锁定Surface对象,即不能在Surface对象上添加PNG/JPG这种图像,要解锁后才能添加) -
pixobj[480,380] = Black
在PixelArray对象创建完成后,就可以根据坐标索引来更改相应位置像素的颜色了
PS:pygame中从左往右为x轴正方向,从上往下为y轴正方向,原点为左上角 -
del pixobj
删除这个PixelArray对象,Surface的锁定也就去掉了(就可以在Surface上绘制图像了)
动画效果
import pygame
import sys
from pygame.locals import *
pygame.init()
FPS = 30 #用于表示帧速率或刷新速率(程序每秒钟绘制的图像的数目)
#pygame.time.Clock对象可以确保程序以某一个最大的FPS运行(Clock对象在游戏循环的每一次迭代上都会设置一个小暂停,让程序运行不那么快)
fpsClock = pygame.time.Clock()
screen = pygame.display.set_mode((400,300),0,32)
pygame.display.set_caption('Animation')
White = (255,255,255)
#图像,也叫精灵 sprite,pygame能够从png,jpg,GIF,bmp图像文件中,将图像加载到Surface对象上
#猫的图像储存在与此文件同一个目录下,要加载这个图像文件,需要传递图像的名称及路径传递给下面的函数
#pygame.image.load()函数将返回一个Surface对象(后面会用另一个函数将此Surface绘制到显示Surface上)
catImg = pygame.image.load('cat.png') #catImg就是装着cat的一个Surface对象
catx = 10 #用于记录绘制的图像左上角的x坐标
caty = 10 #用于记录绘制的图像左上角的y坐标
direction = 'right'
while True:
screen.fill(White)
if direction == 'right':
catx += 5
if catx == 280:
direction = 'down'
elif direction == 'down':
caty += 5
if caty == 220:
direction = 'left'
elif direction == 'left':
catx -= 5
if catx == 10:
direction = 'up'
elif direction == 'up':
caty -= 5
if caty == 10:
direction = 'right'
#使用blit方法将catIMG复制到screen上,两个参数分别为 要复制的Surface对象 和 复制到的位置左上角坐标
screen.blit(catImg,(catx,caty))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
#在update函数之后掉用Clock对象的tick方法
#tick方法会根据前一次调用tick方法到本次调用的时间来计算需要暂停多长时间(来满足FPS需求)
fpsClock.tick(FPS)
-
FPS = 30
创建一个变量用于设置帧速率,后面会用到(帧速率就是程序每秒钟绘制的图像数目(将多个图像连续播放就可以实现动画效果)) -
fpsClock = pygame.time.Clock()
创建一个pygame.time.Clock
对象,。它可以帮助我们让程序以一个最大的帧速率运行(此对象会在每一次循环中设置一个小小的暂停,以达到每秒钟指定次数循环的目的) -
catImg = pygame.image.load('cat.png')
加载图像,此函数返回一个Surface对象(图像已经绘制到这个Surface对象上面了),参数就是图像的名称(相对路径,绝对路径都行) -
screen.blit(catImg,(catx,caty))
将带有图像的Surface对象复制到显示Surface(也就是screen
)上,(catx,caty)是要绘制到screen
上的坐标(图像Surface左上角坐标),因为上面写了判断语句,所以每次循环,坐标都会发生变化,使用blit()
方法绘制的图像位置也就不同,就呈现出动画的效果了 -
pygame.display.update()
,上面将带有图像的Surface对象绘制到显示Surface上面后,调用此函数就也可以将图像绘制到屏幕了 -
fpsClock.tick(FPS)
对Clock对象调用tick()
方法,此方法会计算此时距离上一次调用此方法的时间,然后计算出需要暂停的时间,已达到每次循环耗时相同从而控制帧速率的目的
字体显示和声音播放
import pygame
import sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((400,300))
pygame.display.set_caption('hello world')
White = (255,255,255)
Green = (0,255,0)
Blue = (0,0,255)
#创建一个pygame.font.Font对象
#参数为 字体名称和字体大小 freesansbold.ttf为pygame自带的一种字体
fontobj = pygame.font.Font('freesansbold.ttf',32)
#创建一个Surface对象,通过调用Font对象的render方法,将文本绘制上去
#参数依次为 要显示的文本,是否抗锯齿的Boolean值,文本颜色,文本背景颜色
textimg = fontobj.render('Hello World!',True,Green,Blue)
#调用Surface对象的get_rect()方法,从Surface对象中创建一个Rect对象
#(此Rect对象会自动根据其中的文本来设置正确的高度和宽度,但是它的top和left属性将为0)
textrect =textimg.get_rect()
#因为创建的Rect对象初始top和left属性为0,所以设置一下center来调节位置
textrect.center = (200,150) #中心坐标
#声音
#创建一个pygame.mixer.Sound()对象,参数为声音文件的文件名
sound = pygame.mixer.Sound('wolf.wav')
#背景音乐
#pygame一次只能加载一个作为背景音乐播放的声音文件,用下面的函数加载,参数为文件名称
pygame.mixer.music.load('backgroundmusic.mp3')
#设置播放,-1表示永远循环播放(0或者其他正整数则表示播放的次数),第二个参数0.0表示从头播放,如果是5则从头播放到第5秒
pygame.mixer.music.play(-1,0.0)
while True:
screen.fill(White)
#绘制文字图像到显示Surface(传入图像与位置)
screen.blit(textimg,textrect)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
#当按键被下时,即有按键响应时(有按键响应餐能继续判断,否则会报错)
elif event.type == KEYDOWN:
#当按下的键时a时
if event.key == K_a:
#play()方法开始播放声音文件
sound.play()
elif event.key == K_s:
#stop()方法停止播放声音文件
sound.stop()
pygame.display.update()
#结束背景音乐的播放
pygame.mixer.music.stop()
- 字体创建
-
fontobj = pygame.font.Font('freesansbold.ttf',32)
创建一个pygame.font.Font对象,第一个参数是字体类型,freesansbold.ttf是pygame自带的一种字体,第二个参数表示字体大小 -
textimg = fontobj.render('Hello World!',True,Green,Blue)
上面字体对象创建完成后,就可以调用字体对象的render()方法产生一个绘制了字体的Surface对象 -
textrect =textimg.get_rect()
调用Surface对象的get_rect()方法,从Surface对象创建一个Rect对象(此Rect对象具有根据文本自动设置的高度和宽度,左上角初始坐标为(0,0)) -
textrect.center = (200,150)
因为上面的Rect对象的坐标不符合我们要求(显示的位置需要调整),所以设置Rect对象的属性center为(200,150),即使此Rect对象相对窗口居中 - 字体绘制
-
screen.blit(textimg,textrect)
和之前绘制图像一样,使用blit()方法,传递Surface对象和Rect对象(矩形,即绘制位置与占位大小) - 声音
-
sound = pygame.mixer.Sound('wolf.wav')
创建一个Sound对象,参数为文件名 -
elif event.type == KEYDOWN:
判断检测到的事件类型是否为键盘按下事件(判断按键类型时,必须执行,因为只有键盘按下事件产生的Event对象有key属性,如果不执行此语句就执行下面的event.key判断,就会报错) -
if event.key == K_a:
判断按下的键是否为a,后面的K_s即判断是否是s -
sound.play()
此函数让Sound对象开始播放 -
sound.stop()
此函数让Sound对象终止播放 - 背景音乐
-
pygame.mixer.music.load('backgroundmusic.mp3')
加载一个声音对象,参数为声音文件的名称(pygame一次只允许加载一个声音文件作为背景音乐) -
pygame.mixer.music.play(-1,0.0)
调用此函数让上面加载的声音文件开始播放,第一个参数表示循环播放的次数,-1表示永不休止的播放(其他数如3表示循环3次),第二个参数表示从开始播放到第几秒(然后循环),当第二个为0.0时表示全部播放(即完整的播放到末尾) -
pygame.mixer.music.stop()
调用此函数终止背景音乐的播放
大致介绍完了,后续结合具体游戏来学习
学习书籍《python和pygame游戏开发指南》