Preliminary finish of chapter 7 animations

This commit is contained in:
Grant Sanderson
2016-08-22 21:22:21 -07:00
parent 3391e645d7
commit 87c390f41e
9 changed files with 339 additions and 89 deletions

View File

@ -21,6 +21,7 @@ class Animation(object):
#Options are lagged_start, smoothed_lagged_start, #Options are lagged_start, smoothed_lagged_start,
#one_at_a_time, all_at_once #one_at_a_time, all_at_once
"submobject_mode" : "lagged_start", "submobject_mode" : "lagged_start",
"lag_factor" : 2,
} }
def __init__(self, mobject, **kwargs): def __init__(self, mobject, **kwargs):
mobject = instantiate(mobject) mobject = instantiate(mobject)
@ -77,7 +78,8 @@ class Animation(object):
prop = float(index)/num_submobjects prop = float(index)/num_submobjects
if self.submobject_mode is "smoothed_lagged_start": if self.submobject_mode is "smoothed_lagged_start":
prop = smooth(prop) prop = smooth(prop)
return np.clip(2*alpha - prop, 0, 1) lf = self.lag_factor
return np.clip(lf*alpha - (lf-1)*prop, 0, 1)
elif self.submobject_mode == "one_at_a_time": elif self.submobject_mode == "one_at_a_time":
lower = float(index)/num_submobjects lower = float(index)/num_submobjects
upper = float(index+1)/num_submobjects upper = float(index+1)/num_submobjects

View File

@ -48,6 +48,12 @@ class ShowCreation(ShowPartial):
def get_bounds(self, alpha): def get_bounds(self, alpha):
return (0, alpha) return (0, alpha)
class Uncreate(ShowCreation):
CONFIG = {
"rate_func" : lambda t : smooth(1-t),
"remover" : True
}
class Write(ShowCreation): class Write(ShowCreation):
CONFIG = { CONFIG = {
"rate_func" : None, "rate_func" : None,

View File

@ -85,7 +85,7 @@ class OpeningQuote(Scene):
", not ", ", not ",
"numbers.", "numbers.",
"''", "''",
], separate_list_arg_with_spaces = False) ], arg_separator = "")
# words.scale_to_fit_width(2*SPACE_WIDTH - 2) # words.scale_to_fit_width(2*SPACE_WIDTH - 2)
words.to_edge(UP) words.to_edge(UP)
words.split()[1].highlight(BLUE) words.split()[1].highlight(BLUE)

View File

@ -51,7 +51,9 @@ class OpeningQuote(Scene):
"\\\\Calvin:" , "\\\\Calvin:" ,
"Yeah. All these equations are like miracles." "Yeah. All these equations are like miracles."
"You take two numbers and when you add them, " "You take two numbers and when you add them, "
"they magically become one NEW number!" "they magically become one NEW number! "
"No one can say how it happens. "
"You either believe it or you don't.",
) )
words.scale_to_fit_width(2*SPACE_WIDTH - 1) words.scale_to_fit_width(2*SPACE_WIDTH - 1)
words.to_edge(UP) words.to_edge(UP)
@ -60,8 +62,14 @@ class OpeningQuote(Scene):
words[4].highlight(YELLOW) words[4].highlight(YELLOW)
for i in range(3): for i in range(3):
self.play(Write(VMobject(*words[2*i:2*i+1]))) speaker, quote = words[2*i:2*i+2]
# self.play(FadeIn(words)) self.play(FadeIn(speaker, run_time = 0.5))
rt = max(1, len(quote.split())/18)
self.play(Write(
quote,
run_time = rt,
lag_factor = 5 if rt > 3 else 2,
))
self.dither(2) self.dither(2)
class TraditionalOrdering(RandolphScene): class TraditionalOrdering(RandolphScene):
@ -94,6 +102,7 @@ class TraditionalOrdering(RandolphScene):
class ThisSeriesOrdering(RandolphScene): class ThisSeriesOrdering(RandolphScene):
def construct(self): def construct(self):
title = TextMobject("Essence of linear algebra") title = TextMobject("Essence of linear algebra")
self.randy.rotate(np.pi, UP)
title.scale(1.2).highlight(BLUE) title.scale(1.2).highlight(BLUE)
title.to_corner(UP+LEFT) title.to_corner(UP+LEFT)
line = Line(SPACE_WIDTH*LEFT, SPACE_WIDTH*RIGHT, color = WHITE) line = Line(SPACE_WIDTH*LEFT, SPACE_WIDTH*RIGHT, color = WHITE)
@ -124,7 +133,9 @@ class ThisSeriesOrdering(RandolphScene):
chapters.to_edge(RIGHT) chapters.to_edge(RIGHT)
self.add(title) self.add(title)
self.play(ShowCreation(line)) self.play(
ShowCreation(line),
)
self.play( self.play(
FadeIn( FadeIn(
chapters, chapters,
@ -133,48 +144,53 @@ class ThisSeriesOrdering(RandolphScene):
), ),
self.randy.change_mode, "sassy" self.randy.change_mode, "sassy"
) )
self.play(self.randy.look, UP+LEFT)
self.play(chapters[6].highlight, PINK) self.play(chapters[6].highlight, PINK)
self.dither(2) self.dither(6)
self.dither(2)
class OneMustViewThroughTransformations(TeacherStudentsScene): class OneMustViewThroughTransformations(TeacherStudentsScene):
def construct(self): def construct(self):
self.teacher_says(""" words = TextMobject(
Only with transformations "Only with" , "transformations",
can we truly understand "\n can we truly understand",
""") )
words.highlight_by_tex("transformations", BLUE)
self.teacher_says(words)
self.change_student_modes( self.change_student_modes(
"pondering", "pondering",
"plain", "plain",
"raise_right_hand" "raise_right_hand"
) )
self.random_blink(2) self.random_blink(2)
self.teacher_says(""" words = TextMobject(
First, the "First, the ",
standard view... "standard view...",
""") arg_separator = "\n"
)
self.teacher_says(words)
self.random_blink(2) self.random_blink(2)
class ShowNumericalDotProduct(Scene): class ShowNumericalDotProduct(Scene):
CONFIG = { CONFIG = {
"v1" : [2, 7, 1], "v1" : [2, 7, 1],
"v2" : [8, 2, 8], "v2" : [8, 2, 8],
"write_dot_product_words" : True,
} }
def construct(self): def construct(self):
v1 = Matrix(self.v1) v1 = Matrix(self.v1)
v2 = Matrix(self.v2) v2 = Matrix(self.v2)
inter_array_dot = TexMobject("\\cdot").scale(1.5) inter_array_dot = TexMobject("\\cdot").scale(1.5)
dot_product = VMobject(v1, inter_array_dot, v2) dot_product = Group(v1, inter_array_dot, v2)
dot_product.arrange_submobjects(RIGHT) dot_product.arrange_submobjects(RIGHT, buff = MED_BUFF/2)
dot_product.to_edge(LEFT) dot_product.to_edge(LEFT)
pairs = zip(v1.get_entries(), v2.get_entries()) pairs = zip(v1.get_entries(), v2.get_entries())
for pair, color in zip(pairs, [X_COLOR, Y_COLOR, Z_COLOR, PINK]): for pair, color in zip(pairs, [X_COLOR, Y_COLOR, Z_COLOR, PINK]):
VMobject(*pair).highlight(color) Group(*pair).highlight(color)
dot = TexMobject("\\cdot") dot = TexMobject("\\cdot")
products = VMobject(*[ products = Group(*[
VMobject( Group(
p1.copy(), dot.copy(), p2.copy() p1.copy(), dot.copy(), p2.copy()
).arrange_submobjects(RIGHT, buff = SMALL_BUFF) ).arrange_submobjects(RIGHT, buff = SMALL_BUFF)
for p1, p2 in pairs for p1, p2 in pairs
@ -185,24 +201,38 @@ class ShowNumericalDotProduct(Scene):
products.target = products.copy() products.target = products.copy()
plusses = ["+"]*(len(self.v1)-1) plusses = ["+"]*(len(self.v1)-1)
symbols = VMobject(*map(TexMobject, ["="] + plusses)) symbols = Group(*map(TexMobject, ["="] + plusses))
final_sum = VMobject(*it.chain(*zip( final_sum = Group(*it.chain(*zip(
symbols, products.target symbols, products.target
))) )))
final_sum.arrange_submobjects(RIGHT, buff = SMALL_BUFF) final_sum.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
final_sum.next_to(dot_product, RIGHT) final_sum.next_to(dot_product, RIGHT)
title = TextMobject("Two vectors of the same dimension")
title.to_edge(UP)
arrow = Arrow(DOWN, UP).next_to(inter_array_dot, DOWN)
dot_product_words = TextMobject("Dot product")
dot_product_words.highlight(YELLOW)
dot_product_words.next_to(arrow, DOWN)
dot_product_words.shift_onto_screen()
self.play( self.play(
Write(v1), Write(v1),
Write(v2), Write(v2),
FadeIn(inter_array_dot) FadeIn(inter_array_dot),
FadeIn(title)
) )
self.dither() self.dither()
if self.write_dot_product_words:
self.dither() self.play(
inter_array_dot.highlight, YELLOW,
ShowCreation(arrow),
Write(dot_product_words, run_time = 2)
)
self.dither()
self.play(Transform( self.play(Transform(
VMobject(*it.starmap(VMobject, pairs)).copy(), Group(*it.starmap(Group, pairs)).copy(),
products, products,
path_arc = -np.pi/2, path_arc = -np.pi/2,
run_time = 2 run_time = 2
@ -227,6 +257,7 @@ class FourDDotProductExample(ShowNumericalDotProduct):
CONFIG = { CONFIG = {
"v1" : [6, 2, 8, 3], "v1" : [6, 2, 8, 3],
"v2" : [1, 8, 5, 3], "v2" : [1, 8, 5, 3],
"write_dot_product_words" : False,
} }
class GeometricInterpretation(VectorScene): class GeometricInterpretation(VectorScene):
@ -323,7 +354,7 @@ class GeometricInterpretation(VectorScene):
"(", "(",
"Length of $\\vec{\\textbf{%s}}$"%stable_char, "Length of $\\vec{\\textbf{%s}}$"%stable_char,
")", ")",
separate_list_arg_with_spaces = False arg_separator = ""
) )
product.scale(0.9) product.scale(0.9)
product.next_to(self.dot_product, RIGHT) product.next_to(self.dot_product, RIGHT)
@ -524,7 +555,7 @@ class SymmetricVAndW(VectorScene):
line_of_symmetry.rotate(np.mean([v.get_angle(), w.get_angle()])) line_of_symmetry.rotate(np.mean([v.get_angle(), w.get_angle()]))
line_of_symmetry_words = TextMobject("Line of symmetry") line_of_symmetry_words = TextMobject("Line of symmetry")
line_of_symmetry_words.add_background_rectangle() line_of_symmetry_words.add_background_rectangle()
line_of_symmetry_words.next_to(ORIGIN, UP+RIGHT) line_of_symmetry_words.next_to(ORIGIN, UP+LEFT)
line_of_symmetry_words.rotate(line_of_symmetry.get_angle()) line_of_symmetry_words.rotate(line_of_symmetry.get_angle())
for vect in v, w: for vect in v, w:
@ -539,11 +570,14 @@ class SymmetricVAndW(VectorScene):
run_time = 2 run_time = 2
) )
self.dither() self.dither()
self.play(ShowCreation(line_of_symmetry)) self.play(
self.play(Write(line_of_symmetry_words)) ShowCreation(line_of_symmetry),
self.dither() Write(line_of_symmetry_words, run_time = 1)
self.play(Transform(line_of_symmetry_words, line_of_symmetry)) )
for vect in v, w: self.dither(0.5)
self.remove(line_of_symmetry_words)
self.play(*map(Uncreate, line_of_symmetry_words))
for vect in w, v:
self.play(ShowCreation(vect.proj_line)) self.play(ShowCreation(vect.proj_line))
vect_copy = vect.copy() vect_copy = vect.copy()
self.play(Transform(vect_copy, vect.proj)) self.play(Transform(vect_copy, vect.proj))
@ -556,9 +590,8 @@ class SymmetricVAndW(VectorScene):
def show_doubling(self, v, w): def show_doubling(self, v, w):
scalar = 2 scalar = 2
new_v = v.copy().scale(scalar) new_v = v.copy().scale(scalar)
new_v.label = VMobject(TexMobject(str(scalar)), v.label.copy()) new_v.label = VMobject(TexMobject("c"), v.label.copy())
new_v.label.arrange_submobjects() new_v.label.arrange_submobjects(aligned_edge = DOWN)
new_v.label.highlight(new_v.get_color())
new_v.label.next_to(new_v.get_end(), DOWN+RIGHT) new_v.label.next_to(new_v.get_end(), DOWN+RIGHT)
new_v.proj = v.proj.copy().scale(scalar) new_v.proj = v.proj.copy().scale(scalar)
new_v.proj.fade() new_v.proj.fade()
@ -569,9 +602,9 @@ class SymmetricVAndW(VectorScene):
v_tex, w_tex = ["\\vec{\\textbf{%s}}"%c for c in "v", "w"] v_tex, w_tex = ["\\vec{\\textbf{%s}}"%c for c in "v", "w"]
equation = TexMobject( equation = TexMobject(
"(", "2", v_tex, ")", "\\cdot", w_tex, "(", "c", v_tex, ")", "\\cdot", w_tex,
"=", "=",
"2(", v_tex, "\\cdot", w_tex, ")" "c(", v_tex, "\\cdot", w_tex, ")"
) )
equation.highlight_by_tex(v_tex, V_COLOR) equation.highlight_by_tex(v_tex, V_COLOR)
equation.highlight_by_tex(w_tex, W_COLOR) equation.highlight_by_tex(w_tex, W_COLOR)
@ -584,23 +617,37 @@ class SymmetricVAndW(VectorScene):
v.save_state() v.save_state()
v.proj.save_state() v.proj.save_state()
self.play(Transform(*[ self.play(Transform(*[
VMobject(mob, mob.proj, mob.proj_line, mob.label) Group(mob, mob.proj, mob.proj_line, mob.label)
for mob in v, new_v for mob in v, new_v
]), run_time = 2) ]), run_time = 2)
last_mob = self.get_mobjects_from_last_animation()[0]
self.remove(last_mob)
self.add(*last_mob)
self.play(Write(words)) self.play(Write(words))
self.dither() self.dither()
two_v_parts = equation[1:3] two_v_parts = equation[1:3]
equation.remove(*two_v_parts) equation.remove(*two_v_parts)
self.play(
Write(equation),
Transform(new_v.label.copy(), VMobject(*two_v_parts))
)
self.dither()
for vect in v, v.proj: for v_part, projector, stable in zip([v, v.proj], [w, v], [v, w]):
self.play(*map(FadeOut, [
stable.proj, stable.proj_line
]))
self.play( self.play(
vect.restore, Transform(projector.copy(), projector.proj),
ShowCreation(projector.proj_line)
)
self.remove(self.get_mobjects_from_last_animation()[0])
self.add(projector.proj)
self.dither()
if equation not in self.get_mobjects():
self.play(
Write(equation),
Transform(new_v.label.copy(), VMobject(*two_v_parts))
)
self.dither()
self.play(
v_part.restore,
rate_func = there_and_back, rate_func = there_and_back,
run_time = 2 run_time = 2
) )
@ -1759,58 +1806,246 @@ class AbstractNumericAssociation(AssociationBetweenMatricesAndVectors):
} }
class TwoDOneDTransformationSeparateSpace(Scene): class TwoDOneDTransformationSeparateSpace(Scene):
CONFIG = {
"v_coords" : [4, 1]
}
def construct(self): def construct(self):
x_rad = SPACE_WIDTH/2-0.5 width = SPACE_WIDTH-1
plane = NumberPlane(x_radius = x_rad) plane = NumberPlane(x_radius = 6, y_radius = 7)
squish_plane = plane.copy().apply_function( squish_plane = plane.copy()
lambda p : sum(p)*RIGHT i_hat = Vector([1, 0], color = X_COLOR)
) j_hat = Vector([0, 1], color = Y_COLOR)
plane.to_edge(LEFT) vect = Vector(self.v_coords, color = YELLOW)
squish_plane.scale_to_fit_width(2*x_rad) plane.add(vect, i_hat, j_hat)
squish_plane.to_edge(RIGHT) plane.scale_to_fit_width(SPACE_WIDTH)
plane.to_edge(LEFT, buff = 0)
plane.remove(vect, i_hat, j_hat)
number_line = NumberLine().stretch_to_fit_width(2*x_rad) squish_plane.apply_function(
lambda p : np.dot(p, [4, 1, 0])*RIGHT
)
squish_plane.add(Vector(self.v_coords[0]*RIGHT, color = X_COLOR))
squish_plane.add(Vector(self.v_coords[1]*RIGHT, color = Y_COLOR))
squish_plane.scale(width/(2*SPACE_WIDTH))
plane.add(i_hat, j_hat)
number_line = NumberLine().stretch_to_fit_width(width)
number_line.to_edge(RIGHT) number_line.to_edge(RIGHT)
squish_plane.move_to(number_line)
numbers = number_line.get_numbers(*range(-6, 8, 2)) numbers = number_line.get_numbers(*range(-6, 8, 2))
v_line = Line(UP, DOWN).scale(SPACE_HEIGHT) v_line = Line(UP, DOWN).scale(SPACE_HEIGHT)
v_line.highlight(GREY)
v_line.set_stroke(width = 10)
words = TextMobject(""" matrix = Matrix([self.v_coords])
Any time you have a matrix.highlight_columns(X_COLOR, Y_COLOR)
2d-to-1d linear transform... matrix.next_to(number_line, UP, buff = LARGE_BUFF)
""") v_coords = Matrix(self.v_coords)
words.add_background_rectangle() v_coords.highlight_columns(YELLOW)
words.to_edge(UP) v_coords.scale(0.75)
v_coords.next_to(vect.get_end(), RIGHT)
for array in matrix, v_coords:
array.add_to_back(BackgroundRectangle(array))
start_words = TextMobject(
"\\centering Any time you have a \\\\",
"2d-to-1d linear transform..."
)
end_words = TextMobject(
"\\centering ...it's associated \\\\",
"with some vector",
)
for words in start_words, end_words:
words.add_background_rectangle()
words.scale(0.8)
start_words.next_to(ORIGIN, RIGHT, buff = MED_BUFF).to_edge(UP)
end_words.next_to(ORIGIN, DOWN+LEFT, buff = MED_BUFF/2)
self.play(Write(words, run_time = 1))
self.play(*map(ShowCreation, [ self.play(*map(ShowCreation, [
plane, number_line, v_line plane, number_line, v_line
])+[Animation(words)]) ])+[
self.play(Write(numbers, run_time = 1)) Write(numbers, run_time = 2)
self.play( ])
Transform(plane, squish_plane), self.play(Write(start_words, run_time = 2))
Animation(words), self.play(Write(matrix, run_time = 1))
path_arc = -np.pi/4, mover = plane.copy()
run_time = 3 interim = plane.copy().scale(0.8).move_to(number_line)
) for target in interim, squish_plane:
self.play(
Transform(mover, target),
Animation(plane),
Animation(start_words),
run_time = 1,
)
self.dither()
self.play(Transform(start_words.copy(), end_words))
self.play(ShowCreation(vect))
self.play(Transform(matrix.copy(), v_coords))
self.dither() self.dither()
class IsntThisBeautiful(TeacherStudentsScene): class IsntThisBeautiful(TeacherStudentsScene):
def construct(self): def construct(self):
self.teacher.look(DOWN+LEFT) self.teacher.look(DOWN+LEFT)
self.teacher_says( self.teacher_says(
"Isn't this beautiful", "Isn't this", "beautiful",
pi_creature_target_mode = "surprised" pi_creature_target_mode = "surprised"
) )
for student in self.get_students(): for student in self.get_students():
self.play(student.change_mode, "happy") self.play(student.change_mode, "happy")
self.random_blink() self.random_blink()
duality_words = TextMobject(
"It's called", "duality"
)
duality_words[1].gradient_highlight(BLUE, YELLOW)
self.teacher_says(duality_words)
self.random_blink()
class DualOfAVector(ScaleUpUHat):
pass #Exact copy
class DualOfATransform(TwoDOneDTransformationSeparateSpace):
pass #Exact copy
class UnderstandingProjection(ProjectOntoUnitVectorNumberline):
pass ##Copy
class ShowQualitativeDotProductValuesCopy(ShowQualitativeDotProductValues):
pass
class TranslateToTheWorldOfTransformations(Scene):
def construct(self):
v1, v2 = [
Matrix(["x_%d"%n, "y_%d"%n])
for n in 1, 2
]
v1.highlight_columns(V_COLOR)
v2.highlight_columns(W_COLOR)
dot = TexMobject("\\cdot")
matrix = Matrix([["x_1", "y_1"]])
matrix.highlight_columns(X_COLOR, Y_COLOR)
dot_product = Group(v1, dot, v2)
dot_product.arrange_submobjects(RIGHT)
matrix.next_to(v2, LEFT)
brace = Brace(matrix, UP)
word = TextMobject("Transform")
word.scale_to_fit_width(brace.get_width())
brace.put_at_tip(word)
word.highlight(BLUE)
self.play(Write(dot_product))
self.dither()
self.play(
dot.highlight, BLACK,
Transform(v1, matrix),
)
self.play(
GrowFromCenter(brace),
Write(word)
)
self.dither()
class NumericalAssociationSilliness(GeneralTwoDOneDMatrixMultiplication):
pass #copy
class YouMustKnowPersonality(TeacherStudentsScene):
def construct(self):
self.teacher_says("""
You should learn a
vector's personality
""")
self.random_blink()
self.change_student_modes("pondering")
self.random_blink()
self.change_student_modes("pondering", "plain", "pondering")
self.random_blink()
class WhatTheVectorWantsToBe(Scene):
CONFIG = {
"v_coords" : [2, 4]
}
def construct(self):
width = SPACE_WIDTH-1
plane = NumberPlane(x_radius = 6, y_radius = 7)
squish_plane = plane.copy()
i_hat = Vector([1, 0], color = X_COLOR)
j_hat = Vector([0, 1], color = Y_COLOR)
vect = Vector(self.v_coords, color = YELLOW)
plane.add(vect, i_hat, j_hat)
plane.scale_to_fit_width(SPACE_WIDTH)
plane.to_edge(LEFT, buff = 0)
plane.remove(vect, i_hat, j_hat)
squish_plane.apply_function(
lambda p : np.dot(p, [4, 1, 0])*RIGHT
)
squish_plane.add(Vector(self.v_coords[1]*RIGHT, color = Y_COLOR))
squish_plane.add(Vector(self.v_coords[0]*RIGHT, color = X_COLOR))
squish_plane.scale(width/(2*SPACE_WIDTH))
plane.add(j_hat, i_hat)
number_line = NumberLine().stretch_to_fit_width(width)
number_line.to_edge(RIGHT)
squish_plane.move_to(number_line)
numbers = number_line.get_numbers(*range(-6, 8, 2))
v_line = Line(UP, DOWN).scale(SPACE_HEIGHT)
v_line.highlight(GREY)
v_line.set_stroke(width = 10)
matrix = Matrix([self.v_coords])
matrix.highlight_columns(X_COLOR, Y_COLOR)
matrix.next_to(number_line, UP, buff = LARGE_BUFF)
v_coords = Matrix(self.v_coords)
v_coords.highlight_columns(YELLOW)
v_coords.scale(0.75)
v_coords.next_to(vect.get_end(), RIGHT)
for array in matrix, v_coords:
array.add_to_back(BackgroundRectangle(array))
words = TextMobject(
"What the vector",
"\\\\ wants",
"to be"
)
words[1].highlight(BLUE)
words.next_to(matrix, UP, buff = MED_BUFF)
self.add(plane, v_line, number_line, numbers)
self.play(ShowCreation(vect))
self.play(Write(v_coords))
self.dither()
self.play(
Transform(v_coords.copy(), matrix),
Write(words)
)
self.play(
Transform(plane.copy(), squish_plane),
Animation(words),
Animation(matrix),
Animation(plane),
)
self.dither()
class NextVideo(Scene):
def construct(self):
title = TextMobject("""
Next video: Cross products in the
light of linear transformations
""")
title.scale_to_fit_height(1.2)
title.to_edge(UP, buff = MED_BUFF/2)
rect = Rectangle(width = 16, height = 9, color = BLUE)
rect.scale_to_fit_height(6)
rect.next_to(title, DOWN)
Group(title, rect).show()
self.add(title)
self.play(ShowCreation(rect))
self.dither()

View File

@ -204,10 +204,13 @@ def main():
scene_kwargs["construct_args"] = tuplify(args) scene_kwargs["construct_args"] = tuplify(args)
try: try:
handle_scene(SceneClass(**scene_kwargs), **config) handle_scene(SceneClass(**scene_kwargs), **config)
play_finish_sound()
except: except:
print "\n\n" print "\n\n"
traceback.print_exc() traceback.print_exc()
print "\n\n" print "\n\n"
play_error_sound()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -20,18 +20,24 @@ def play_chord(*nums):
"play", "play",
"-n", "-n",
"-c1", "-c1",
"--no-show-progress",
"synth", "synth",
] + [ ] + [
"sin %-"+str(num) "sin %-"+str(num)
for num in nums for num in nums
] + [ ] + [
"fade h 0.5 1 0.5" "fade h 0.5 1 0.5",
"> /dev/null"
] ]
try: try:
os.system(" ".join(commands)) os.system(" ".join(commands))
except: except:
pass pass
def play_error_sound():
play_chord(12, 11, 8, 6, 1)
def play_finish_sound(): def play_finish_sound():
play_chord(12, 9, 5, 2) play_chord(12, 9, 5, 2)

