python 问题在manim动画只持续2秒

6gpjuf90  于 2023-05-21  发布在  Python
关注(0)|答案(3)|浏览(172)
class PendBall(Scene):
    def construct(self):
        square = Square(side_length=1.5, fill_opacity=1, fill_color=BLUE_E)
        line = Line(ORIGIN, [0, 4, 0], buff=0)

        bullet = Circle(radius=0.2, fill_color=RED, fill_opacity=1)
        bullet.shift(6*LEFT)
        self.flag = False

        def updatebullet(bullet: Mobject, dt):
            if bullet.get_x() >= square.get_left()[0] or self.flag:
                bullet_vel = -1
                self.flag = True
                self.play(Rotate(line, angle=PI/4,
                                 about_point=[0, 4, 0], run_time=10),
                          Rotate(square, angle=PI/4, about_point=[0, 4, 0], run_time=10))

            else:
                bullet_vel = 1
            bullet.shift(np.array([bullet_vel, 0, 0])*dt)

        bullet.add_updater(updatebullet)

        self.play(FadeIn(square, line))
        self.play(FadeIn(bullet))
        self.wait(10)

动画只持续了两秒钟,而且看起来像是陷入了一个无限循环

当我在旋转类解释器中添加运行时陷入无限循环当我删除运行时动画只持续2秒
当我尝试添加运行时间到淡入项目符号时,我得到错误ValueError:写入已关闭文件

c86crjj0

c86crjj01#

实际的问题是,您不能在更新程序中调用self.play()。但是你有一个很好的函数在这里会很有用。turn_animation_into_updater()。这一个可以从更新器调用,并创建另一个更新器,该更新器播放该动画(与其他更新器并行),直到动画到达其结束,此时辅助更新器被移除。
关于你的代码的其他观察:

  • 您不希望将速度设置回1,一旦它被更改为-1。所以else部分可以去掉
  • 你不需要旗子。你可以测试速度是否为正
  • 您可以将速度存储为bullet对象的一部分,以便在更新程序调用之间保留它。
  • 要设置块的动画,您可能需要使用适当的rate_func,以便在动画结束时降低其速度。

所有这些想法:

class Test(Scene):
    def construct(self):
        square = Square(side_length=1.5, fill_opacity=1, fill_color=BLUE_E)
        line = Line(ORIGIN, [0, 4, 0], buff=0)

        bullet = Circle(radius=0.2, fill_color=RED, fill_opacity=1)
        bullet.shift(6*LEFT)
        bullet.velocity = 2
        ease_out_sine = rate_functions.ease_out_sine

        def updatebullet(bullet: Mobject, dt):
            if bullet.get_x() >= square.get_left()[0] and bullet.velocity > 0:
                bullet.velocity *= -1
                turn_animation_into_updater(
                    Rotate(line, angle=PI/4, about_point=[0, 4, 0], 
                           run_time=5, rate_func=ease_out_sine))
                turn_animation_into_updater(
                    Rotate(square, angle=PI/4, about_point=[0, 4, 0], 
                           run_time=5, rate_func=ease_out_sine))
            bullet.shift(np.array([bullet.velocity, 0, 0])*dt)

        bullet.add_updater(updatebullet)
        square.add_updater(lambda m,dt: None)
        line.add_updater(lambda m,dt: None)
        self.play(FadeIn(square, line))
        self.play(FadeIn(bullet))
        self.wait(10)

生产:

8cdiaqws

8cdiaqws2#

不能在更新程序中启动新的self.play()动画。一个更新器函数被调用为在你的动画中生成的每个帧,即。当你以每秒15帧的速度渲染时,更新程序将被调用15次。
如果你现在在你的更新程序中启动一个新的10秒长的动画,那将调用更新程序另外150次,每次启动一个新的10秒长的动画。
来Discord与Manim上的问题-在那里你会得到快速的帮助和很多提示!https://discord.com/channels/581738731934056449/785271046970278008

wfauudbj

wfauudbj3#

我猜你想做类似的事情:(非常粗略的草图)

class PendBall(Scene):
    def construct(self):
        pendulum = VGroup(
            Square(side_length=1.5, fill_opacity=1, fill_color=BLUE_E),
            Line(ORIGIN, [0, 4, 0], buff=0)
        )
        pendulum.ang_vel = 0

        bullet = Circle(radius=0.2, fill_color=RED, fill_opacity=1)
        bullet.shift(6*LEFT)
        bullet.vel = 1
        def bulletUpdater(mobj,dt):
            mobj.shift(mobj.vel * dt * RIGHT)
        bullet.add_updater(bulletUpdater)

        def pendulumUpdater(mobj, dt):
            if bullet.get_x() >= mobj[0].get_left()[0]:
                bullet.vel = -1
                mobj.ang_vel = 1
            if  ((mobj[0].get_x()>2) and (mobj.ang_vel > 0)) or ((mobj[0].get_x()<-2) and (mobj.ang_vel < 0)):
                mobj.ang_vel *= -1
            mobj.rotate(mobj.ang_vel * dt, about_point=mobj[1].get_end())       

        pendulum.add_updater(pendulumUpdater)

        self.play(FadeIn(pendulum))
        self.play(FadeIn(bullet))
        self.wait(10)

相关问题