zoukankan      html  css  js  c++  java
  • 让小乌龟可以唱歌——对Python turtle进行拓展

    在Scratch中,小猫是可以唱歌的,而且Scratch的声音木块有着丰富的功能,在这方面Python turtle略有欠缺,今天我们就来完善一下.

    Scratch声音模块

    Python声音模块

    Python有关声音的库有639种,可以完成非常复杂的功能的

    Python处理声音的模块很多,但是我们要实现的功能并不复杂,所以只需要用到winsound这个系统自带的模块就好了.我们要的只是实现类似scratch的功能,用不到很复杂的功能的,当然Python能够做的比scratch多多了.

    Python turtle的代码结构

    最近一直在阅读python turtle的源代码对于Python源代码的结构有所了解,针对造型的操作也重新定义了一些函数来与scratch的积木块相对应。

    在Python turtle基础上进行扩充而不是使用Pygame、Pyglet等复杂的库是因为Python turtle本身为了教小孩子编程设计的,在结构上更加符合小孩子的学习习惯,对交互式编程友好,而pygame和pyglet不具备这两个特点。

    Python Turtle的代码结构图

    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

    TNavigator更多的承载了类似动作积木类的功能

    TNavigator

    Tpen

    TPen更多的实现了画笔分类的功能

    TPen更多的实现了画笔分类的功能

    上面两组功能是否很相似呢。

    所以要实现Python turtle的声音功能,只要重新写一个声音相关的类,然后让RawTurtle继承这个声音类就ok了,当然还要注意一个问题,turtle所有的类都要加入到_tg_turtle_functions这个列表中,这个列表保存了turtle所有的方法,用来保证在交互式命令行里,默认turtle的各种方法可以直接作为函数调用.

    image.png

    让我们开工把

    实现TSound类

    Scratch积木块对应的Python

    我们一步步的来实现

    导入库并生命类

    winsound模块的同学,可以访问其在官方的文档,这里介绍播放声音的方法:

    winsound.PlaySound('d:codingmaow.wav',winsound.SND_FILENAME)
    # 第一个参数是文件的完整路径,第二个是播放的标志,winsound.SND_FILENAME代表的是播放的是文件
    

    首先我们导入winsound模块之后,然后利用这个模块的PlaySound方法播放指定的声音文件这样就实现了

    播放直到完毕

    停止声音的办法是:

    winsound.PlaySound(None, winsound.SND_PURGE)
    

    对应的是
    停止所有声音模块

    默认的声音播放方式是同步的,也就是说播放声音的时候程序啥也不能干,如下面播放5分钟的音频:

    import winsound as s
    s.PlaySound("d:codingsound.wav",s.SND_FILENAME)
    print('Playing ended!')
    

    如果这五分钟的音频sound.wav没有播放完毕,程序啥也不能干,尬不尬.

    这个积木块比较霸道,要求必须等他做完了才可以,本来就相当于你跟你女朋友打电话,一般我是边打电话边做事情,但是女朋友呢非得要求你啥也不能做,直到电话打完,不然就是不尊重她,不爱她,真尬.当然了少年们,跟女朋友打电话的时候一定不要做别的事情哦.

    如何实现异步播放声音呢,毕竟我们是热爱时间的好少年.

    播放声音
    这里要用到的是同步标志winsound.SND_ASYNC

    winsound.SND_ASYNC
    虽然同样是5分钟的音频,可是后面的语句很明显的执行了.

    找到了与这三个积木块对应的winsound语句

    实现TSound类

    image.png

    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:codingsound.wav", snd.SND_ASYNC)
    
        def playuntil(self, soundfile):
            snd.PlaySound("d:codingsound.wav", snd.SND_FILENAME)
    
        def stopall(self):
            snd.PlaySound(None, snd.SND_PURGE)
    

    首先导入winsound模块并重命名为snd,然后生命TSound类,定义三个函数,实现播放,播放直到和停止所有声音的功能,当然这也仅仅是个实现而已,要真的完善还是需要比较长的时间,只是给大家简单的举个例子,这个其实可以对照register_shape和shape函数来定义和完善的.

    让RawTurtle继承TSound类

    RawTurtle继承TSound类

    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的函数列表

    然后再RawTurtle中初始化一下TSound

    pycat

    我把修改后的文件重命名为pycat,然后导入:

    运行
    注意我用IDLE新建了一个sound.py文件然后保存在d:codingyaohao目录下,然后导入同目录下的pycat,如果你的python文件和pycat不在同一目录,是无法导入pycat

    播放声音

    停止播放声音,大功告成

  • 相关阅读:
    三地气温的典型相关分析
    android 使用 BroadcastReceiver 总结
    发布网站问题笔记
    Android 两个Activity 实现数据的来回传递
    input 标签屏蔽谷歌浏览器高亮显示
    javascript 获取当前html 标签的位置
    c# 四舍五入
    利用SQL的charindex实现字符串数组和Split函数
    ExtJs 一些常用的控件
    C#中return、break、continue的用法
  • 原文地址:https://www.cnblogs.com/asworm/p/7045486.html
Copyright © 2011-2022 走看看