Program Arcade Games
With Python And PygameChapter 11: 位图和声音
要超越简单的绘制图形,我们的程序需要有能力使用位图图像。位图图像可以是照片或者有绘图程序绘制并存储起来的图形。
但是光有图像还不够。游戏还要哟声音! 这一章展示了如何把图像和声音添加到你的游戏。
11.1 在文件夹中存储程序
我们现在写的程序都只涉及打一个文件而已。现在我们要包含图像和声音,所以在我们的程序里会有很多文件。 很容易把这些文件和其他程序混在一起。 最简洁的分离办法是把每一类程序放在各自的文件夹内。 在开始任何项目之前,点击“创建新文件夹”按钮,比使用新的文件夹作为存储点,如图例所示11.1。
11.2 设置背景图像
需要给你的游戏添加一个背景? 找一张图片如图所示11.2。 如果你在浏览器里寻找,通常你可以右击一张图片,然后保存在计算机上。 把图片保存在我们刚给游戏创建的文件夹里。
确保你没有使用有版权的图片!使用反图像搜索很容易发现你是否盗用了。你已经学程过半了,不要冒这个风险。
任何用在游戏里的位图图像应该剪裁到符合屏幕的尺寸。不要取一张从高分辨率里拍摄的5000x5000的图片并输出到一个800x600的窗口里。 使用一个图形程序(甚至简单的画图程序),可以重新调整图形的尺寸。
载入图像是个简单的过程,只需要用到一行代码。 在那一行代码背后有许多事情正在发生,所以解释这一行需要三个部分。 我们第一个版本的load命令会载入一个saturn_family1.jpg的文件。这个文件和Python程序在同一个文件夹内,否则计算机无法找到它:
pygame.image.load("saturn_family1.jpg")
这行代码可以载入图片,但是我们没有办法指向这个图片并显示出来!我们需要一个变量来获取load()命令返回的内容。 在下一个版本中,我们创建了一个新的便利那个名叫background_image。下面就是版本2:
background_image = pygame.image.load("saturn_family1.jpg")
最后,图片需要转化成Pygame可以轻松操作的格式。为了这个目的,我们砸末尾添加一个.convert()命令来调用转化函数。 函数.convert()是属于Image类的一个方法。我们会在第12章中讨论类,对象和方法的相关内容。
所有图片的导入应该都和下面这行代码类似。 只需更具需要改变变量名和文件名。
background_image = pygame.image.load("saturn_family1.jpg").convert()
载入图片嘘小在主循环之前完成。 尽管在主循环内载入是可能的,但这样会使得程序每秒从硬盘读取很多次。是完全没有必要的。只需要在程序启动时读取一次。
要显示图片使用blit命令。这个“blits”命令会把图片比特化到屏幕上。我们已经在之前第五章显示文本的时候使用过这个命令。
blit命令是screen变量的一个方法,所以我们需要使用screen.blit。 下一步,我们需要传递图像来比特化,已经决定在哪儿显示。 这个命令需要在循环之内完成,这样每一帧都能绘制图像。参考下列代码:
screen.blit(background_image, [0, 0])
这行代码会将background_image中的图像比特化到屏幕上,从(0, 0)开始。
11.3 移动图片
现在我们需要载入一个图片并在屏幕中移动它。我们会一艘简单橙色太空飞船开始。 你可以在这里http://kenney.nl/获取它以及其他素材。参考图例11.3。 飞船的图片也可以从书的网站上下载,或者你可以寻找任一.gif或者.png格式的图片(白色或者黑色背景)。不要使用.jpg格式。
载入图片的命令和载入背景图片是一样的。 在这个例子中,我假设文件名保存为player.png.
player_image = pygame.image.load("player.png").convert()
在程序主循环内,鼠标坐标已经获取,并传递至另一个blit函数来绘制图像:
# 获取现在的鼠标位置。这会返回一个两个数字组成的列表。 player_position = pygame.mouse.get_pos() x = player_position[0] y = player_position[1] # 复制图片至屏幕: screen.blit(player_image, [x, y])
这会产生一个问题。图片是一张带黑色背景的飞船。 所以当图像如图例绘制出来的时候11.4.
我们只想要飞船,不需要矩形的北极啊! 但是所有我们能够载入的都是矩形,我们如何移除矩形只保留我们想要的部分呢? 一种可行的办法是告诉程序让一种颜色变“透明”,不显示出来。 这在载入之后可以立即完成。下面的代码会把黑色 (假设BLACK是已经被定义的变量)变透明:
player_image.set_colorkey(BLACK)
这对大部分以.gif和.png结尾的图片文件有效。对绝大多数.jpg文件无效。jpeg格式对保存摄影图片很棒,但是它为了压缩图片用算法更改了图像。 .gif and .png格式的图片虽然也压缩了,但是它们使用的算法并没有改变图像。.bmp格式是完全不压缩的,也造成文件巨大。 因为.jpg格式图片改变了凸显,这就意味着不是所有的背景是同一种颜色。 在图例11.5中飞船已经以白色背景存储为jpeg文件了。这种白色并不是正好(255, 255, 255), 但是非常接近。
如果你在挑选一张想变透明的图片,选择.gif或者.png格式。它们是艺术类图片最好的格式。照片是.jpg。 请记住不是把文件扩展名改成.png就真的可以改变一章.jpg图片的。即使你把它叫成其他名字它还是一张.jpg图片。 它需要通过图像程序才能转化成另一种格式。但是一旦是jpg格式,那么图像已经被改变了再转化成.png以及无济于事。
下面是三个找到免费的图皮的网站:
Kenney.nl
OpenGameArt.org
HasGraphics.com
11.4 声音
砸这个部分我们会在鼠标点击的时候播放一个镭射光的声音。这个声音文件源自于Kenney.nl。你可以在这里下载并保存:
ProgramArcadeGames.com/python_examples/en/laser5.ogg
像图像一样,声音必须在使用前载入好。这一步也是要在循环主程序之前一次完成。 下面的命令载入了一个声音文件并创建了一个名为click_sound的变量来指向它:
click_sound = pygame.mixer.Sound("laser5.ogg")
我们可以使用下面的命令来播放声音:
click_sound.play()
但是我们把这条命令放在哪儿? 如果我们放在主循环里那么它会每秒播放二十次以上。非常烦人。我们需要一个“触发器”。当一些事件发生时,我们来播放声音。 例如下面这段代码,当用户点击鼠标按年的时候我们来播放这段声音:
for event in pygame.event.get(): if event.type == pygame.QUIT: done = True elif event.type == pygame.MOUSEBUTTONDOWN: click_sound.play()
未压缩的声音文件通常以.wav结尾。这些文件比其他文件大很多因为没有使用算法来使文件变小。 还有一种更受欢迎的.mp3格式,尽管这种格式砸某些特定应用中很不合适。另一种免费使用的格式是.ogg。
Pygame不使用任何在网上可以找到的网上bd>.wav文件。 如果你有文件不工作,你可一使用程序Audacity把它转化成一个.ogg.格式的声音文件。这种格式很小且在pygame中很可靠。
如果你想让你的程序运行时播放背景声音,可以参考这些例子:
ProgramArcadeGames.com/en/python_examples/f.php?file=background_music.py
请注意你不能够传播有版权的音乐。即使你做了一个关于你程序的视频使用了有版权的音乐作背景。YouTube和其他视频网站会以侵权举报你。
能给你的程序找到免费声音的地方是:
OpenGameArt.org
www.freesound.org
11.5 代码清单
""" Sample Python/Pygame Programs Simpson College Computer Science http://programarcadegames.com/ http://simpson.edu/computer-science/ Explanation video: http://youtu.be/4YqIKncMJNs Explanation video: http://youtu.be/ONAK8VZIcI4 Explanation video: http://youtu.be/_6c4o41BIms """ import pygame # Define some colors WHITE = (255, 255, 255) BLACK = (0, 0, 0) # Call this function so the Pygame library can initialize itself pygame.init() # Create an 800x600 sized screen screen = pygame.display.set_mode([800, 600]) # This sets the name of the window pygame.display.set_caption('CMSC 150 is cool') clock = pygame.time.Clock() # Before the loop, load the sounds: click_sound = pygame.mixer.Sound("laser5.ogg") # Set positions of graphics background_position = [0, 0] # Load and set up graphics. background_image = pygame.image.load("saturn_family1.jpg").convert() player_image = pygame.image.load("playerShip1_orange.png").convert() player_image.set_colorkey(BLACK) done = False while not done: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True elif event.type == pygame.MOUSEBUTTONDOWN: click_sound.play() # Copy image to screen: screen.blit(background_image, background_position) # Get the current mouse position. This returns the position # as a list of two numbers. player_position = pygame.mouse.get_pos() x = player_position[0] y = player_position[1] # Copy image to screen: screen.blit(player_image, [x, y]) pygame.display.flip() clock.tick(60) pygame.quit()
11.6 复习
11.6.1 选择题小测验
Click here for a multiple-choice quiz.
11.6.2 练习表
Click here for the chapter worksheet.
11.6.3 实验
Click here for the chapter lab.
You are not logged in. Log in here and track your progress.
English version by Paul Vincent Craven
Spanish version by Antonio Rodríguez Verdugo
Russian version by Vladimir Slav
Turkish version by Güray Yildirim
Portuguese version by Armando Marques Sobrinho and Tati Carvalho
Dutch version by Frank Waegeman
Hungarian version by Nagy Attila
Finnish version by Jouko Järvenpää
French version by Franco Rossi
Korean version by Kim Zeung-Il
Chinese version by Kai Lin