用Python和Pygame写游戏-从入门到精通(20)

By | 2011/08/15

声音是游戏中必要的元素之一,音效可以给予用户良好的反馈体验。赛车的时候可以听到振奋人心的启动时的引擎声和刹车时轮胎摩擦声,射击游戏中枪支弹药的音效和呐喊助威的嗓音,无一不是让人热血沸腾的要因。

宛若电影,最初的电影史无声的,而自从1927年第一部公认的有声电影放映之后,人们的娱乐项目一下子丰富了好多;游戏中也是啊,好的配音绝对可以给我们的作品增色不少。这几次就是给我们的pygame作品中增加美妙的声音的。

什么是声音?

又要开始讲原理了啊,做游戏真是什么都要懂,物理数学美术心理学和编程等等等等,大家都不容易呀~~

声音的本质是振动,通过各种介质传播到我们的耳朵里。基本任何物质都可以振动,比如说一旦我们敲打桌子,桌子表面会快速振动,推动附近的空气一起振动,而这种振动会传播(宛如水中扔一颗石子,水波会慢慢传播一样),这种振动最终进入我们的耳道,使得鼓膜振动,引起我们的听觉。

振动的幅度(响度)越大,听到的声音也就越大,这个很好理解,我们越用力拍桌子,声音也就越大(同时手也越疼——)。同时,振动的快慢(音调)也会直接影响我们对声音高低的判断,也就是平时说的高音和低音的差别,决定着个音调的要素每秒振动的次数,也就是频率,单位是赫兹(Hz)。比如100Hz意味着这个振动在1秒内进行了100次。音色也是一个重要指标,敲打木头和金属听到的声音完全不同,是音色的作用,这个的要素是有振动波形的形状来决定。

现实中很多声音都是许多不同的声音组合而来的。同时声音在传播的时候也会发生变化,最直接的就是随着距离增大,响度会减小;而在不同的环境中,因为反射和混合,声音的效果也完全不一样。这些都要好好考虑,比如脚步声,空旷的山谷中应该是“空谷足音”的效果,楼梯上则是比较短但是渐渐靠近的效果。甚至发声物体的速度也会影响我们听到的声音,谓之“多普勒效应”……好麻烦!不过最后游戏里可能不是那么符合现实的,比如说太空中发射导弹什么,按说是听不到声音的,因为没有介质传播,不过为了效果好,咱也不在意了……

声音的存储

声音完全是一种模拟的信号,而我们的计算机只能存储数字(二进制)信号,咋办?数字化咯~

(一下说明摘录修改自轩辕天数-丝竹的文章,表示感谢)

以最常见的WAV文件为例,要把声音记录成WAV格式,电脑要先把声音的波形“画在一张坐标纸上”。然后呢,电脑要看了“横坐标第一格处,波形图的纵坐标是多少啊?哦,差不多是500啊(仅仅是打比方,而且这个“差不多”很关键),那么横坐标第二格呢?…”最后,电脑就得出来一大堆坐标值。然后再经过一些其他后续工作,电脑就把这些坐标值保存下来了。

当要放音的时候,电脑要根据这些“坐标值在坐标纸上面画点”,最后“用线把点连起来”,差不多就把原先的波形还原出来了。其实数字化录音基本上就是这样的原理。

电脑记录波形时,用的坐标纸格子越密,自然记录下来的点就越多、越精确,将来还原出来的波形就越接近原始波形?上边例子的横坐标轴格子密度就相当于采样频率(比如,44.1KHz),纵坐标格子密度就相当于量化精度(比如,16BIT)。这就是“KHZ”、“BIT”的值越高,音乐的音质越好的原因。

这个世界上自然不仅仅有WAV这一种存储声音的文件格式,宛若图像文件格式中的BMP一样,WAV是一种无压缩的格式,体积最大;而OGG则好像PNG,是无损的压缩,可以完全保持图像的本真,但是大小又比较小;常用的MP3,则是类似于JPG的有损压缩格式。

声音处理

想要获得声音,最简单的自然是录制,不过有的时候比较困难,比如录制心跳要很高昂的仪器,而录制火山爆发的声音实在过于……

这时候我们可以手动合成声音,而录制获得的声音还需要经过处理,比如净化等,有很多软件可以选择,开源的Audacity就是一个很不错的选择。具体的这里就不说了,一门大学问啊。

网上也有很多声音素材可供下载,好的专业的素材都是卖钱的,哎这个世界什么都是钱啊~~

Pygame中声音的初始化

这次来不及举一个实际例子放声音了,先说一下初始化。

在pygame中,使用mixer模块来播放声音,不过在实际播放之前,我们需要使用pygame.mixer.init函数来初始化一些参数,不过在有的平台上,pygame.mixer.init会随着pygame.init一起被初始化,pygame干脆提供了一个pygame.mixer.pre_init()来进行最先的初始化工作,参数说明如下:

  • frequency – 声音文件的采样率,尽管高采样率可能会降低性能,但是再次的声卡都可以轻松对应44.1KHz的声音回放,所以就设这个值吧;
  • size – 量化精度
  • stereo – 立体声效果,1:mono,2:stereo,具体请google,一般设2好了
  • buffer – 缓冲大小,2的倍数,设4096就差不多了吧

你可以像这样初始化声音:

pygame.mixer.pre_init(44100, 16, 2, 4096)
pygame.init()

这里先用pre_init来设定了参数,然后在pygame.init中初始化所有的东西。

如果你需要重新设定声音的参数,那么你需要先执行pygame.mixer.quit然后再执行pygame.mixer.init,不过一般用不到吧……

>> 用Python和Pygame写游戏-从入门到精通(21)

 

10 thoughts on “用Python和Pygame写游戏-从入门到精通(20)

  1. tangly

    只想说一句:爱死你了 哇哇。。。。。。。。。。。。

    Reply
  2. tangly

    想必你每天也比较辛苦吧,不容易!

    Reply
  3. ZHG

    没想到居然有这样的高手,不知道愿不愿意指点一二,我对游戏变成比较感兴趣,不过是个人爱好,对了不知道有人对C++的游戏编程了解么?

    Reply
  4. 陈鹏飞

    我在树莓派上运行的程序,在跑到pygame.init()时系统报出xcb_connection_has_error() returned true,我感觉它像是关于音频输出的错误,想问问这个问题怎么解决?

    Reply
  5. Pingback: 用Python和Pygame写游戏-从入门到精通(20)-演道网

  6. julian

    今天是2024-3-8. 我大概在七八年前第一次看到博主的这个系列, 受益匪浅. 相信除了幼教工作者, 业余玩家如今兴趣早已到了3D. 但希望我还来得及说, 感谢楼主的dedicated devotion.

    Reply

ZHG进行回复 取消回复

您的电子邮箱地址不会被公开。