View File

@ -33,7 +33,7 @@ class TexMobject(SVGMobject):
"fill_opacity" : 1.0, "fill_opacity" : 1.0,
"fill_color" : WHITE, "fill_color" : WHITE,
"should_center" : True, "should_center" : True,
"separate_list_arg_with_spaces" : True, "arg_separator" : " ",
"enforce_new_line_structure" : False, "enforce_new_line_structure" : False,
"initial_scale_factor" : TEX_MOB_SCALE_FACTOR, "initial_scale_factor" : TEX_MOB_SCALE_FACTOR,
"organize_left_to_right" : False, "organize_left_to_right" : False,
@ -68,10 +68,7 @@ class TexMobject(SVGMobject):
self.handle_multiple_args() self.handle_multiple_args()
def get_modified_expression(self): def get_modified_expression(self):
separator = "" result = self.arg_separator.join(self.args)
if self.separate_list_arg_with_spaces:
separator = " "
result = separator.join(self.args)
if self.enforce_new_line_structure: if self.enforce_new_line_structure:
result = result.replace("\n", " \\\\ \n ") result = result.replace("\n", " \\\\ \n ")
return result return result

View File

@ -351,7 +351,6 @@ class Scene(object):
process.stdin.write(frame.tostring()) process.stdin.write(frame.tostring())
process.stdin.close() process.stdin.close()
process.wait() process.wait()
play_finish_sound()
# To list possible args that subclasses have # To list possible args that subclasses have
# Elements should always be a tuple # Elements should always be a tuple

View File

@ -304,10 +304,12 @@ class RandolphScene(Scene):
self.add(self.randy) self.add(self.randy)
def dither(self, time = 1, blink = True): def dither(self, time = 1, blink = True):
if blink: while time > 0:
self.play(Blink(self.randy)) if blink and time%2 == 1:
self.play(Blink(self.randy))
else:
Scene.dither(self, time)
time -= 1 time -= 1
Scene.dither(self, time)
return self return self
class TeacherStudentsScene(Scene): class TeacherStudentsScene(Scene):