![零基础入门Python游戏](https://wfqqreader-1252317822.image.myqcloud.com/cover/70/44510070/b_44510070.jpg)
2.15 音效与音乐
前面介绍了Pygame中各个常用的模块,作为本章的最后一个知识点,现在开始讲解在Pygame中如何播放音效与音乐,这也是游戏中至关重要的一部分。
通常意义上所说的音效指游戏中比较短的声音效果,如子弹声、爆炸声等,一般情况下只需控制它自动播放就可以了;而音乐通常时长较长,一般作为背景音乐贯穿游戏始终,所以经常需要对它进行播放、暂停、停止等较多的控制操作。
支持音效与音乐的相关模块为pygame.mixer。
1. 播放音效
播放音效所用的方法为:
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P73_2656.jpg?sign=1739277140-qY4K0ZNza7ZiAWrczqfIyAPZCFFwE6fH-0-5113a72680feaf0553850de08aec62a5)
这里使用win.wav作为示例音频。第1行代码的意义是根据所指定的音频文件创建一个pygame.mixer.Sound类的对象sound;第2行代码的意义是调用Sound类的play()方法播放音频。
注意:对于音频文件的格式,这里仅支持ogg和wav,并不支持mp3。
下面详细了解一下Sound类的play()方法。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2676.jpg?sign=1739277140-HfLuxnGI2cnT1wbJsTocqrEwDuTSQM7j-0-b6fa072bd854b1d5de143b1de55720aa)
它接收3个参数,这3个参数都有其各自的默认值。其中,loops代表播放次数,0表示播放一次,1表示播放两次,5表示播放六次,-1表示循环播放;参数maxtime表示该音频的最长播放时间,即播放超过多久就必须停止,单位为毫秒(ms);最后一个参数fade_ms表示音频淡入所花费的时间,单位也为毫秒(ms)。虽然参数比较多,但是在一般情况下,我们都是让它们全部使用默认值,这样的话,音效音频文件只播放一次,没有最长时间限制,也没有淡入效果,这是最通常的情况。
关于pygame.mixer.Sound类,除了常用的play()方法,还有许多其他方法,如stop()、fadeout()、set_volume()、get_length()等。另外,在pygame.mixer模块下,除了定义了Sound类,还提供了许多其他函数,它们主要用来对声道(channel)进行管理。鉴于它们的使用频率并不是那么高,所以这里不再做详细介绍。
2. 播放音乐
为音乐提供支持的函数全部放在pygame.mixer.music模块下面,主要有:
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2685.jpg?sign=1739277140-m6DNe1oS0yYWCb2aztPEQN8oRcVZXc8V-0-41e83a2ce12c190cc8cbb525602f56a4)
加载音乐文件,参数filename为音乐文件名称。
它所支持的音频文件格式同样也为ogg和wav。对于mp3格式,它提供了非常有限的支持,并不是所有的系统或Pygame版本都支持mp3格式。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2694.jpg?sign=1739277140-23FDvdhLpJ5sllsCNt3ldI1SVRWeHTlx-0-0bff01fd78a0296309cffaa6770b5d83)
播放之前所加载的音乐文件。参数loops代表播放次数,0为播放一次,1为播放两次,以此类推,如果为-1,则代表循环播放。参数start表示音乐播放所开始的位置。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2703.jpg?sign=1739277140-3eC8JAgRoB5hyE1rE9XsszqiHTK3ZgQg-0-587572a25ada627ab4eba0fd765617c8)
暂停播放音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2712.jpg?sign=1739277140-bXuFVykg1QgMZ0UFBaxKbbDHAv5JJAeG-0-93198abb6785062155d42bf3298c3286)
恢复播放被暂停的音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2721.jpg?sign=1739277140-b6FL729d3T7M7FkQtABDAWoZeSO2Nod0-0-05b7df0469a9637466598ca1996b4bd6)
结束播放音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P75_2733.jpg?sign=1739277140-9pUrpEUmi8mE3ZfdE4AdElMqKAYQbPYt-0-1a08664b63d39325cfe2e1baca785f09)
淡出播放音乐。参数time表示淡出效果所持续的时间,单位为毫秒(ms),代表经过多少毫秒的淡出播放之后音乐结束。
除了上面的函数,pygame.mixer.music模块还提供了一些其他的函数用于对音乐进行更进一步的控制,如set_volume()、get_volume()、rewind()等,这里不做过多介绍。
注意:不同于前面的Sound,这里的music并不是以类的形式存在的,它只是pygame.mixer中的一个模块,所以上面的一些函数也并不是类的方法,它们的使用方法类似pygame.mixer.music.load()、pygame.mixer.music.play(),是直接通过模块名调用的。
3. 具体示例
按照惯例,最后还是看一个关于音效与音乐播放的完整示例程序。
先看看它的执行效果。
如图2-19所示,该程序的功能一目了然:窗口上有两列总共7个按钮,第一列按钮是与音乐相关的,第二列按钮是与音效相关的,单击按钮就会执行相应的操作。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P75_2746.jpg?sign=1739277140-piTLhyRybWeqYA5TW3qZ3E9vWI5vkwtj-0-a3a190b3ad54ca06f74478c45dec6ae9)
图2-19 音效与音乐示例程序
完整代码如下。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P75_10373.jpg?sign=1739277140-EmgOLePIUqjvpH7mz4njBHBuJV0o6Df6-0-b12a0e32ed10031f6ef10a9dfaa154a7)
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P76_10375.jpg?sign=1739277140-UMhCJo7aXBCxPBenDqMVAsXQtnOw0WhP-0-eaef53926723734ba53a60316388d610)
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P77_10376.jpg?sign=1739277140-Gpfg9jpuNrDxUgJbqZulIN8wsGIwlDxa-0-abe86fcffb24271c1918e25f1d4da035)
首先解释按钮的实现方法。每个按钮实际上都是一张图片,在代码中,我们把按钮抽象为Button类,因为有7个类似的按钮,所以就把Button类当作Sprite,使用Group管理它们。Button类有3个属性,即self.name、self.image、self.rect,分别代表该按钮的名称、image surface和所在的矩形区域。
判断鼠标是否单击某个按钮使用的是Rect对象的collidepoint()方法。然后是在每当MOUSEBUTTONDOWN事件到来时进行判断,并且要对该Event的button属性值进行检测,只有当button值为1时,才表示鼠标左键被按下,需进行更进一步的判断,如果是其他值,则不予处理。
代码中关于音效与音乐的控制部分还是比较简单的,只是简单地调用了前面所介绍的一些函数。