diff --git a/eoc/chapter4.py b/eoc/chapter4.py index ad400663..c3638c99 100644 --- a/eoc/chapter4.py +++ b/eoc/chapter4.py @@ -40,16 +40,178 @@ class Chapter3OpeningQuote(OpeningQuote): class TransitionFromLastVideo(TeacherStudentsScene): def construct(self): - rules = power_rule, sine_rule, exp_rule = VGroup(*[ - TexMobject("\\frac{d(x^3)}{dx} = 3x^2"), - TexMobject("\\frac{d(\\sin(x))}{dx} = \\cos(x)"), - TexMobject("\\frac{d(e^x)}{dx} = e^x"), + simple_rules = VGroup(*map(TexMobject, [ + "\\frac{d(x^3)}{dx} = 3x^2", + "\\frac{d(\\sin(x))}{dx} = \\cos(x)", + "\\frac{d(e^x)}{dx} = e^x", + ])) + + combination_rules = VGroup(*[ + TexMobject("\\frac{d}{dx}\\left(%s\\right)"%tex) + for tex in [ + "\\sin(x) + x^2", + "\\sin(x)(x^2)", + "\\sin(x^2)", + ] ]) - rules.arrange_submobjects(buff = LARGE_BUFF) - rules.next_to(self.get_teacher(), UP, buff = MED_LARGE_BUFF) - rules.to_edge(LEFT) + for rules in simple_rules, combination_rules: + rules.arrange_submobjects(buff = LARGE_BUFF) + rules.next_to(self.get_teacher(), UP, buff = MED_LARGE_BUFF) + rules.to_edge(LEFT) + + series = VideoSeries() + series.to_edge(UP) + last_video = series[2] + last_video.save_state() + this_video = series[3] + brace = Brace(last_video) + + #Simple rules + self.add(series) + self.play( + FadeIn(brace), + last_video.highlight, YELLOW + ) + for rule in simple_rules: + self.play( + Write(rule, run_time = 1), + self.get_teacher().change_mode, "raise_right_hand", + *[ + ApplyMethod(pi.change_mode, "pondering") + for pi in self.get_students() + ] + ) + self.dither(2) + self.play(simple_rules.replace, last_video) + self.play( + last_video.restore, + Animation(simple_rules), + brace.next_to, this_video, DOWN, + this_video.highlight, YELLOW + ) + + #Combination rules + self.play( + Write(combination_rules), + *[ + ApplyMethod(pi.change_mode, "confused") + for pi in self.get_students() + ] + ) + self.dither(2) + for rule in combination_rules: + interior = VGroup(*rule[5:-1]) + added_anims = [] + if rule is combination_rules[-1]: + inner_func = VGroup(*rule[-4:-2]) + self.play(inner_func.shift, 0.5*UP) + added_anims = [ + inner_func.shift, 0.5*DOWN, + inner_func.highlight, YELLOW + ] + self.play( + interior.highlight, YELLOW, + *added_anims, + submobject_mode = "lagged_start" + ) + self.dither() + self.dither() + + #Address subtraction and division + subtraction = TexMobject("\\sin(x)", "-", "x^2") + decomposed_subtraction = TexMobject("\\sin(x)", "+(-1)\\cdot", "x^2") + pre_division = TexMobject("\\frac{\\sin(x)}{x^2}") + division = VGroup( + VGroup(*pre_division[:6]), + VGroup(*pre_division[6:7]), + VGroup(*pre_division[7:]), + ) + pre_decomposed_division = TexMobject("\\sin(x)\\cdot\\frac{1}{x^2}") + decomposed_division = VGroup( + VGroup(*pre_decomposed_division[:6]), + VGroup(*pre_decomposed_division[6:9]), + VGroup(*pre_decomposed_division[9:]), + ) + for mob in subtraction, decomposed_subtraction, division, decomposed_division: + mob.next_to(self.get_teacher(), UP+LEFT) + + top_group = VGroup(series, simple_rules, brace) + combination_rules.save_state() + self.play( + top_group.next_to, SPACE_HEIGHT*UP, UP, + combination_rules.to_edge, UP, + ) + pairs = [ + (subtraction, decomposed_subtraction), + (division, decomposed_division) + ] + for question, answer in pairs: + self.play( + Write(question), + combination_rules.fade, 0.2, + self.get_students()[2].change_mode, "raise_right_hand", + self.get_teacher().change_mode, "plain", + ) + self.dither() + answer[1].highlight(GREEN) + self.play( + Transform(question, answer), + self.get_teacher().change_mode, "hooray", + self.get_students()[2].change_mode, "plain", + ) + self.dither() + self.play(FadeOut(question)) + + #Monstrous expression + monster = TexMobject( + "\\Big(", + "e^{\\sin(x)} \\cdot", + "\\cos\\big(", + "\\frac{1}{x^3}", + " + x^3", + "\\big)", + "\\Big)^4" + ) + monster.next_to(self.get_pi_creatures(), UP) + parts = [ + VGroup(*monster[3][2:]), + VGroup(*monster[3][:2]), + monster[4], + VGroup(monster[2], monster[5]), + monster[1], + VGroup(monster[0], monster[6]) + ] + modes = [ + "erm", "erm", + "confused", + "sad", "sad", + "pleading", + ] + for part, mode in zip(parts, modes): + self.play( + FadeIn(part, submobject_mode = "lagged_start"), + self.get_teacher().change_mode, "raise_right_hand", + *[ + ApplyMethod(pi.change_mode, mode) + for pi in self.get_students() + ] + ) + self.dither(2) + + #Bring back combinations + self.play( + FadeOut(monster), + combination_rules.restore, + *[ + ApplyMethod(pi_creature.change_mode, "pondering") + for pi_creature in self.get_pi_creatures() + ] + ) + self.dither(2) + + + - self.add(rules) diff --git a/topics/characters.py b/topics/characters.py index 5ad81420..26e8797e 100644 --- a/topics/characters.py +++ b/topics/characters.py @@ -82,7 +82,10 @@ class PiCreature(SVGMobject): return self def change_mode(self, mode): - new_self = self.__class__(mode = mode) + new_self = self.__class__( + mode = mode, + color = self.color + ) new_self.scale_to_fit_height(self.get_height()) new_self.shift(self.eyes.get_center() - new_self.eyes.get_center()) if self.is_flipped() ^ new_self.is_flipped(): @@ -304,7 +307,8 @@ class PiCreatureScene(Scene): return VGroup(self.create_pi_creature()) def create_pi_creature(self): - return Mortimer().to_corner(DOWN+RIGHT) + self.pi_creature = Mortimer().to_corner(DOWN+RIGHT) + return self.pi_creature def get_pi_creatures(self): return self.pi_creatures @@ -406,9 +410,9 @@ class PiCreatureScene(Scene): if pi_creature in anim.mobject.submobject_family() ] if anims_with_pi_creature: - for anim in animations: + for anim in anims_with_pi_creature: if isinstance(anim, Transform): - index = anim.submobject_family().index(pi_creature) + index = anim.mobject.submobject_family().index(pi_creature) target_family = anim.target_mobject.submobject_family() target = target_family[index] if isinstance(target, PiCreature):