您的位置:首页 > 编程语言 > Python开发

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

2015-06-25 21:25 295 查看

辛苦啦~ 这次是我们系统的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的判断),显示的也很简单,几个控制按钮,下面显示当前歌名(显示中文总是不那么方便的,如果你运行失败,请具体参考代码内的注释自己修改):

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

#
-*- coding: utf-8 -*-

#
注意文件编码也必须是utf-8

SCREEN_SIZE
=
(800,
600)

#
存放音乐文件的位置

MUSIC_PATH
=
"./MUSIC"

import
pygame

from
pygame.locals
import
*

from
math
import
sqrt

import
os

import
os.path

def
get_music(path):

#
从文件夹来读取所有的音乐文件

raw_filenames
=
os.listdir(path)

music_files
=
[]

for
filename
in
raw_filenames:

#
不是Windows的话,还是去掉mp3吧

if
filename.lower().endswith('.ogg')
or
filename.lower().endswith('.mp3'):

music_files.append(os.path.join(MUSIC_PATH,
filename))

return
sorted(music_files)

class
Button(object):

"""这个类是一个按钮,具有自我渲染和判断是否被按上的功能"""

def
__init__(self,
image_filename,
position):

self.position
=
position

self.image
=
pygame.image.load(image_filename)

def
render(self,
surface):

#
家常便饭的代码了

x,
y
=
self.position

w,
h
=
self.image.get_size()

x
-=
w
/
2

y
-=
h
/
2

surface.blit(self.image,
(x,
y))

def
is_over(self,
point):

#
如果point在自身范围内,返回True

point_x,
point_y
=
point

x,
y
=
self.position

w,
h
=
self.image.get_size()

x
-=
w
/2

y
-=
h
/
2

in_x
=
point_x
>=
x
and
point_x
<
x
+
w

in_y
=
point_y
>=
y
and
point_y
<
y
+
h

return
in_x
and
in_y

def
run():

pygame.mixer.pre_init(44100,
16,
2,
1024*4)

pygame.init()

screen
=
pygame.display.set_mode(SCREEN_SIZE,
0)

#font
= pygame.font.SysFont("default_font", 50, False)

#
为了显示中文,我这里使用了这个字体,具体自己机器上的中文字体请自己查询

#
详见本系列第四部分://eyehere.net/2011/python-pygame-novice-professional-4/

font
=
pygame.font.SysFont("simsunnsimsun",
50,
False)

x
=
100

y
=
240

button_width
=
150

buttons
=
{}

buttons["prev"]
=
Button("prev.png",
(x,
y))

buttons["pause"]
=
Button("pause.png",
(x+button_width*1,
y))

buttons["stop"]
=
Button("stop.png",
(x+button_width*2,
y))

buttons["play"]
=
Button("play.png",
(x+button_width*3,
y))

buttons["next"]
=
Button("next.png",
(x+button_width*4,
y))

music_filenames
=
get_music(MUSIC_PATH)

if
len(music_filenames)
==
0:

print
"No
music files found in ",
MUSIC_PATH

return

white
=
(255,
255,
255)

label_surfaces
=
[]

#
一系列的文件名render

for
filename
in
music_filenames:

txt
=
os.path.split(filename)[-1]

print
"Track:",
txt

#
这是简体中文Windows下的文件编码,根据自己系统情况请酌情更改

txt
=
txt.split('.')[0].decode('gb2312')

surface
=
font.render(txt,
True,
(100,
0,
100))

label_surfaces.append(surface)

current_track
=
0

max_tracks
=
len(music_filenames)

pygame.mixer.music.load(
music_filenames[current_track]
)

clock
=
pygame.time.Clock()

playing
=
False

paused
=
False

#
USEREVENT是什么?请参考本系列第二部分:

#
//eyehere.net/2011/python-pygame-novice-professional-2/

TRACK_END
=
USEREVENT
+
1

pygame.mixer.music.set_endevent(TRACK_END)

while
True:

button_pressed
=
None

for
event
in
pygame.event.get():

if
event.type
==
QUIT:

return

if
event.type
==
MOUSEBUTTONDOWN:

#
判断哪个按钮被按下

for
button_name,
button
in
buttons.iteritems():

if
button.is_over(event.pos):

print
button_name,
"pressed"

button_pressed
=
button_name

break

if
event.type
==
TRACK_END:

#
如果一曲播放结束,就“模拟”按下"next"

button_pressed
=
"next"

if
button_pressed
is
not
None:

if
button_pressed
==
"next":

current_track
=
(current_track
+
1)
%
max_tracks

pygame.mixer.music.load(
music_filenames[current_track]
)

if
playing:

pygame.mixer.music.play()

elif
button_pressed
==
"prev":

#
prev的处理方法:

#
已经播放超过3秒,从头开始,否则就播放上一曲

if
pygame.mixer.music.get_pos()
>
3000:

pygame.mixer.music.stop()

pygame.mixer.music.play()

else:

current_track
=
(current_track
-
1)
%
max_tracks

pygame.mixer.music.load(
music_filenames[current_track]
)

if
playing:

pygame.mixer.music.play()

elif
button_pressed
==
"pause":

if
paused:

pygame.mixer.music.unpause()

paused
=
False

else:

pygame.mixer.music.pause()

paused
=
True

elif
button_pressed
==
"stop":

pygame.mixer.music.stop()

playing
=
False

elif
button_pressed
==
"play":

if
paused:

pygame.mixer.music.unpause()

paused
=
False

else:

if
not
playing:

pygame.mixer.music.play()

playing
=
True

screen.fill(white)

#
写一下当前歌名

label
=
label_surfaces[current_track]

w,
h
=
label.get_size()

screen_w
=
SCREEN_SIZE[0]

screen.blit(label,
((screen_w
-
w)/2,
450))

#
画所有按钮

for
button
in
buttons.values():

button.render(screen)

#
因为基本是不动的,这里帧率设的很低

clock.tick(5)

pygame.display.update()

if
__name__
==
"__main__":

run()

这个程序虽然可以运行,还是很简陋,有兴趣的可以改改,比如显示播放时间/总长度,甚至更厉害一点,鼠标移动到按钮上班,按钮会产生一点变化等等,我们现在已经什么都学过了,唯一欠缺的就是实践而已!
所以下一次,我将开始一个实战篇,用pygame书写一个真正可以玩的游戏,敬请期待~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: