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

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

2015-06-01 21:28 861 查看
本文转载自:http://eyehere.net/2011/python-pygame-novice-professional-21/

紧接着上一次,我们继续来看如何在Pygame中使用声音。




Sound对象

在初始化声音系统之后,我们就可以读取一个音乐文件到一个Sound对象中了。pygame.mixer.Sound()接受一个文件名,或者也可以使一个文件对象,不过这个文件必须是WAV或者OGG,切记!

Python

1hello_sound = Pygame.mixer.Sound("hello.ogg")
一旦这个Sound对象出来了,你可以使用play方法来播放它。play(loop, maxtime)可以接受两个参数,loop自然就是重复的次数,-1意味着无限循环,1呢?是两次,记住是重复的次数而不是播放的次数;maxtime是指多少毫秒后结束,这个很简单。当你不使用任何参数调用的时候,意味着把这个声音播放一次。一旦play方法调用成功,就会返回一个Channel对象,否则返回一个None。

Channel对象

Channel,也就是声道,可以被声卡混合(共同)播放的数据流。游戏中可以同时播放的声音应该是有限的,pygame中默认是8个,你可以通过pygame.mixer.get_num_channels()来得知当前系统可以同时播放的声道数,而一旦超过,调用sound对象的play方法就会返回一个None,如果你确定自己要同时播放很多声音,可以用set_num_channels()来设定一下,最好一开始就设,因为重新设定会停止当前播放的声音。那么Channel对象有什么用呢?如果你只是想简单的播放一下声音,那么根本不用管这个东西,不过如果你想创造出一点有意境的声音,比如说一辆火车从左到右呼啸而过,那么应该是一开始左声道比较响,然后相当,最后右声道比较响,直至慢慢消失。这就是Channel能做到的事情。Channel的set_volume(left, right)方法接受两个参数,分别是代表左声道和右声道的音量的小数,从0.0~1.0。

竖起我们的耳朵

OK,来个例子试试吧~这个例子里我们通过释放金属小球并让它们自由落体和弹跳,听碰撞的声音。这里面不仅仅有这次学习的声音,还有几个一起没有接触到的技术,最重要的一个就是重力的模拟,我们可以设置一个重力因子来影响小球下落的速度,还有一个弹力系数,来决定每次弹跳损失的能量,虽然不难,但是游戏中引入这个东西能让我们的游戏仿真度大大提高。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

SCREEN_SIZE
=
(640,
480)

# 重力因子,实际上是单位
像素/平方秒

GRAVITY
=
250.0

# 弹力系数,不要超过1!

BOUNCINESS
=
0.7

import
pygame

from
pygame.locals
import
*

from
random
import
randint

from
gameobjects.vector2
import
Vector2

def
stero_pan(x_coord,
screen_width):

"""这个函数根据位置决定要播放声音左右声道的音量"""

right_volume
=
float(x_coord)
/
screen_width

left_volume
=
1.0
-
right_volume

return
(left_volume,
right_volume)

class
Ball():

"""小球类,实际上我们可以使用Sprite类来简化"""

def
__init__(self,
position,
speed,
image,
bounce_sound):

self.position
=
Vector2(position)

self.speed
=
Vector2(speed)

self.image
=
image

self.bounce_sound
=
bounce_sound

self.age
=
0.0

def
update(self,
time_passed):

w,
h
=
self.image.get_size()

screen_width,
screen_height
=
SCREEN_SIZE

x,
y
=
self.position

x
-=
w/2

y
-=
h/2

#
是不是要反弹了

bounce
=
False

#
小球碰壁了么?

if
y
+
h
>=
screen_height:

self.speed.y
=
-self.speed.y
*
BOUNCINESS

self.position.y
=
screen_height
-
h
/
2.0
-
1.0

bounce
=
True

if
x
<=
0:

self.speed.x
=
-self.speed.x
*
BOUNCINESS

self.position.x
=
w
/
2.0
+
1

bounce
=
True

elif
x
+
w
>=
screen_width:

self.speed.x
=
-self.speed.x
*
BOUNCINESS

self.position.x
=
screen_width
-
w
/
2.0
-
1

bounce
=
True

#
根据时间计算现在的位置,物理好的立刻发现这其实不标准,

#
正规的应该是“s = 1/2*g*t*t”,不过这样省事省时一点,咱只是模拟~

self.position
+=
self.speed
*
time_passed

#
根据重力计算速度

self.speed.y
+=
time_passed
*
GRAVITY

if
bounce:

self.play_bounce_sound()

self.age
+=
time_passed

def
play_bounce_sound(self):

"""这个就是播放声音的函数"""

channel
=
self.bounce_sound.play()

if
channel
is
not
None:

#
设置左右声道的音量

left,
right
=
stero_pan(self.position.x,
SCREEN_SIZE[0])

channel.set_volume(left,
right)

def
render(self,
surface):

#
真有点麻烦了,有爱的,自己用Sprite改写下吧……

w,
h
=
self.image.get_size()

x,
y
=
self.position

x
-=
w/2

y
-=
h/2

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

def
run():

#
上一次的内容

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

pygame.init()

pygame.mixer.set_num_channels(8)

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

pygame.mouse.set_visible(False)

clock
=
pygame.time.Clock()

ball_image
=
pygame.image.load("ball.png").convert_alpha()

mouse_image
=
pygame.image.load("mousecursor.png").convert_alpha()

#
加载声音文件

bounce_sound
=
pygame.mixer.Sound("bounce.ogg")

balls
=
[]

while
True:

for
event
in
pygame.event.get():

if
event.type
==
QUIT:

return

if
event.type
==
MOUSEBUTTONDOWN:

#
刚刚出来的小球,给一个随机的速度

random_speed
=
(
randint(-400,
400),
randint(-300,
0)
)

new_ball
=
Ball(
event.pos,

random_speed,

ball_image,

bounce_sound
)

balls.append(new_ball)

time_passed_seconds
=
clock.tick()
/
1000.

screen.fill((255,
255,
255))

#
为防止小球太多,把超过寿命的小球加入这个“死亡名单”

dead_balls
=
[]

for
ball
in
balls:

ball.update(time_passed_seconds)

ball.render(screen)

#
每个小球的的寿命是10秒

if
ball.age
>
10.0:

dead_balls.append(ball)

for
ball
in
dead_balls:

balls.remove(ball)

mouse_pos
=
pygame.mouse.get_pos()

screen.blit(mouse_image,
mouse_pos)

pygame.display.update()

if
__name__
==
"__main__":

run()

这么久了,咱们的游戏终于有了声音,太棒了!不过,是不是游戏的背景音乐也是用mixer来播放的呢?这不是一个好主意,因为背景音乐往往很长,比较占资源,pygame中另外提供了一个pygame.mixer.music类来控制背景音乐的播放,这也是我们下一次要讲的内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: