![零基础入门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=1739250775-43dMxZEb2oxQBiZ9e9Q47NXortjhF8RY-0-9fa14e50f34f16853f069021f3847593)
这里使用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=1739250775-fQcxToF1rs9ccQWA5CSMwlI4SOYtR34w-0-d513bf2a37fb424e6b3a96e2c71349c6)
它接收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=1739250775-ip92zFkt6RG55JtJWAdR9hE6KtGsBDNq-0-bd9af2d42e739899ccd6d2c940624f79)
加载音乐文件,参数filename为音乐文件名称。
它所支持的音频文件格式同样也为ogg和wav。对于mp3格式,它提供了非常有限的支持,并不是所有的系统或Pygame版本都支持mp3格式。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2694.jpg?sign=1739250775-BpEADekFXEmnsxPG1ll9YghlH5XuBgcz-0-66f153b679fcfc21a96dd773e18449ac)
播放之前所加载的音乐文件。参数loops代表播放次数,0为播放一次,1为播放两次,以此类推,如果为-1,则代表循环播放。参数start表示音乐播放所开始的位置。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2703.jpg?sign=1739250775-tmXjuRyWi0RiKH7QRsT1nDRn9SyMbeR7-0-cd943d8da70735608f1bfcb1cf7d5978)
暂停播放音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2712.jpg?sign=1739250775-PrGIuHan6U9lgMrtyYpaCm34toSVtQ6L-0-0f65e89364196e2a992541020ff340b7)
恢复播放被暂停的音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P74_2721.jpg?sign=1739250775-DzZLq3c1ogppRt5tEWOli808PXybax3f-0-d823892e29190a1610953fe9af3c77b9)
结束播放音乐。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P75_2733.jpg?sign=1739250775-F0nzOkydV1jcUBq17xrilphrQRgJVkJ3-0-fe88cac91610ae4f9991ca3b536c18fc)
淡出播放音乐。参数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=1739250775-HfDDTQjB7BwBpIAsMIh9tcTHWd3IN7b9-0-eac6f12a2ca2a377e6a35c537f38bf22)
图2-19 音效与音乐示例程序
完整代码如下。
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P75_10373.jpg?sign=1739250775-p2EtM863svTr0iFR2F5EYdFFvKDiqeU6-0-523da8fb0fa4fde5aac453031ac90f7b)
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P76_10375.jpg?sign=1739250775-3kjyI4E97kVq6SilhKGnh3jogMPzxN3n-0-a5a54751c93cf0db40649132816ab2f8)
![](https://epubservercos.yuewen.com/31D206/23721606009501206/epubprivate/OEBPS/Images/Figure-P77_10376.jpg?sign=1739250775-yklTn8RfELXGeXZ8BaLBiNoH7myDoj6X-0-71d1a4ab0d89f90b1002ff55ba429659)
首先解释按钮的实现方法。每个按钮实际上都是一张图片,在代码中,我们把按钮抽象为Button类,因为有7个类似的按钮,所以就把Button类当作Sprite,使用Group管理它们。Button类有3个属性,即self.name、self.image、self.rect,分别代表该按钮的名称、image surface和所在的矩形区域。
判断鼠标是否单击某个按钮使用的是Rect对象的collidepoint()方法。然后是在每当MOUSEBUTTONDOWN事件到来时进行判断,并且要对该Event的button属性值进行检测,只有当button值为1时,才表示鼠标左键被按下,需进行更进一步的判断,如果是其他值,则不予处理。
代码中关于音效与音乐的控制部分还是比较简单的,只是简单地调用了前面所介绍的一些函数。