2020年9月12日星期六

87 《零基礎入門學習Python》筆記 第087講:Pygame:播放聲音和音效

《零基礎入門學習Python》第087講:Pygame:播放聲音和音效



一般遊戲來說,聲音主要分為兩種,一種是背景音樂,一種是音效。
背景音樂就是時刻伴隨著遊戲存在的,往往就是重複播放的一首曲子或者歌曲;音效就是在某種條件下被觸發產生的,比如兩個小球碰撞在一起就會發出"啪啪啪" 的聲音。
剛才我們也說了,Pygame 支持的聲音格式十分有限,一般情況下我們使用.ogg 的格式來做背景音樂,用無壓縮的.wvb 來作為音效。那麼你拿到一個.mp3 格式該怎麼辦呢?
你可以使用格式工廠這類的軟件把它轉為.ogg 或者.wvb 格式。
注意:music 模塊雖然寫了支持 .mp3 格式,但是它對.mp3 格式的支持十分有限,經常你會在網上找到一段很好的.mp3 的曲子,但是載入之後壓根沒有聲音。你把它轉為.ogg 格式就可以很好的支持了。

•播放音效:

–pygame.mixer.Sound()

播放音效我們使用mixer 模塊,在使用之前,需要先生成一個Sound 對象,對這個Sound 對象進行控制,Sound 對象的play() 方法就是播放音效,稍候我們來講這些方法。

•播放背景音樂:

–pygame.mixer.music

播放背景音樂我們使用music 模塊,music 模塊和mixer 模塊是緊密關聯的。

Sound 對象方法如下:

方法
含義
play()
播放音效
stop()
停止播放
fadeout()
淡出
set_volume()
設置音量
get_volume()
獲取音量
get_num_channels()
計算該音效播放了多少次
get_length()
獲得該音效的長度
get_raw()
將該音效以二進制格式的字符串返回

music 模塊方法如下:

方法
含義
load()
載入音樂
play()
播放音樂
rewind()
重新播放
stop()
停止播放
pause()
暫停播放
unpause()
恢復播放
fadeout()
淡出
set_volume()
設置音量
get_volume()
獲取音量
get_busy()
檢測音樂流是否正在播放
set_pos()
設置開始播放的位置
get_pos()
獲取已經播放的時間
queue()
將音樂文件放入待播放列表中
set_endevent()
在音樂播放完畢時發送事件
get_endevent()
獲取音樂播放完畢時發送的事件類型
我們來舉個例子:
要求:寫一個程序,打開程序就會自動播放背景音樂(bg_music.ogg),當你在窗口中點擊鼠標左鍵時,就會播放winner.wav音效;點擊鼠標右鍵,就會播放loser.wav音效;點擊空格鍵就暫停背景音樂,再次點擊就繼續播放。(需要這幾個聲音文件的的可以在下面評論區留下郵箱,我看到後就把免費發送給你們)
  1. import pygame
  2. import sys
  3. from pygame.locals import *
  4. pygame.init()
  5. pygame.mixer.init()#初始化混音器模块(可以不写,上面初始化已经包含了,但是最好写上)
  6. #加载背景音乐
  7. pygame.mixer.music.load('bg_music.ogg')
  8. pygame.mixer.music.set_volume(0.2)#设置音量
  9. pygame.mixer.music.play()#播放
  10. #加载音效
  11. winner_sound = pygame.mixer.Sound("winner.wav")
  12. winner_sound.set_volume(0.2)
  13. loser_sound = pygame.mixer.Sound("loser.wav")
  14. loser_sound.set_volume(0.2)
  15. #设置窗口
  16. bg_size = width, height = 300, 200
  17. screen = pygame.display.set_mode(bg_size)
  18. pygame.display.set_caption("Music - Python Demo")
  19. #设置 暂停 标记
  20. pause = False
  21. #显示播放和暂停图片
  22. pause_image = pygame.image.load("pause.png").convert_alpha()
  23. unpause_image = pygame.image.load("unpause.png").convert_alpha()
  24. pause_rect = pause_image.get_rect()
  25. pause_rect.left, pause_rect.top = (width - pause_rect.width) // 2, (height - pause_rect.height) // 2#居窗口正中央
  26. clock = pygame.time.Clock() #帧率
  27. while True:
  28. for event in pygame.event.get():
  29. if event.type == QUIT:
  30. sys.exit()
  31. if event.type == MOUSEBUTTONDOWN:
  32. if event.button == 1: #鼠标左键
  33. winner_sound.play()
  34. if event.button == 3: #鼠标右键
  35. loser_sound.play()
  36. if event.type == KEYDOWN:
  37. if event.key == K_SPACE: #空格键
  38. pause = not pause
  39. screen.fill((255, 255, 255)) #窗口背景白色
  40. if pause: #暂停
  41. screen.blit(pause_image, pause_rect)
  42. pygame.mixer.music.pause()
  43. else: #播放
  44. screen.blit(unpause_image, pause_rect)
  45. pygame.mixer.music.unpause()
  46. pygame.display.flip() #刷新窗口
  47. clock.tick(30)#帧率
上面就是我們實現music 模塊的Demo。
現在我們就來把我們學到的新東西加到Play TheBall 小遊戲中。我們繼續完善我們的代碼:
代碼如下:(需要素材的可以在評論區留下郵箱)
  1. import pygame
  2. import sys
  3. from pygame.locals import *
  4. from random import *
  5. # 球类继承自Spirte类
  6. class Ball(pygame.sprite.Sprite):
  7. def __init__(self, image, position, speed, bg_size):
  8. # 初始化动画精灵
  9. pygame.sprite.Sprite.__init__(self)
  10. self.image = pygame.image.load(image).convert_alpha()
  11. self.rect = self.image.get_rect()
  12. # 将小球放在指定位置
  13. self.rect.left, self.rect.top = position
  14. self.speed = speed
  15. self.width, self.height = bg_size[0], bg_size[1]
  16. self.radius = self.rect.width / 2 #增加半径属性
  17. def move(self):
  18. self.rect = self.rect.move(self.speed)
  19. # 如果小球的左侧出了边界,那么将小球左侧的位置改为右侧的边界
  20. # 这样便实现了从左边进入,右边出来的效果
  21. if self.rect.right < 0:
  22. self.rect.left = self.width
  23. elif self.rect.left > self.width:
  24. self.rect.right = 0
  25. elif self.rect.bottom < 0:
  26. self.rect.top = self.height
  27. elif self.rect.top > self.height:
  28. self.rect.bottom = 0
  29. def main():
  30. pygame.init()
  31. ball_image = "gray_ball.png"
  32. bg_image = "background.png"
  33. running = True
  34. ##############################################################
  35. #添加背景音乐
  36. pygame.mixer.music.load('bg_music.ogg')
  37. pygame.mixer.music.set_volume(0.2)#设置音量
  38. pygame.mixer.music.play()#播放
  39. #加载音效
  40. winner_sound = pygame.mixer.Sound("winner.wav")
  41. winner_sound.set_volume(0.2)
  42. loser_sound = pygame.mixer.Sound("loser.wav")
  43. loser_sound.set_volume(0.2)
  44. laugh_sound = pygame.mixer.Sound("laugh.wav")
  45. laugh_sound.set_volume(0.2)
  46. hole_sound = pygame.mixer.Sound("hole.wav")
  47. hole_sound.set_volume(0.2)
  48. #背景音乐会贯穿游戏的始终,背景音乐完整播放一次我们视为游戏的时间,
  49. #因此我们需要想办法让游戏在背景音乐停止时结束,我们应该有留意到:
  50. #music 模块有一个 set_endevent() 方法,该方法的作用就是在音乐播放完时
  51. #发送一条事件消息,发送什么消息是我们自定义的,USEREVENT 就是自定义消息,
  52. #Pygame 给我们预定了很多事件,像我们熟悉的 键盘事件、鼠标事件等。这些预定义
  53. #的事件都有一个标记符,例如:MOUSEBUTTONDOWN 、KEYDOWN等。这些都是
  54. #一些数字的等值定义,其实在内部,2 就表示鼠标按下,但是人类难以记住,所以定义为
  55. #MOUSEBUTTONDOWN。
  56. #USEREVENT 就是数字24,24以上就是我们可以自定义的事件,我们可以像这样自定义事件:
  57. # MY_EVENT = USEREVENT。
  58. # MY_EVENT_1 = USEREVENT + 1........
  59. #音乐播放完时,游戏结束
  60. GAMEOVER = USEREVENT
  61. pygame.mixer.music.set_endevent(GAMEOVER)
  62. ##############################################################
  63. # 根据背景图片指定游戏界面尺寸
  64. bg_size = width, height = 1024, 681
  65. screen = pygame.display.set_mode(bg_size)
  66. pygame.display.set_caption("Play the ball - Python Demo")
  67. background = pygame.image.load(bg_image).convert_alpha()
  68. # 用来存放小球对象的列表
  69. balls = []
  70. group = pygame.sprite.Group()
  71. # 创建五个小球
  72. for i in range(5):
  73. # 位置随机,速度随机
  74. position = randint(0, width-100), randint(0, height-100)
  75. speed = [randint(-10, 10), randint(-10, 10)]
  76. ball = Ball(ball_image, position, speed, bg_size)
  77. while pygame.sprite.spritecollide(ball, group, False, pygame.sprite.collide_circle):#在创建小球这里必须进行一下碰撞检测
  78. ball.rect.left, ball.rect.top = randint(0, width-100), randint(0, height-100)
  79. balls.append(ball)
  80. group.add(ball)
  81. clock = pygame.time.Clock()
  82. while running:
  83. for event in pygame.event.get():
  84. if event.type == QUIT:
  85. sys.exit()
  86. #####################################################################
  87. elif event.type == GAMEOVER: #判断事件是否为我们自定义的GAMEOVER事件
  88. loser_sound.play()
  89. pygame.time.delay(2000)#暂停2秒
  90. laugh_sound.play()
  91. running = False
  92. #####################################################################
  93. screen.blit(background, (0, 0))
  94. for each in balls:
  95. each.move()
  96. screen.blit(each.image, each.rect)
  97. for each in group:
  98. group.remove(each) #把自身拿出来
  99. if pygame.sprite.spritecollide(each, group, False, pygame.sprite.collide_circle):#把自己和别的球进行碰撞检测
  100. each.speed[0] = -each.speed[0]
  101. each.speed[1] = -each.speed[1]
  102. group.add(each)#还要把自己放进去
  103. pygame.display.flip()
  104. clock.tick(30)
  105. if __name__ == "__main__":
  106. main()
有一點需要講解的:
背景音樂會貫穿遊戲的始終,背景音樂完整播放一次我們視為遊戲的時間,因此我們需要想辦法讓遊戲在背景音樂停止時結束,我們應該有留意到:
music 模塊有一個set_endevent() 方法,該方法的作用就是在音樂播放完時發送一條事件消息,發送什麼消息是我們自定義的,USEREVENT 就是自定義消息,Pygame 給我們預定了很多事件,像我們熟悉的鍵盤事件、鼠標事件等。這些預定義的事件都有一個標記符,
例如:MOUSEBUTTONDOWN 、KEYDOWN等。這些都是一些數字的等值定義,其實在內部,2 就表示鼠標按下,但是人類難以記住,所以定義為 MOUSEBUTTONDOWN。
USEREVENT 就是數字24,24以上就是我們可以自定義的事件,我們可以像這樣自定義事件:
     MY_EVENT = USEREVENT。
     MY_EVENT_1 = USEREVENT + 1........

0 留言:

發佈留言