欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

学了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

学了python,想做游戏?一起学习pygame模块

  • 首先 import pygameimport 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()

学了python,想做游戏?一起学习pygame模块

  • 颜色,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)

学了python,想做游戏?一起学习pygame模块

  • 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游戏开发指南》

相关标签: pygame