使用Pygame来制作游戏吧!——Pygame学习

本文最后更新于:2023年4月2日 下午

叠甲

所有内容均从The ultimate introduction to Pygame获得

Pygame基础

如何初始化Pygame?

pygame.init()即可

但是没有弹出窗口

使用screen = pygame.display.set_mode((x, y))来创建一个大小(解析度)为x * y的窗口,
使用pygame.display.set_caption(title)来设置窗口标题
但是现在的窗口并不完善,因为只出现1s就消失了。要解决这个问题,只需要加个while True保持程序一直运行就好了。
但是还需要在循环里添加一句pygame.display.update(),它能够更新我们的窗口里的画面,而不会让我们的窗口一直保持一个帧(画面)不变。

Oops!你可能又发现了一个问题,在点击关闭窗口之后报错了!因为关闭窗口之后程序仍将运行,并且继续执行pygame.display.update()
要解决这个问题,我们会捕捉关闭窗口事件,并在捕捉到之后调用Python的exit()方法(此方法在sys库中,需import),退出程序。

1
2
3
4
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()

十分重要的定时器

在不同机器上运行同一个游戏,帧数会根据机器的好坏而变得不一致,如果我们不对1s内更新的帧数进行某些限制,那么帧数低的时候所有的事物将变慢,帧数高的时候所有的事物将变快,这是我们不希望看到的,所以我们需要使用定时器。
在pygame中,我们使用clock = pygame.time.Clock()来初始化一个定时器,随后,在while True里加入一句clock.time(60)设置每秒最大帧速率进行限制。

绘制我们想要展示在窗口上的”GameObject”!

在窗口中加载(绘制)一个图像,我们可以使用以下命令:

1
2
image_01 = pygame.image.load(path).convert()
screen.blit(image_01, (x, y))

当然如果是透明图像或图像不是你想象的那个样子,就请使用image_01 = pygame.image.load(path).convert_aplha()方法试试吧。
我们还可以绘制文本,具体方法为:

1
2
3
test_font = pygame.font.Font(path, size)
text_surf = test_font.render(text, AA, color) # AA is Anti-aliasing.The value is True or False.
screen.blit(text_surf, (x, y))

使用碰撞箱!

游戏(都)需要有碰撞箱并进行碰撞检测,那么在pygame中,得益于pygame,我们很容易就能获取一个物体的碰撞箱,并使用它们进行各种各样方便开发的操作。

1
2
object_rect = object_surf.get_rect(midbottom=(x, y))
screen.blit(object_surf, object_rect)

关于get_rect()方法的更多参数请自行查阅说明文档,在此仅作简单说明:以该物体碰撞箱的底部的中点作为基准点,将物体绘制到(x, y)位置上。
有了这个碰撞箱,我们也能更好地更新物体在画面中的表现了!比如移动一个物体,我们只需要:

1
2
3
4
object_rect.x -= x
if object_rect.right <= y:
object_rect.left = z
screen.blit(object_surf, object_rect)

上面这段代码写在while True循环中,大致意思为:更新object_rect的在x坐标轴上的位置,如果碰撞箱右边坐标小于某个值,就设置碰撞箱左边的坐标为某个值,然后在画面上绘制出来。
接下来终于进入碰撞检测环节了!
在Pygame中,如果我们需要检测两个碰撞箱是否相撞,直接使用rect_01.colliderect(rect_02)即可,该方法返回01;也可以检测某个点(位置)是否和该物体相撞,用rect.collidepoint((x, y))方法。

对鼠标进行检测

有两种方法,一种是利用pygame.mouse,一种是利用pygame.event。下面举例:

1
2
3
4
for event in pygame.event.get():
if event.type == pygame.MOUSEMOTION:
print(event.pos)
mouse_pos = pygame.mouse.get_pos()

检测键盘输入!

跟检测鼠标一样,检测键盘输入也有两种方法,pygame.keypygame.event
如果我们想要使用pygame.key来检测空格是否被摁下,可以这么写:

1
2
3
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
print('jump')

也可以结合pygame.event

1
2
3
4
5
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
print('jump')
if event.type == pygame.KEYUP:
print('key up')

当然要记住一点,这些相关操作检测我们应该放在相关的类里面而不是主程序的event loop里,在event loop中我们更注重一些通常操作,比如关闭游戏。

转换一个GameObject

pygametransform提供了许多的转换图像的方法,下面举几个例子:
object_01 = pygame.transform.scale(object_01, (weight, height)),最基本的方法,按照所传入的长宽比例进行放大,比较难用。
object_01 = pygame.transform.scale2x(object_01),十分方便的一个方法,直接将原本的图像放大一倍。
object_01 = pygame.transform.rotozoom(object_01, angle, scale),非常全面的方法,可以将图像进行旋转和按比例缩放。

使用Sprite class精灵类吧!

Sprite class, a class that contains a surface and a rectangle; and it can be drawn and updated very easily.
我们可以为玩家和怪物创建他们的精灵类,用于存放他们的surfacerectangle,这符合OOP的编程思想,也能够使代码更整洁,更具有可读性。
有了精灵类后,并不是直接创建他们的实例(对象),而是将他们放进Group中,然后对在Group中对他们进行更新和绘制。在pygame中,有两种Group,一种是通常用的Group,适合存放多个精灵(sprites)实例(对象),一种是GroupSingle,专门为一个sprite服务。
那么很明显我们应该把玩家丢入GroupSingle中,而把怪物等丢入Group中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
def update(self):
...

class Monster(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
def update(self):
...

player = pygame.sprite.GroupSingle()
player.add(Player())

monster_group = pygame.sprite.Group()

精灵类和组都创建完成后,就可以在屏幕上绘制出来了,使用draw()update()方法就能自动完成绘制和更新。

1
2
3
4
5
player.draw(screen)
player.update()

monster_group.draw(screen)
monster_group.update()

过于单调?那就加点音乐

想要为我们的游戏添加背景音乐的话也十分简单,使用pygame.mixer.Sound('path')类即可。

1
2
3
4
background_music = pygame.mixer.Sound('audio/background.mp3')
background_music.set_volume(0.5) # set volume
background_music.play(loops=-1) # loop forever
background_music.stop()

这里有一只爱丽丝

希望本文章能够帮到您~


使用Pygame来制作游戏吧!——Pygame学习
https://map1e-g.github.io/2023/03/30/pygame-learning-1/
作者
MaP1e-G
发布于
2023年3月30日
许可协议