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

来源:互联网 发布:sql 数据库链接 编辑:程序博客网 时间:2024/05/02 02:36

本文转自: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对象,失败则返回Noneset_volume设置音量stop立刻停止播放

Channels对象

方法名作用fadeout类似get_busy如果正在播放,返回trueget_endevent获取播放完毕时要做的event,没有则为Noneget_queue获取队列中的声音,没有则为Noneget_volume类似pause暂停播放play类似queue将一个Sound对象加入队列,在当前声音播放完毕后播放set_endevent设置播放完毕时要做的eventset_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的判断),显示的也很简单,几个控制按钮,下面显示当前歌名(显示中文总是不那么方便的,如果你运行失败,请具体参考代码内的注释自己修改):

# -*- coding: utf-8 -*-# 注意文件编码也必须是utf-8SCREEN_SIZE = (800, 600)# 存放音乐文件的位置MUSIC_PATH = "./MUSIC"import pygamefrom pygame.locals import *from math import sqrtimport osimport os.pathdef 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_ydef 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)    # 为了显示中文,我这里使用了这个字体,具体自己机器上的中文字体请自己查询    # 详见本系列第四部分:http://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是什么?请参考本系列第二部分:    # http://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书写一个真正可以玩的游戏,敬请期待~~






0 0
原创粉丝点击