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)
the animation only lasts for two seconds and also seems like is getting stuck on an infinite loop
when I add the runtimes in the rotation class interpreter get stuck into an infinite loop when I ELIMINATE the runtimes the animation only lasts 2 sec
when trying to add run time to the fadein bullet I get the error ValueError: write to closed file
The actual problem is that you cannot call self.play()
inside an updater. But you have a little nice function that can be useful here. It is turn_animation_into_updater()
. This one can be called from an updater, and creates another updater which plays that animation (in parallel with others), until the animation reach its end, at which moment the auxiliar updater is removed.
Other observations about your code:
rate_func
which decreases its velocity when the animation is reaching its end.With all these ideas:
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)
Which produces: