本文转自:http://eyehere.net/2011/python-pygame-novice-professional-22/

辛苦啦~ 这次是我们系统的pygame理论学习的最后一章了,把这次的音乐播放讲完了,pygame的基础知识就全部OK了。不过作为完整的教程,只有理论讲解太过枯燥了,我随后还会加一个或更多的实践篇系列,看需要可能也会追加真3D等额外的内容。

就像上次所说的,pygame.mixer并不适合播放长时间的音乐播放,我们要使用pygame.mixer.music。

pygame.mixer.music用来播放MP3和OGG音乐文件,不过MP3并不是所有的系统都支持(Linux默认就不支持MP3播放),所以最好还是都用Ogg文件,我们可以很容易把MP3转换为Ogg文件,自己搜一下吧。

我们使用pygame.mixer.music.load()来加载一个文件,然后使用pygame.mixer.music.play()来播放,这里并没有一个类似Music这样的类和对象,因为背景音乐一般般只要有一个在播放就好了不是么~不放的时候就用stop()方法来停止就好了,当然很自然有类似录影机上的pause()和unpause()方法。

音效和音乐方法总结

Sound对象:

方法名 作用
fadeout 淡出声音,可接受一个数字(毫秒)作为淡出时间
get_length 获得声音文件长度,以秒计
get_num_channels 声音要播放多少次
get_volume 获取音量(0.0 ~ 1.0)
play 开始播放,返回一个Channel对象,失败则返回None
set_volume 设置音量
stop 立刻停止播放

Channels对象:

方法名 作用
fadeout 类似
get_busy 如果正在播放,返回true
get_endevent 获取播放完毕时要做的event,没有则为None
get_queue 获取队列中的声音,没有则为None
get_volume 类似
pause 暂停播放
play 类似
queue 将一个Sound对象加入队列,在当前声音播放完毕后播放
set_endevent 设置播放完毕时要做的event
set_volume 类似
stop 立刻停止播放
unpause 继续播放

Music对象:

方法名 作用
fadeout 类似
get_endevent 类似
get_volume 类似
load 加载一个音乐文件
pause 类似
play 类似
rewind 从头开始重新播放
set_endevent 类似
set_volume 类似
stop 立刻停止播放
unpause 继续播放
get_pos 获得当前播放的位置,毫秒计

虽然很简单,不过还是提供一个例程吧,这里面音乐的播放很简单,就是上面讲过的,不过其中还有一点其他的东西,希望大家学习一下pygame中按钮的实现方法。

