Pygame是一个“游戏开发库” - 一组帮助程序员制作游戏的代码库。包含:
每个游戏的核心都是一个循环,将其称为“游戏循环”。这个循环一直在不断运行,一遍又一遍地完成游戏工作所需的所有事情。每次循环显示一次游戏当前画面,称为帧。
这意味着游戏在进行的同时,需要响应与处理用户的操作—这些可能是键盘上的键被按下,或鼠标被点击等事件。
如果飞机对象在空中飞行,收到重力作用,自身的位置需要改变。如果两个对象相互碰撞,则需要爆炸。
此步骤中,在屏幕上重新绘制所有更新位置后的所有游戏对象。
pygame程序开始部分需导入所需的库并设置好一些变量,然后创建好窗口和程序循环的部分:
import pygame
import random
WIDTH = 360 # 游戏窗口的宽度
HEIGHT = 480 # 游戏窗口的高度
FPS = 30 # 帧率
# 初始化pygame并创建窗口
pygame.init()
pygame.mixer.init() #声音初始化
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My Game")#设置游戏窗口标题栏文字
clock = pygame.time.Clock()
pygame.init()是启动pygame,并“初始化”它的命令。 screen指的是游戏屏幕,按照在配置常量中设置的窗口大小创建它。最后,创建了一个,clock时钟对象,以便能够确保游戏以想要的FPS运行。
# 游戏循环
running = True
while running:
# Process input (events)
# Update
# # Draw / Render
这是游戏循环,它是由变量running控制的循环。如果希望游戏结束,只需要设置running为False,循环就会结束。接下来用一些基本代码填写每个部分。
我们将从Draw部分开始。目前还没有任何游戏对象,用纯色填充屏幕。
图像由像素组成,这些像素有3个部分:红色,绿色和蓝色。每个部分点亮多少会决定像素的颜色,如下所示:
三原色中的每一个可以具有介于0和255之间的值,因此对于三种基色中的每一种,存在256种不同的可能性。以下是一些三种颜色的组合示例:
我们可以在开始设置变量的时候将颜色这些量都配置好然后绘图时就可以直接应用这些颜色进行填充:
# Colors (R, G, B)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# Draw / render
screen.fill(BLACK)
这样还不够。更改屏幕上的像素意味着告诉视频卡告诉显示器更改实际像素。从计算机的角度来看,这是一个非常非常缓慢的过程。因此,如果你在屏幕上绘制了很多东西,那么绘制它们可能需要很长时间。处理能力差的计算机表现为游戏运行卡顿。
我们可以通过使用称为双缓冲的技术,以巧妙的方式解决这个问题。
想象一下,有一个双面白板,可以翻转显示一侧或另一侧。前面是显示器(玩家看到的屏幕),而背面是隐藏的,只有计算机可以“看到”它。每一帧,都在背面(内存中)绘制所有图画 - 每个角色,每个子弹,每个闪耀的光线等等。然后,当完成后,将白板翻转并显示。这意味着每帧只是执行一次白板翻转的过程。
所有这些都在pygame中自动发生。完成绘图后,只需要告诉它翻转白板。命令为flip():
# Draw / render
screen.fill(BLACK)
# *after* drawing everything, flip the display
pygame.display.flip()
如果现在尝试运行该程序,我们会发现遇到了问题:无法关闭窗口!单击屏幕右上角中的“X”按钮不起作用。那是因为当用户点击关闭按钮时产生了一个事件,我们需要程序监听该事件,并做出相应处理—退出游戏。
Pygame内部保存自上一帧以来发生的所有事件。可以通过下面的代码检查发生了哪些事件:
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
running = False
Pygame有很多事件。 pygame.QUIT是单击“X”按钮时发生的事件。程序检查到该事件发生后,将running变量设置成False,从而推出游戏循环,结束游戏。
pygame支持使用pygame.font对象将文本打印到窗口上。要打印文本的话,首先需要创建一个字体对象,Font的第一个参数为None是告诉pygame获得系统默认字体,也可以是具体的字体名称。Font的第二个参数指明字体大小。
myfont = pygame.font.Font(None,60)
文本绘制过程比较耗费时间,常用的做法是先在内存中创建文本图像,然后将文本当作一个图像来渲染。
textImage = myfont.render("pygame", True, WHITE)
textImage 对象可以使用screen.blit()来绘制。上面代码中的render函数第一个参数是要绘制的文本,第二个参数是启用抗锯齿能力,第三个参数是文本的颜色。
下面的代码,将刚刚产生文本图像绘制到屏幕的坐标(10,100)处:
screen.fill(BLACK)
screen.blit(textImage, (10,100))
pygame.display.flip()
游戏循环的另一个重要方面是控制整个循环的运行速度。游戏中有个术语叫FPS(Frames Per Second),它代表每秒帧数,也叫帧率。这意味着游戏循环每秒应发生多少次。这很重要,因为我们不希望游戏运行得太快或太慢。也不希望它在不同的计算机上以不同的速度运行 。
虽然现在还没有任何东西要放在“更新”部分,但仍然需要设置FPS来控制游戏运行速度。可以这样做:
while running:
# keep loop running at the right speed
clock.tick(FPS)
该tick()命令告诉pygame一秒循环多少次。如果设置FPS为20,这意味着我们命令游戏的每个循环持续1 / 20(0.05)秒。如果循环代码(更新,绘图等)只需要0.03秒,那么pygame将等待0.02秒。以上是计算机处理比较快的情况。如果电脑比较差,运行缓慢,一秒钟未必能执行20次循环— 那么clock.tick(20)就成为一个指导意见。
可循环计算出FPS并显示在屏幕上
首先,在while循环之前定义2个变量:
count = 0
start = time.time()
计算方法:循环开始前获得当前系统时间,在每次循环中,累加循环次数count;同时在每次循环时,获得当前系统时间,那么从开始循环到目前为止流逝的时间(时间差)为:now-start。再用count除以这个时间差,即为FPS(每秒循环了多少次)。代码如下:
# Update
count+=1
now = time.time()
fps = count/(now-start)
fpsImage = myfont.render(str(fps), True, WHITE)
# Draw / render
screen.fill(BLACK)
screen.blit(fpsImage, (10, 100))
# *after* drawing everything, flip the display
pygame.display.flip()
我们可以修改FPS的值,看看是否界面上输出的值会跟着变化,我的电脑,将FPS设置成10000时,发现屏幕上打印的是2300,说明,我的电脑配置最多可以支持到1秒中运行循环中的代码2300次。
最后,为了确保当游戏循环结束时,游戏窗口正确退出。我们通过将代码pygame.quit()的放到最后一行来实现这一点。
FPS = 10
FPS = 100
FPS = 1000
FPS = 10000