mirror of
https://github.com/3b1b/manim.git
synced 2025-08-01 17:29:06 +08:00
First full pass of crypto animations
This commit is contained in:
634
crypto.py
634
crypto.py
@ -65,6 +65,28 @@ def sha256_tex_mob(message, n_forced_start_zeros = 0):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
class EthereumLogo(SVGMobject):
|
||||||
|
CONFIG = {
|
||||||
|
"file_name" : "ethereum_logo",
|
||||||
|
"stroke_width" : 0,
|
||||||
|
"fill_opacity" : 1,
|
||||||
|
"color_chars" : "8B8B48",
|
||||||
|
"height" : 0.5,
|
||||||
|
}
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
SVGMobject.__init__(self, **kwargs)
|
||||||
|
for part, char in zip(self.submobjects, self.color_chars):
|
||||||
|
part.highlight("#" + 6*char)
|
||||||
|
|
||||||
|
class LitecoinLogo(SVGMobject):
|
||||||
|
CONFIG = {
|
||||||
|
"file_name" : "litecoin_logo",
|
||||||
|
"stroke_width" : 0,
|
||||||
|
"fill_opacity" : 1,
|
||||||
|
"fill_color" : LIGHT_GREY,
|
||||||
|
"height" : 0.5,
|
||||||
|
}
|
||||||
|
|
||||||
class TenDollarBill(VGroup):
|
class TenDollarBill(VGroup):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"color" : GREEN,
|
"color" : GREEN,
|
||||||
@ -159,12 +181,6 @@ class AskQuestion(Scene):
|
|||||||
self.dither(self.time_per_char*n_spaces)
|
self.dither(self.time_per_char*n_spaces)
|
||||||
self.dither(2)
|
self.dither(2)
|
||||||
|
|
||||||
# class BitcoinPaperHighlightTitle(ExternallyAnimatedScene):
|
|
||||||
# pass
|
|
||||||
|
|
||||||
# class TimeBitcoinCover(ExternallyAnimatedScene):
|
|
||||||
# pass
|
|
||||||
|
|
||||||
class ListOfAttributes(Scene):
|
class ListOfAttributes(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
logo = BitcoinLogo()
|
logo = BitcoinLogo()
|
||||||
@ -321,6 +337,81 @@ class Hype(TeacherStudentsScene):
|
|||||||
)
|
)
|
||||||
self.dither(3)
|
self.dither(3)
|
||||||
|
|
||||||
|
class NoCommentOnSpeculation(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
axes = VGroup(
|
||||||
|
Line(0.25*LEFT, 4*RIGHT),
|
||||||
|
Line(0.25*DOWN, 3*UP),
|
||||||
|
)
|
||||||
|
times = np.arange(0, 4.25, 0.25)
|
||||||
|
prices = [
|
||||||
|
0.1, 0.5, 1.75, 1.5,
|
||||||
|
2.75, 2.2, 1.3, 0.8,
|
||||||
|
1.1, 1.3, 1.2, 1.4,
|
||||||
|
1.5, 1.7, 1.2, 1.3,
|
||||||
|
]
|
||||||
|
graph = VMobject()
|
||||||
|
graph.set_points_as_corners([
|
||||||
|
time*RIGHT + price*UP
|
||||||
|
for time, price in zip(times, prices)
|
||||||
|
])
|
||||||
|
graph.set_stroke(BLUE)
|
||||||
|
group = VGroup(axes, graph)
|
||||||
|
group.next_to(self.teacher, UP+LEFT)
|
||||||
|
|
||||||
|
cross = Cross(group)
|
||||||
|
|
||||||
|
mining_graphic = ImageMobject("bitcoin_mining_graphic")
|
||||||
|
mining_graphic.scale_to_fit_height(2)
|
||||||
|
mining_graphic.next_to(self.teacher, UP+LEFT)
|
||||||
|
mining_cross = Cross(mining_graphic)
|
||||||
|
mining_cross.set_stroke(RED, 8)
|
||||||
|
|
||||||
|
axes.save_state()
|
||||||
|
axes.shift(DOWN)
|
||||||
|
axes.fade(1)
|
||||||
|
self.play(
|
||||||
|
self.teacher.change, "sassy",
|
||||||
|
axes.restore,
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(
|
||||||
|
graph, run_time = 2,
|
||||||
|
rate_func = None
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
self.play(ShowCreation(cross))
|
||||||
|
group.add(cross)
|
||||||
|
self.play(
|
||||||
|
group.shift, 2*SPACE_WIDTH*RIGHT,
|
||||||
|
self.teacher.change, "happy"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
self.student_says(
|
||||||
|
"But...what are they?",
|
||||||
|
student_index = 0,
|
||||||
|
target_mode = "confused"
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
FadeIn(mining_graphic),
|
||||||
|
RemovePiCreatureBubble(self.students[0]),
|
||||||
|
self.teacher.change, "sassy",
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(mining_cross))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
VGroup(mining_graphic, mining_cross).shift,
|
||||||
|
2*SPACE_WIDTH*RIGHT
|
||||||
|
)
|
||||||
|
black_words = TextMobject("Random words\\\\Blah blah")
|
||||||
|
black_words.highlight(BLACK)
|
||||||
|
self.teacher_thinks(black_words)
|
||||||
|
self.zoom_in_on_thought_bubble()
|
||||||
|
|
||||||
|
class MiningIsALotteryCopy(ExternallyAnimatedScene):
|
||||||
|
pass
|
||||||
|
|
||||||
class LedgerScene(PiCreatureScene):
|
class LedgerScene(PiCreatureScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"ledger_width" : 6,
|
"ledger_width" : 6,
|
||||||
@ -407,7 +498,7 @@ class LedgerScene(PiCreatureScene):
|
|||||||
|
|
||||||
amount_color = {
|
amount_color = {
|
||||||
"USD" : GREEN,
|
"USD" : GREEN,
|
||||||
"BTC" : BITCOIN_COLOR,
|
"BTC" : YELLOW,
|
||||||
"LD" : YELLOW,
|
"LD" : YELLOW,
|
||||||
}.get(self.denomination, WHITE)
|
}.get(self.denomination, WHITE)
|
||||||
line.highlight_by_tex(amount_str, amount_color)
|
line.highlight_by_tex(amount_str, amount_color)
|
||||||
@ -4197,29 +4288,514 @@ class VariableProofOfWork(WhenToTrustANewBlock):
|
|||||||
e = self.n_proof_of_work_digits
|
e = self.n_proof_of_work_digits
|
||||||
return Integer(random.randint(10**e, 10**(e+1)))
|
return Integer(random.randint(10**e, 10**(e+1)))
|
||||||
|
|
||||||
class CompareBLockTimes(Scene):
|
class CompareBlockTimes(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
pass
|
title = TextMobject("Average block time")
|
||||||
|
title.scale(1.5)
|
||||||
|
title.to_edge(UP)
|
||||||
|
h_line = Line(LEFT, RIGHT)
|
||||||
|
h_line.scale_to_fit_width(SPACE_WIDTH)
|
||||||
|
h_line.next_to(title, DOWN, SMALL_BUFF)
|
||||||
|
|
||||||
|
examples = VGroup(
|
||||||
|
TextMobject("BTC: ", "10 minutes"),
|
||||||
|
TextMobject("ETH: ", "15 Seconds"),
|
||||||
|
TextMobject("XRP: ", "3.5 Seconds"),
|
||||||
|
TextMobject("LTC: ", "2.5 Minutes"),
|
||||||
|
)
|
||||||
|
examples.arrange_submobjects(
|
||||||
|
DOWN,
|
||||||
|
buff = LARGE_BUFF,
|
||||||
|
aligned_edge = LEFT,
|
||||||
|
)
|
||||||
|
examples.next_to(h_line, DOWN)
|
||||||
|
logos = VGroup(
|
||||||
|
BitcoinLogo(),
|
||||||
|
ImageMobject("ethereum_logo"),
|
||||||
|
ImageMobject("ripple_logo"),
|
||||||
|
SVGMobject(
|
||||||
|
file_name = "litecoin_logo",
|
||||||
|
stroke_width = 0,
|
||||||
|
fill_opacity = 1,
|
||||||
|
fill_color = LIGHT_GREY,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
colors = [BITCOIN_COLOR, BLUE_D, BLUE_B, LIGHT_GREY]
|
||||||
|
for logo, example, color in zip(logos, examples, colors):
|
||||||
|
logo.scale_to_fit_height(0.5)
|
||||||
|
logo.next_to(example, LEFT)
|
||||||
|
example[0].highlight(color)
|
||||||
|
|
||||||
|
self.add(title, h_line)
|
||||||
|
self.play(
|
||||||
|
FadeIn(examples[0]),
|
||||||
|
DrawBorderThenFill(logos[0])
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(*[
|
||||||
|
LaggedStart(FadeIn, VGroup(*group[1:]))
|
||||||
|
for group in examples, logos
|
||||||
|
])
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
# def get_ethereum_logo(self):
|
||||||
|
# logo = SVGMobject(
|
||||||
|
# file_name = "ethereum_logo",
|
||||||
|
# height = 1,
|
||||||
|
# )
|
||||||
|
# logo.set_fill(GREEN, 1)
|
||||||
|
# logo.set_stroke(WHITE, 3)
|
||||||
|
# logo.gradient_highlight(GREEN_B, GREEN_D)
|
||||||
|
# logo.scale_to_fit_width(1)
|
||||||
|
# logo.center()
|
||||||
|
# self.add(SurroundingRectangle(logo))
|
||||||
|
# return logo
|
||||||
|
|
||||||
|
class BlockRewards(Scene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject("Block rewards")
|
||||||
|
title.scale(1.5)
|
||||||
|
logo = BitcoinLogo()
|
||||||
|
logo.scale_to_fit_height(0.75)
|
||||||
|
logo.next_to(title, LEFT)
|
||||||
|
title.add(logo)
|
||||||
|
title.to_edge(UP)
|
||||||
|
h_line = Line(LEFT, RIGHT)
|
||||||
|
h_line.scale_to_fit_width(SPACE_WIDTH)
|
||||||
|
h_line.next_to(title, DOWN)
|
||||||
|
self.add(title, logo, h_line)
|
||||||
|
|
||||||
|
rewards = VGroup(
|
||||||
|
TextMobject("Jan 2009 - Nov 2012:", "50", "BTC"),
|
||||||
|
TextMobject("Nov 2012 - Jul 2016:", "25", "BTC"),
|
||||||
|
TextMobject("Jul 2016 - Feb 2020$^*$:", "12.5", "BTC"),
|
||||||
|
TextMobject("Feb 2020$^*$ - Sep 2023$^*$:", "6.25", "BTC"),
|
||||||
|
)
|
||||||
|
rewards.arrange_submobjects(
|
||||||
|
DOWN,
|
||||||
|
buff = MED_LARGE_BUFF,
|
||||||
|
aligned_edge = LEFT
|
||||||
|
)
|
||||||
|
rewards.next_to(h_line, DOWN)
|
||||||
|
for reward in rewards:
|
||||||
|
reward[1].highlight(YELLOW)
|
||||||
|
|
||||||
|
footnote = TextMobject(
|
||||||
|
"$^*$ Extrapolating from the 25 BTC reward period"
|
||||||
|
)
|
||||||
|
footnote.scale(0.5)
|
||||||
|
footnote.to_corner(DOWN+RIGHT)
|
||||||
|
|
||||||
|
self.play(LaggedStart(
|
||||||
|
FadeIn, rewards,
|
||||||
|
run_time = 4,
|
||||||
|
lag_ratio = 0.5
|
||||||
|
))
|
||||||
|
self.play(FadeIn(footnote))
|
||||||
|
self.dither(3)
|
||||||
|
|
||||||
|
class ShowFirstFewBlocks(ExternallyAnimatedScene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ShowGeometricSum(Scene):
|
||||||
|
def construct(self):
|
||||||
|
equation = TexMobject(
|
||||||
|
"210{,}000", "(",
|
||||||
|
"50", "+", "25", "+", "12.5", "+",
|
||||||
|
"6.25", "+\\cdots", ")", "=", "21{,}000{,}000"
|
||||||
|
)
|
||||||
|
numbers = ["50", "25", "12.5", "6.25"]
|
||||||
|
colors = color_gradient([BLUE_D, BLUE_B], 4)
|
||||||
|
for tex, color in zip(numbers, colors):
|
||||||
|
equation.highlight_by_tex(tex, color)
|
||||||
|
equation[-1].highlight(YELLOW)
|
||||||
|
|
||||||
|
self.add(*equation[:2] + equation[-3:-1])
|
||||||
|
for i in range(2, 9, 2):
|
||||||
|
self.play(FadeIn(VGroup(*equation[i:i+2])))
|
||||||
|
self.dither()
|
||||||
|
self.play(Write(equation[-1]))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
class TransactionFeeExample(PiCreatureScene):
|
||||||
|
def construct(self):
|
||||||
|
alice = self.pi_creature
|
||||||
|
payment = TextMobject(
|
||||||
|
"Alice", "pays", "Bob", "0.42 BTC",
|
||||||
|
)
|
||||||
|
payment.highlight_by_tex("Alice", BLUE_C)
|
||||||
|
payment.highlight_by_tex("Bob", MAROON)
|
||||||
|
payment.highlight_by_tex("BTC", YELLOW)
|
||||||
|
payment.move_to(2.5*UP)
|
||||||
|
|
||||||
|
fee = TextMobject("And leaves", "0.001 BTC", "to the miner")
|
||||||
|
fee.highlight_by_tex("BTC", YELLOW)
|
||||||
|
fee.next_to(payment, DOWN)
|
||||||
|
|
||||||
|
signature = TextMobject(
|
||||||
|
"$\\langle$Alice's digital signature$\\rangle$"
|
||||||
|
)
|
||||||
|
signature.highlight(BLUE_C)
|
||||||
|
signature.next_to(fee, DOWN)
|
||||||
|
|
||||||
|
group = VGroup(payment, fee, signature)
|
||||||
|
rect = SurroundingRectangle(group, color = BLUE_B)
|
||||||
|
|
||||||
|
incentive_words = TextMobject(
|
||||||
|
"Incentivizes miner \\\\ to include"
|
||||||
|
)
|
||||||
|
incentive_words.next_to(rect, DOWN, buff = 1.5)
|
||||||
|
incentive_words.shift(2*RIGHT)
|
||||||
|
arrow = Arrow(
|
||||||
|
incentive_words.get_top(),
|
||||||
|
rect.get_bottom(),
|
||||||
|
buff = MED_LARGE_BUFF
|
||||||
|
)
|
||||||
|
|
||||||
|
fee.save_state()
|
||||||
|
fee.shift(DOWN)
|
||||||
|
fee.set_fill(opacity = 0)
|
||||||
|
|
||||||
|
self.play(Write(payment))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
alice.change, "raise_right_hand", payment,
|
||||||
|
fee.restore,
|
||||||
|
)
|
||||||
|
self.play(Write(signature))
|
||||||
|
self.play(
|
||||||
|
ShowCreation(rect),
|
||||||
|
alice.change_mode, "happy"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Write(incentive_words),
|
||||||
|
ShowCreation(arrow),
|
||||||
|
alice.change, "pondering"
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
def create_pi_creature(self):
|
||||||
|
alice = PiCreature(color = BLUE_C)
|
||||||
|
alice.to_edge(DOWN)
|
||||||
|
alice.shift(SPACE_WIDTH*LEFT/2)
|
||||||
|
return alice
|
||||||
|
|
||||||
|
class ShowBitcoinBlockSize(LedgerScene):
|
||||||
|
CONFIG = {
|
||||||
|
"denomination" : "BTC"
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
block = VGroup()
|
||||||
|
ledger = self.get_ledger()
|
||||||
|
|
||||||
|
payments = VGroup(*[
|
||||||
|
self.add_payment_line_to_ledger(*args)
|
||||||
|
for args in [
|
||||||
|
("Alice", "Bob", "0.42"),
|
||||||
|
("You", "Charlie", "3.14"),
|
||||||
|
("Bob", "You", "2.72"),
|
||||||
|
("Alice", "Charlie", "4.67"),
|
||||||
|
]
|
||||||
|
])
|
||||||
|
dots = TexMobject("\\vdots")
|
||||||
|
dots.next_to(payments, DOWN)
|
||||||
|
payments.add(dots)
|
||||||
|
payments.to_edge(LEFT)
|
||||||
|
payments.shift(DOWN+0.5*RIGHT)
|
||||||
|
payments_rect = SurroundingRectangle(
|
||||||
|
payments, color = WHITE, buff = MED_LARGE_BUFF
|
||||||
|
)
|
||||||
|
block.add(payments_rect, payments)
|
||||||
|
|
||||||
|
tuples = [
|
||||||
|
("Prev hash", UP, BLUE_C),
|
||||||
|
("Proof of work", DOWN, GREEN),
|
||||||
|
]
|
||||||
|
for word, vect, color in tuples:
|
||||||
|
mob = TextMobject(word)
|
||||||
|
mob.highlight(color)
|
||||||
|
rect = SurroundingRectangle(
|
||||||
|
mob, color = WHITE, buff = MED_SMALL_BUFF
|
||||||
|
)
|
||||||
|
VGroup(mob, rect).next_to(payments_rect, vect, 0)
|
||||||
|
rect.stretch_to_fit_width(payments_rect.get_width())
|
||||||
|
block.add(mob, rect)
|
||||||
|
|
||||||
|
title = VGroup(
|
||||||
|
BitcoinLogo(height = 0.75),
|
||||||
|
TextMobject("Block").scale(1.5)
|
||||||
|
)
|
||||||
|
title.arrange_submobjects(RIGHT, SMALL_BUFF)
|
||||||
|
title.next_to(block, UP)
|
||||||
|
|
||||||
|
brace = Brace(payments_rect, RIGHT)
|
||||||
|
limit = brace.get_text(
|
||||||
|
"Limited to\\\\",
|
||||||
|
"$\\sim 2{,}400$", "transactions"
|
||||||
|
)
|
||||||
|
limit.highlight_by_tex("2{,}400", RED)
|
||||||
|
|
||||||
|
self.add(title, block)
|
||||||
|
self.remove(payments)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(limit)
|
||||||
|
)
|
||||||
|
self.play(LaggedStart(FadeIn, payments))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
####Visa
|
||||||
|
|
||||||
|
visa_logo = SVGMobject(
|
||||||
|
file_name = "visa_logo",
|
||||||
|
height = 0.5,
|
||||||
|
stroke_width = 0,
|
||||||
|
fill_color = BLUE_D,
|
||||||
|
fill_opacity = 1,
|
||||||
|
)
|
||||||
|
visa_logo[-1].highlight("#faa61a")
|
||||||
|
visa_logo.sort_submobjects()
|
||||||
|
avg_rate = TextMobject("Avg: $1{,}700$/second")
|
||||||
|
max_rate = TextMobject("Max: $>24{,}000$/second")
|
||||||
|
rates = VGroup(avg_rate, max_rate)
|
||||||
|
rates.scale(0.8)
|
||||||
|
rates.arrange_submobjects(DOWN, aligned_edge = LEFT)
|
||||||
|
rates.next_to(visa_logo, RIGHT, buff = MED_SMALL_BUFF)
|
||||||
|
visa = VGroup(visa_logo, rates)
|
||||||
|
visa.to_corner(UP+RIGHT)
|
||||||
|
|
||||||
|
self.play(LaggedStart(DrawBorderThenFill, visa_logo))
|
||||||
|
self.play(LaggedStart(FadeIn, avg_rate))
|
||||||
|
self.dither()
|
||||||
|
self.play(LaggedStart(FadeIn, max_rate))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
class CurrentAverageFees(Scene):
|
||||||
|
def construct(self):
|
||||||
|
fees = TextMobject(
|
||||||
|
"Current average fees: ",
|
||||||
|
"$\\sim 0.0013$ BTC",
|
||||||
|
"$\\approx$", "\\$3.39"
|
||||||
|
)
|
||||||
|
fees.highlight_by_tex("BTC", YELLOW)
|
||||||
|
fees.highlight_by_tex("\\$", GREEN)
|
||||||
|
fees.to_edge(UP)
|
||||||
|
|
||||||
|
self.play(Write(fees))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class HighlightingAFewFees(ExternallyAnimatedScene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TopicsNotCovered(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject("Topics not covered:")
|
||||||
|
title.to_corner(UP+LEFT)
|
||||||
|
title.highlight(YELLOW)
|
||||||
|
title.save_state()
|
||||||
|
title.shift(DOWN)
|
||||||
|
title.set_fill(opacity = 0)
|
||||||
|
|
||||||
|
topics = VGroup(*map(TextMobject, [
|
||||||
|
"Merkle trees",
|
||||||
|
"Alternatives to proof of work",
|
||||||
|
"Scripting",
|
||||||
|
"$\\vdots$",
|
||||||
|
"(See links in description)",
|
||||||
|
]))
|
||||||
|
topics.arrange_submobjects(DOWN, aligned_edge = LEFT)
|
||||||
|
topics[-2].next_to(topics[-3], DOWN)
|
||||||
|
topics.next_to(title, RIGHT)
|
||||||
|
topics.to_edge(UP)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
title.restore,
|
||||||
|
self.teacher.change_mode, "raise_right_hand"
|
||||||
|
)
|
||||||
|
for topic in topics:
|
||||||
|
self.change_student_modes(
|
||||||
|
"confused", "thinking","pondering",
|
||||||
|
look_at_arg = topic,
|
||||||
|
added_anims = [LaggedStart(FadeIn, topic)]
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class Exchange(Animation):
|
||||||
|
CONFIG = {
|
||||||
|
"rate_func" : None,
|
||||||
|
}
|
||||||
|
def __init__(self, exchange, **kwargs):
|
||||||
|
self.swap = Swap(
|
||||||
|
exchange.left,
|
||||||
|
exchange.right,
|
||||||
|
)
|
||||||
|
self.changed_symbols_yet = False
|
||||||
|
Animation.__init__(self, exchange, **kwargs)
|
||||||
|
|
||||||
|
def update_mobject(self, alpha):
|
||||||
|
exchange = self.mobject
|
||||||
|
if alpha < 1./3:
|
||||||
|
self.swap.update(3*alpha)
|
||||||
|
elif alpha < 2./3:
|
||||||
|
sub_alpha = alpha*3 - 1
|
||||||
|
group = VGroup(exchange.left, exchange.right)
|
||||||
|
group.set_fill(opacity = 1-smooth(sub_alpha))
|
||||||
|
else:
|
||||||
|
if not self.changed_symbols_yet:
|
||||||
|
new_left = random.choice(
|
||||||
|
exchange.cryptocurrencies
|
||||||
|
).copy()
|
||||||
|
new_left.move_to(exchange.right)
|
||||||
|
new_right = random.choice(
|
||||||
|
exchange.currencies
|
||||||
|
).copy()
|
||||||
|
new_right.move_to(exchange.left)
|
||||||
|
Transform(exchange.left, new_left).update(1)
|
||||||
|
Transform(exchange.right, new_right).update(1)
|
||||||
|
self.changed_symbols_yet = True
|
||||||
|
sub_alpha = 3*alpha - 2
|
||||||
|
group = VGroup(exchange.left, exchange.right)
|
||||||
|
group.set_fill(opacity = smooth(sub_alpha))
|
||||||
|
|
||||||
|
class ShowManyExchanges(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"n_rows" : 2,
|
||||||
|
"n_cols" : 8,
|
||||||
|
"shift_radius" : 0.5,
|
||||||
|
"run_time" : 30,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
cryptocurrencies = [
|
||||||
|
BitcoinLogo(),
|
||||||
|
BitcoinLogo(),
|
||||||
|
BitcoinLogo(),
|
||||||
|
EthereumLogo(),
|
||||||
|
LitecoinLogo()
|
||||||
|
]
|
||||||
|
currencies = [
|
||||||
|
TexMobject("\\$").highlight(GREEN),
|
||||||
|
TexMobject("\\$").highlight(GREEN),
|
||||||
|
TexMobject("\\$").highlight(GREEN),
|
||||||
|
SVGMobject(
|
||||||
|
file_name = "euro_symbol",
|
||||||
|
stroke_width = 0,
|
||||||
|
fill_opacity = 1,
|
||||||
|
fill_color = BLUE,
|
||||||
|
),
|
||||||
|
SVGMobject(
|
||||||
|
file_name = "yen_symbol",
|
||||||
|
stroke_width = 0,
|
||||||
|
fill_opacity = 1,
|
||||||
|
fill_color = RED,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
for currency in it.chain(currencies, cryptocurrencies):
|
||||||
|
currency.scale_to_fit_height(0.5)
|
||||||
|
currency.align_data(EthereumLogo())
|
||||||
|
exchange = VGroup(*[
|
||||||
|
Arrow(
|
||||||
|
p1, p2,
|
||||||
|
path_arc = np.pi,
|
||||||
|
buff = MED_LARGE_BUFF
|
||||||
|
)
|
||||||
|
for p1, p2 in (LEFT, RIGHT), (RIGHT, LEFT)
|
||||||
|
]).highlight(WHITE)
|
||||||
|
exchanges = VGroup(*[
|
||||||
|
VGroup(*[
|
||||||
|
exchange.copy()
|
||||||
|
for x in range(3)
|
||||||
|
]).arrange_submobjects(RIGHT, buff = 2*LARGE_BUFF)
|
||||||
|
for y in range(3)
|
||||||
|
]).arrange_submobjects(DOWN, buff = MED_LARGE_BUFF)
|
||||||
|
exchanges = VGroup(*it.chain(*exchanges))
|
||||||
|
self.add(exchanges)
|
||||||
|
start_times = list(np.linspace(0, 2, len(exchanges)))
|
||||||
|
random.shuffle(start_times)
|
||||||
|
for exchange, start_time in zip(exchanges, start_times):
|
||||||
|
left = random.choice(cryptocurrencies).copy()
|
||||||
|
right = random.choice(currencies).copy()
|
||||||
|
left.move_to(exchange.get_left())
|
||||||
|
right.move_to(exchange.get_right())
|
||||||
|
|
||||||
|
exchange.left = left
|
||||||
|
exchange.right = right
|
||||||
|
exchange.start_time = start_time
|
||||||
|
exchange.add(left, right)
|
||||||
|
exchange.currencies = currencies
|
||||||
|
exchange.cryptocurrencies = cryptocurrencies
|
||||||
|
exchange.animation = Exchange(exchange)
|
||||||
|
|
||||||
|
times = np.arange(0, self.run_time, self.frame_duration)
|
||||||
|
from scene.scene import ProgressDisplay
|
||||||
|
for t in ProgressDisplay(times):
|
||||||
|
for exchange in exchanges:
|
||||||
|
sub_t = t - exchange.start_time
|
||||||
|
if sub_t < 0:
|
||||||
|
continue
|
||||||
|
elif sub_t > 3:
|
||||||
|
exchange.start_time = t
|
||||||
|
sub_t = 0
|
||||||
|
exchange.animation = Exchange(exchange)
|
||||||
|
exchange.animation.update(sub_t/3.0)
|
||||||
|
self.update_frame(
|
||||||
|
self.extract_mobject_family_members(exchanges)
|
||||||
|
)
|
||||||
|
self.add_frames(self.get_frame())
|
||||||
|
|
||||||
|
class CryptoPatreonThanks(PatreonThanks):
|
||||||
|
CONFIG = {
|
||||||
|
"specific_patrons" : [
|
||||||
|
"Ali Yahya",
|
||||||
|
"Desmos",
|
||||||
|
"Burt Humburg",
|
||||||
|
"CrypticSwarm",
|
||||||
|
"Juan Benet",
|
||||||
|
"Samantha D. Suplee",
|
||||||
|
"James Park",
|
||||||
|
"Erik Sundell",
|
||||||
|
"Yana Chernobilsky",
|
||||||
|
"Kaustuv DeBiswas",
|
||||||
|
"Kathryn Schmiedicke",
|
||||||
|
"Karan Bhargava",
|
||||||
|
"Yu Jun",
|
||||||
|
"Dave Nicponski",
|
||||||
|
"Damion Kistler",
|
||||||
|
"Markus Persson",
|
||||||
|
"Yoni Nazarathy",
|
||||||
|
"Ed Kellett",
|
||||||
|
"Joseph John Cox",
|
||||||
|
"Dan Buchoff",
|
||||||
|
"Luc Ritchie",
|
||||||
|
"Andrew Busey",
|
||||||
|
"Michael McGuffin",
|
||||||
|
"John Haley",
|
||||||
|
"Mourits de Beer",
|
||||||
|
"Ankalagon",
|
||||||
|
"Eric Lavault",
|
||||||
|
"Tomohiro Furusawa",
|
||||||
|
"Boris Veselinovich",
|
||||||
|
"Julian Pulgarin",
|
||||||
|
"Jeff Linse",
|
||||||
|
"Cooper Jones",
|
||||||
|
"Ryan Dahl",
|
||||||
|
"Mark Govea",
|
||||||
|
"Robert Teed",
|
||||||
|
"Jason Hise",
|
||||||
|
"Meshal Alshammari",
|
||||||
|
"Bernd Sing",
|
||||||
|
"Nils Schneider",
|
||||||
|
"James Thornton",
|
||||||
|
"Mustafa Mahdi",
|
||||||
|
"Mathew Bramson",
|
||||||
|
"Jerry Ling",
|
||||||
|
"Vecht",
|
||||||
|
"Shimin Kuang",
|
||||||
|
"Rish Kundalia",
|
||||||
|
"Achille Brighton",
|
||||||
|
"Ripta Pasay",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ class PatreonThanks(Scene):
|
|||||||
"Felipe Diniz",
|
"Felipe Diniz",
|
||||||
],
|
],
|
||||||
"max_patron_group_size" : 20,
|
"max_patron_group_size" : 20,
|
||||||
"patron_scale_val" : 0.7,
|
"patron_scale_val" : 0.8,
|
||||||
|
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
Reference in New Issue
Block a user