多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
>在Scratch中,小猫是可以唱歌的,而且Scratch的声音木块有着丰富的功能,在这方面Python turtle略有欠缺,今天我们就来完善一下. ![Scratch声音模块](http://upload-images.jianshu.io/upload_images/1108512-cfdae465c49e3e70.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ## Python声音模块 ![Python有关声音的库有639种,可以完成非常复杂的功能的](http://upload-images.jianshu.io/upload_images/1108512-6474443ff821573e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) Python处理声音的模块很多,但是我们要实现的功能并不复杂,所以只需要用到```winsound```这个系统自带的模块就好了.我们要的只是实现类似scratch的功能,用不到很复杂的功能的,当然Python能够做的比scratch多多了. ## Python turtle的代码结构 最近一直在阅读python turtle的源代码对于Python源代码的结构有所了解,针对造型的操作也重新定义了一些函数来与scratch的积木块相对应。 在Python turtle基础上进行扩充而不是使用Pygame、Pyglet等复杂的库是因为Python turtle本身为了教小孩子编程设计的,在结构上更加符合小孩子的学习习惯,对交互式编程友好,而pygame和pyglet不具备这两个特点。 ![Python Turtle的代码结构图](http://upload-images.jianshu.io/upload_images/1108512-24f2ff8343e5fd31.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ``` class RawTurtle(TPen, TNavigator): # 小乌龟的动画部分 # 为何添加的函数不工作呢 """Animation part of the RawTurtle. Puts RawTurtle upon a TurtleScreen and provides tools for its animation. """ ``` 其中核心的turtle继承自RawTurtle类,而RawTurtle继承自TPen和TNavigator,两个类分别控制画笔的绘制和移动,简单的来说TPen承载的是类似Scratch中画笔积木类的功能,而TNavigator更多的承载了动作积木类的功能。 ![TNavigator](http://upload-images.jianshu.io/upload_images/1108512-279d6da6d352ff6e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![TNavigator更多的承载了类似动作积木类的功能](http://upload-images.jianshu.io/upload_images/1108512-28fe1ce598005b69.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![TNavigator](http://upload-images.jianshu.io/upload_images/1108512-a9cb8b16399f0b06.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![Tpen](http://upload-images.jianshu.io/upload_images/1108512-d13a42df2b02f7fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![TPen更多的实现了画笔分类的功能](http://upload-images.jianshu.io/upload_images/1108512-ee8cf247c7fef79f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![TPen更多的实现了画笔分类的功能](http://upload-images.jianshu.io/upload_images/1108512-5aae07e293da8a6d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 上面两组功能是否很相似呢。 所以要实现Python turtle的声音功能,只要重新写一个声音相关的类,然后让```RawTurtle```继承这个声音类就ok了,当然还要注意一个问题,turtle所有的类都要加入到```_tg_turtle_functions```这个列表中,这个列表保存了turtle所有的方法,**用来保证在交互式命令行里,默认turtle的各种方法可以直接作为函数调用**. ![image.png](http://upload-images.jianshu.io/upload_images/1108512-48e11f8e361b641b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 让我们开工把 ## 实现TSound类 ### Scratch积木块对应的Python 我们一步步的来实现 ![导入```winsound```库并生命类](http://upload-images.jianshu.io/upload_images/1108512-3a7097265f3ac3b7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 对[winsound](https://docs.python.org/2/library/winsound.html)模块的同学,可以访问其在官方的文档,这里介绍播放声音的方法: ``` winsound.PlaySound('d:\coding\maow.wav',winsound.SND_FILENAME) # 第一个参数是文件的完整路径,第二个是播放的标志,winsound.SND_FILENAME代表的是播放的是文件 ``` 首先我们导入winsound模块之后,然后利用这个模块的```PlaySound```方法播放指定的声音文件这样就实现了 ![播放直到完毕](http://upload-images.jianshu.io/upload_images/1108512-5d2f26304bf04c91.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 停止声音的办法是: ``` winsound.PlaySound(None, winsound.SND_PURGE) ``` 对应的是 ![停止所有声音模块](http://upload-images.jianshu.io/upload_images/1108512-ce7580074670c9b9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 默认的声音播放方式是同步的,也就是说播放声音的时候程序啥也不能干,如下面播放5分钟的音频: ``` import winsound as s s.PlaySound("d:\coding\sound.wav",s.SND_FILENAME) print('Playing ended!') ``` 如果这五分钟的音频sound.wav没有播放完毕,程序啥也不能干,尬不尬. 这个积木块比较霸道,要求必须等他做完了才可以,本来就相当于你跟你女朋友打电话,一般我是边打电话边做事情,但是女朋友呢非得要求你啥也不能做,直到电话打完,不然就是不尊重她,不爱她,真尬.当然了少年们,跟女朋友打电话的时候一定不要做别的事情哦. 如何实现异步播放声音呢,毕竟我们是热爱时间的好少年. ![播放声音](http://upload-images.jianshu.io/upload_images/1108512-0cdde800a1c30051.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 这里要用到的是同步标志```winsound.SND_ASYNC``` ![winsound.SND_ASYNC](http://upload-images.jianshu.io/upload_images/1108512-4b1ee590e3f34617.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 虽然同样是5分钟的音频,可是后面的语句很明显的执行了. ![找到了与这三个积木块对应的winsound语句](http://upload-images.jianshu.io/upload_images/1108512-57c400b81637ccd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### 实现TSound类 ![image.png](http://upload-images.jianshu.io/upload_images/1108512-ee2ea4f0f929efb8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ``` import winsound as snd # 导入声音类 class TSound(object): """Sounding part of the RawTurtle Implements sounding methods """ def __init__(self, soundfile, resizemode=_CFG["resizemode"]): # 其实Sound并不涉及画笔的移动和绘制,resizemode不加也是可以滴 self._soundfile = soundfile def play(self, soundfile): snd.PlaySound("d:\coding\sound.wav", snd.SND_ASYNC) def playuntil(self, soundfile): snd.PlaySound("d:\coding\sound.wav", snd.SND_FILENAME) def stopall(self): snd.PlaySound(None, snd.SND_PURGE) ``` 首先导入winsound模块并重命名为snd,然后生命TSound类,定义三个函数,实现播放,播放直到和停止所有声音的功能,当然这也仅仅是个实现而已,要真的完善还是需要比较长的时间,只是给大家简单的举个例子,这个其实可以对照register_shape和shape函数来定义和完善的. ### 让RawTurtle继承TSound类 ![RawTurtle继承TSound类](http://upload-images.jianshu.io/upload_images/1108512-5f03f718c53cdb15.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ``` class RawTurtle(TPen, TNavigator, TSound): # 小乌龟的动画部分 # 为何添加的函数不工作呢 """Animation part of the RawTurtle. Puts RawTurtle upon a TurtleScreen and provides tools for its animation. """ ``` ### 将```TSound```的方法添加到Turtle的函数列表 ![添加TSound的方法到turtle的函数列表](http://upload-images.jianshu.io/upload_images/1108512-283aff74934339a5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![然后再RawTurtle中初始化一下TSound](http://upload-images.jianshu.io/upload_images/1108512-1fa2daa8717dff26.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![pycat](http://upload-images.jianshu.io/upload_images/1108512-90a1ae064e14c5e9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 我把修改后的文件重命名为pycat,然后导入: ![运行](http://upload-images.jianshu.io/upload_images/1108512-507480e89544e951.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 注意我用IDLE新建了一个sound.py文件然后保存在```d:\coding\yaohao```目录下,然后导入同目录下的```pycat```,如果你的python文件和pycat不在同一目录,是无法导入```pycat```的 ![播放声音](http://upload-images.jianshu.io/upload_images/1108512-ac590741128df949.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![停止播放声音,大功告成](http://upload-images.jianshu.io/upload_images/1108512-e87f87ab86659c2a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)