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

本网站用的阿里云ECS,推荐大家用。自己搞个学习研究也不错
原文出处: eyeHere   

辛苦啦~ 这次是我们系统的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书写一个真正可以玩的游戏,敬请期待~~

本次使用的几个图像文件打包下载(也可以自己找更帅的)。

1 赞
收藏

评论





转载自演道,想查看更及时的互联网产品技术热点文章请点击http://go2live.cn

未经允许不得转载:演道网 » 用Python和Pygame写游戏-从入门到精通(22)

赞 (0)
分享到:更多 ()