界面如上,运行的时候,脚本读取./MUSIC下所有的OGG和MP3文件(如果你不是Windows,可能要去掉MP3的判断),显示的也很简单,几个控制按钮,下面显示当前歌名(显示中文总是不那么方便的,如果你运行失败,请具体参考代码内的注释自己修改):

  1. # -*- coding: utf-8 -*-
  2. # 注意文件编码也必须是utf-8
  3. SCREEN_SIZE = (800, 600)
  4. # 存放音乐文件的位置
  5. MUSIC_PATH = “./MUSIC”
  6. import pygame
  7. from pygame.locals import *
  8. from math import sqrt
  9. import os
  10. import os.path
  11. def get_music(path):
  12. # 从文件夹来读取所有的音乐文件
  13. raw_filenames = os.listdir(path)
  14. music_files = []
  15. for filename in raw_filenames:
  16. # 不是Windows的话,还是去掉mp3吧
  17. if filename.lower().endswith(‘.ogg’) or filename.lower().endswith(‘.mp3’):
  18. music_files.append(os.path.join(MUSIC_PATH, filename))
  19. return sorted(music_files)
  20. class Button(object):
  21. “”“这个类是一个按钮,具有自我渲染和判断是否被按上的功能”“”
  22. def __init__(self, image_filename, position):
  23. self.position = position
  24. self.image = pygame.image.load(image_filename)
  25. def render(self, surface):
  26. # 家常便饭的代码了
  27. x, y = self.position
  28. w, h = self.image.get_size()
  29. x -= w / 2
  30. y -= h / 2
  31. surface.blit(self.image, (x, y))
  32. def is_over(self, point):
  33. # 如果point在自身范围内,返回True
  34. point_x, point_y = point
  35. x, y = self.position
  36. w, h = self.image.get_size()
  37. x -= w /2
  38. y -= h / 2
  39. in_x = point_x >= x and point_x < x + w
  40. in_y = point_y >= y and point_y < y + h
  41. return in_x and in_y
  42. def run():
  43. pygame.mixer.pre_init(44100, 16, 2, 1024*4)
  44. pygame.init()
  45. screen = pygame.display.set_mode(SCREEN_SIZE, 0)
  46. #font = pygame.font.SysFont(“default_font”, 50, False)
  47. # 为了显示中文,我这里使用了这个字体,具体自己机器上的中文字体请自己查询
  48. # 详见本系列第四部分:http://eyehere.net/2011/python-pygame-novice-professional-4/
  49. font = pygame.font.SysFont(“simsunnsimsun”, 50, False)
  50. x = 100
  51. y = 240
  52. button_width = 150
  53. buttons = {}
  54. buttons[“prev”] = Button(“prev.png”, (x, y))
  55. buttons[“pause”] = Button(“pause.png”, (x+button_width*1, y))
  56. buttons[“stop”] = Button(“stop.png”, (x+button_width*2, y))
  57. buttons[“play”] = Button(“play.png”, (x+button_width*3, y))
  58. buttons[“next”] = Button(“next.png”, (x+button_width*4, y))
  59. music_filenames = get_music(MUSIC_PATH)
  60. if len(music_filenames) == 0:
  61. print “No music files found in “, MUSIC_PATH
  62. return
  63. white = (255, 255, 255)
  64. label_surfaces = []
  65. # 一系列的文件名render
  66. for filename in music_filenames:
  67. txt = os.path.split(filename)[-1]
  68. print “Track:”, txt
  69. # 这是简体中文Windows下的文件编码,根据自己系统情况请酌情更改
  70. txt = txt.split(‘.’)[0].decode(‘gb2312’)
  71. surface = font.render(txt, True, (100, 0, 100))
  72. label_surfaces.append(surface)
  73. current_track = 0
  74. max_tracks = len(music_filenames)
  75. pygame.mixer.music.load( music_filenames[current_track] )
  76. clock = pygame.time.Clock()
  77. playing = False
  78. paused = False
  79. # USEREVENT是什么?请参考本系列第二部分:
  80. # http://eyehere.net/2011/python-pygame-novice-professional-2/
  81. TRACK_END = USEREVENT + 1
  82. pygame.mixer.music.set_endevent(TRACK_END)
  83. while True:
  84. button_pressed = None
  85. for event in pygame.event.get():
  86. if event.type == QUIT:
  87. return
  88. if event.type == MOUSEBUTTONDOWN:
  89. # 判断哪个按钮被按下
  90. for button_name, button in buttons.iteritems():
  91. if button.is_over(event.pos):
  92. print button_name, “pressed”
  93. button_pressed = button_name
  94. break
  95. if event.type == TRACK_END:
  96. # 如果一曲播放结束,就“模拟”按下”next”
  97. button_pressed = “next”
  98. if button_pressed is not None:
  99. if button_pressed == “next”:
  100. current_track = (current_track + 1) % max_tracks
  101. pygame.mixer.music.load( music_filenames[current_track] )
  102. if playing:
  103. pygame.mixer.music.play()
  104. elif button_pressed == “prev”:
  105. # prev的处理方法:
  106. # 已经播放超过3秒,从头开始,否则就播放上一曲
  107. if pygame.mixer.music.get_pos() > 3000:
  108. pygame.mixer.music.stop()
  109. pygame.mixer.music.play()
  110. else:
  111. current_track = (current_track - 1) % max_tracks
  112. pygame.mixer.music.load( music_filenames[current_track] )
  113. if playing:
  114. pygame.mixer.music.play()
  115. elif button_pressed == “pause”:
  116. if paused:
  117. pygame.mixer.music.unpause()
  118. paused = False
  119. else:
  120. pygame.mixer.music.pause()
  121. paused = True
  122. elif button_pressed == “stop”:
  123. pygame.mixer.music.stop()
  124. playing = False
  125. elif button_pressed == “play”:
  126. if paused:
  127. pygame.mixer.music.unpause()
  128. paused = False
  129. else:
  130. if not playing:
  131. pygame.mixer.music.play()
  132. playing = True
  133. screen.fill(white)
  134. # 写一下当前歌名
  135. label = label_surfaces[current_track]
  136. w, h = label.get_size()
  137. screen_w = SCREEN_SIZE[0]
  138. screen.blit(label, ((screen_w - w)/2, 450))
  139. # 画所有按钮
  140. for button in buttons.values():
  141. button.render(screen)
  142. # 因为基本是不动的,这里帧率设的很低
  143. clock.tick(5)
  144. pygame.display.update()
  145. if __name__ == “__main__”:
  146. run()

这个程序虽然可以运行,还是很简陋,有兴趣的可以改改,比如显示播放时间/总长度,甚至更厉害一点,鼠标移动到按钮上班,按钮会产生一点变化等等,我们现在已经什么都学过了,唯一欠缺的就是实践而已!

所以下一次,我将开始一个实战篇,用pygame书写一个真正可以玩的游戏,敬请期待~~

如何用Pygame写游戏(二十二)相关推荐

  1. 如何用Pygame写游戏(十)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-10/ 有时候无聊在网上翻翻小说看看,绝大多数那叫一个无聊.比如说修炼的境 ...

  2. 如何用Pygame写游戏(十九)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-19/ 3D世界 让我们现在开始写一个3D的程序,巩固一下这几次学习的东西 ...

  3. 如何用Pygame写游戏(十八)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-18/ 3D是非常酷的技术,同时也就意味着更多的工作,上次的简单介绍之后, ...

  4. 如何用Pygame写游戏(十六)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-16/ 经历了长年的艰苦卓绝的披星戴月的惨绝人寰的跋山涉水,我们终于接近了 ...

  5. 如何用Pygame写游戏(十四)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-14/ 上一次稍微说了一下AI,为了更好的理解它,我们必须明白什么是状态机 ...

  6. 如何用Pygame写游戏(十五)

    本文转自: http://eyehere.net/2011/python-pygame-novice-professional-15/ 在继续我们的AI之旅前,分享一个在煎蛋上看到的有趣新闻,能通过读 ...

  7. 如何用Pygame写游戏(一)

    转载地址:http://eyehere.net/2011/python-pygame-novice-professional-1/ Pygame的历史  Pygame是一个利用SDL库的写就的游戏 ...

  8. 如何用Pygame写游戏(二十)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-20/ 声音是游戏中必要的元素之一,音效可以给予用户良好的反馈体验.赛车的 ...

  9. 如何用Pygame写游戏(二)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-2/ 上次我们试着写了一个最简单的Pygame程序并且解释了一个大概的框架 ...

最新文章

  1. Test class should have exactly one public constructor解决办法
  2. ArcGIS Server 9.2 on Solaris/Linux 安装可能出现的问题
  3. 如何控制C#Socket的连接超时时间
  4. Win10:tensorflow学习笔记(4)
  5. C语言中的结构体,联合,链表和枚举,位域(上)
  6. 三维重建11:点云的全局特征和局部特征
  7. SAP Spartacus 读取 Cart 的原理分析
  8. Activiti5第七弹,自己实现一个ProcessEngineConfiguration同时自定义拦截器
  9. 【jQuery笔记Part1】06-jQuery对象与js对象转换
  10. php用curl调用接口方法,get和post两种方式
  11. OpenStack KVM环境搭建
  12. Solr6 快速入门教程
  13. 关于‘挖矿’minerd
  14. 6. JavaScript String 对象
  15. mac nginx 指定php.ini,基于Mac自带nginx、php,配置php运行环境
  16. Python的类和继承中的属性变量
  17. 示坡线高程判断_地理示坡线
  18. 线性代数笔记5.3实对称矩阵的对角化
  19. 论文笔记:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
  20. Vue美食杰项目个人主页

热门文章

  1. C++:类访问修饰符
  2. linux内核那些事之mmap
  3. 笨方法“学习python笔记之字典
  4. libpng warning: iCCP: known incorrect sRGB profile
  5. ExtJS4.2 menu鼠标移开隐藏
  6. keil如何添加h文件_如何给PDF文件添加水印?分享给PDF批量加水印的方法
  7. phpcmsV9各种模板页面调用文章 hits 点击量和评论量 - 代码总结分类
  8. 响应式多终端挖掘机机械设备展示类网站模板
  9. 多个redistemplate_Spring boot 使用多个RedisTemplate
  10. java for update 无效_java.sql.BatchUpdateException:调用中的无效参数