![零基础入门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=1739054451-PAqhnDQ1pcGI80qiLUk5RrXkC8s5uWq2-0-856d10e4b880ed24d966be509f4c9f3e)
这里使用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=1739054451-guH8og8BBCq3XlPCmq0n45nKhek7sOho-0-c5a44d014f83eb9ea506222a22914162)
它接收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=1739054451-EmB0KjdTm1EoMdXThFr7SqhIye1MYXq1-0-79d6a131257f4520e9776ae4d82179d2)
加载音乐文件,参数filename为音乐文件名称。
它所支持的音频文件格式同样也为ogg和wav。对于mp3格式,它提供了非常有限的支持,并不是所有的系统或Pygame版本都支持mp3格式。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2694.jpg?sign=1739054451-ClvFYCN7NKU6zhZPxTC7DOw6qsb4xI8L-0-dfdd920457f568d2a0a7d54e6944b854)
播放之前所加载的音乐文件。参数loops代表播放次数,0为播放一次,1为播放两次,以此类推,如果为-1,则代表循环播放。参数start表示音乐播放所开始的位置。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2703.jpg?sign=1739054451-ub0ONJHltPBtp0DQavBOByt6HuWlVF06-0-3672b9780b914e158d41f01f826066f5)
暂停播放音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2712.jpg?sign=1739054451-wTWjBLyQzgXRQZKsK88K68nmz8TENJNd-0-41bf352eafb5f63312da4fbda3a3cca8)
恢复播放被暂停的音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2721.jpg?sign=1739054451-IMQkgxACpNIFs06tjfwm5hpoZdXeEEbj-0-81528eab75a8ad186e46f81961f01c1d)
结束播放音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P75_2733.jpg?sign=1739054451-TWaztPSk1znjUsESf5KzfNM14s8qFPMG-0-c7a8a9f96b1138d2e9d5ef2bf1a16d0a)
淡出播放音乐。参数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=1739054451-Lb5ax8lCMvcnhwZx6G7HXD5vyolGmSMI-0-ae72bb33015d27ad05cc35471a223915)
图2-19 音效与音乐示例程序
完整代码如下。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P75_10373.jpg?sign=1739054451-8MSo6QOkrQhABztNKZ5xearNb53qqwEG-0-4b04d0590845dc5a56150e23d91946e0)
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P76_10375.jpg?sign=1739054451-CVHqXONbJZPiFV6iDzx5GL0BUgJeofbR-0-29e2ef7c1b0ddb113e65a1fc6584360c)
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P77_10376.jpg?sign=1739054451-Z1080Ffl11ORlZ1xG8AHx7C4tWKpcFYc-0-f25c03ed34aeb9e6b6f531e93e6f8bad)
首先解释按钮的实现方法。每个按钮实际上都是一张图片,在代码中,我们把按钮抽象为Button类,因为有7个类似的按钮,所以就把Button类当作Sprite,使用Group管理它们。Button类有3个属性,即self.name、self.image、self.rect,分别代表该按钮的名称、image surface和所在的矩形区域。
判断鼠标是否单击某个按钮使用的是Rect对象的collidepoint()方法。然后是在每当MOUSEBUTTONDOWN事件到来时进行判断,并且要对该Event的button属性值进行检测,只有当button值为1时,才表示鼠标左键被按下,需进行更进一步的判断,如果是其他值,则不予处理。
代码中关于音效与音乐的控制部分还是比较简单的,只是简单地调用了前面所介绍的一些函数。