Fundamentação¶
Código-fonte
main.py
from manim import *
from pathlib import Path
import os
class cena1(Scene):
def construct(self):
# ABERTURA DO VÍDEO
inicio = Text("SAEPE Animado")
fim = inicio.copy()
triangulo = Triangle(color=BLUE)
retangulo = Rectangle(width=2.5, height=1.5, color=GREEN)
pentagono = RegularPolygon(n=5, radius=1, color=ORANGE)
hexagono = RegularPolygon(n=6, radius=1, color=PURPLE)
self.wait()
self.play(Write(inicio))
self.wait()
self.play(Transform(
inicio,
fim.shift(2*UP),
path_func=utils.paths.straight_path(),
run_time=1.5,
))
self.wait()
triangulo.shift(LEFT * 4.5)
retangulo.shift(LEFT * 1.6)
pentagono.shift(RIGHT * 1.6)
hexagono.shift(RIGHT * 4.5)
self.play(Create(triangulo), Create(retangulo),
Create(pentagono), Create(hexagono))
self.wait(1)
# AGRUPAMENTO E REDUÇÃO DAS FIGURAS
grupo1 = VGroup(triangulo, retangulo, pentagono, hexagono)
self.play(grupo1.animate.scale(0.7))
self.wait(0.5)
for _ in range(4):
self.play(CyclicReplace(*grupo1))
self.wait(1)
# Agora adiciona o texto e agrupa tudo
titulo_gp = Text(
"Números e Operações/Álgebra e Funções", font="Fira Sans").scale(0.75)
titulo_gp.next_to(grupo1, DOWN, buff=0.8)
self.play(Write(titulo_gp))
self.wait(1)
grupo_com_texto = VGroup(grupo1, titulo_gp, inicio)
self.play(FadeOut(grupo_com_texto))
t1 = Text("Progressão Aritmética", font="Fira Sans").scale(0.5)
self.play(Write(t1, run_time=2))
self.wait(0.5)
linha = Line(
start=t1.get_bottom() + DOWN * 0.2 + LEFT * t1.width / 2,
end=t1.get_bottom() + DOWN * 0.2 + RIGHT * t1.width / 2,
stroke_width=6,
)
linha.set_color(RED)
# Função para atualizar a cor da linha
def atualizar_linha(obj, dt):
t = self.time
nova_cor = interpolate_color(RED, BLUE, (np.sin(t * 2) + 1) / 2)
obj.set_color(nova_cor)
linha.add_updater(atualizar_linha)
self.play(FadeIn(linha))
self.wait(1)
grupo2 = VGroup(linha, t1)
self.play(grupo2.animate.scale(0.9).to_corner(UP + LEFT), run_time=1.5)
self.wait(1.5)
explicacao = Paragraph(
r"As progressões aritméticas são sequências numéricas em que cada termo subsequente é obtido pela adição de uma constante.",
r"Para exemplificar, considere a situação ilustrada com os quadrados abaixo.",
alignment="left",
line_spacing=0.8,
font="CMU Serif"
).scale(0.35)
# Posiciona abaixo e alinha à esquerda com o grupo
explicacao.next_to(grupo2, DOWN, buff=0.3)
explicacao.align_to(grupo2, LEFT) # <- ESSENCIAL!
self.play(Write(explicacao, run_time = 1))
self.wait(1)
quadrados = VGroup(*[
VGroup(
Square(0.2*i).next_to(DOWN, UP, buff=0).shift(6*LEFT + 1.24**i*RIGHT + i*0.05*RIGHT),
MathTex(f'{i}').scale(0.7).next_to(DOWN, DOWN, buff=0.3).shift(6*LEFT + 1.24**i*RIGHT + i*0.05*RIGHT),
)
for i in range(1, 8, 2)
]).add(Tex('...').next_to(DOWN, UP, buff=0)).shift(4.5*LEFT + 1.24**8*RIGHT + 8*0.05*RIGHT)
self.play(Write(quadrados))
self.play(quadrados.animate.shift(2*LEFT))
explicacao1 = Paragraph(
r"Nessa sequência, a diferença constante entre os lados é 2, que representa a razão da progressão.",
alignment="left",
line_spacing=0.8,
font="CMU Serif"
).scale(0.35)
# Posiciona abaixo e alinha à esquerda com o grupo
explicacao1.next_to(grupo2, DOWN, buff=5)
explicacao1.align_to(grupo2, LEFT) # <- ESSENCIAL!
self.play(Write(explicacao1, run_time = 1))
self.wait(1)
explicacao_formula = Paragraph(
r"Com isso, podemos escrever uma função que calcule o tamanho do lado do n-ésimo quadrado dessa progressão.",
alignment="left",
line_spacing=0.8,
font="CMU Serif"
).scale(0.35)
# Posiciona abaixo e alinha à esquerda com o grupo
explicacao_formula.next_to(grupo2, DOWN, buff=5.5)
explicacao_formula.align_to(grupo2, LEFT) # <- ESSENCIAL!
self.play(Write(explicacao_formula, run_time = 1))
self.wait(1)
funcoes_exemplo = MathTex(r'f(1)=1\\f(2)=3\\f(3)=4\\f(4)=7').scale(0.7).shift(1.5*RIGHT + 0.2*DOWN)
funcao = MathTex('f(n) = 1 + 2n').scale(0.7).shift(4*RIGHT + 0.5*DOWN)
self.play(Write(funcoes_exemplo))
self.play(Write(funcao))
# --- Apaga todos os elementos visíveis com fade ---
self.play(*[FadeOut(mob) for mob in self.mobjects])
self.wait(0.5)
duvida = Paragraph(
r"Como podemos deduzir essa função?",
alignment="left",
line_spacing=0.8,
font="CMU Serif"
).scale(0.35)
self.play(Write(duvida))
self.wait(1.5)
self.play(FadeOut(duvida))
numeros = [
Tex(f'{i}').scale(0.9).shift(2 * LEFT + i * 0.5 * RIGHT)
for i in range(1, 8, 2)
]
steps = [
ArcBetweenPoints(start=start.get_center() + 0.05 * RIGHT,
end=end.get_center() + 0.1 * LEFT,
color=RED).shift(0.5 * DOWN)
for start, end in zip(numeros[:-1], numeros[1:])
]
steps_number = [
Tex(f'+2', color=YELLOW).scale(0.8).next_to(steps[i], DOWN, buff=0.3).shift(0.05 * LEFT)
for i in range(len(steps))
]
visualizar = VGroup(*numeros, *steps, *steps_number)
visualizar.shift(UP * 1.2)
explicacao3 = Paragraph(
r"A progressão começa em 1 e aumenta de 2 em 2. Para escrever a fórmula, precisamos do primeiro termo da progressão, no caso 1,",
r"e da diferença entre dois termos, no caso 2. Com isso, podemos ter a seguinte fórmula. Usamos n-1 pois a progressão começa a ",
r"partir da posição 0 em vez da 1.",
alignment="left",
line_spacing=0.8,
font="CMU Serif"
).scale(0.35).shift(UP*2.4)
self.play(Write(explicacao3), run_time = 2)
self.wait(1.5)
self.play(Write(visualizar, run_time = 3))
self.wait(1)
self.play(visualizar.animate.shift(4.5 * LEFT), run_time = 1.5)
formula = MathTex(r'f(n) = 1 + 2n').scale(0.7).shift(UP*1.1)
self.play(Write(formula))
formula_geral = MathTex(r'a_{n} = a_{1} + (n - 1) \cdot r').scale(0.7)
self.play(Write(formula_geral))
self.wait(1)
termos = Tex(
r'''
\raggedright
$a_n$: n-ésimo termo da progressão \\
$a_1$: primeiro termo da progressão \\
$n$: posição do termo na progressão \\
$r$: razão
'''
).scale(0.6).shift(1.2 * DOWN + 0.5*RIGHT)
self.play(Write(termos))
self.wait(1)
self.play(*[FadeOut(mob) for mob in self.mobjects])
self.wait(1.5)
Exercícios Resolvidos¶
Código-fonte
exercicio1.py
from manim import *
from pathlib import Path
import os
class cena1(Scene):
def construct(self):
# --- Título com linha animada ---
t5 = Text("Questão Progressão Aritmética (SAEPE - 2019)", font="Fira Sans").scale(0.5)
self.play(Write(t5, run_time=2))
self.wait(0.5)
linha5 = Line(
start=t5.get_bottom() + DOWN * 0.2 + LEFT * t5.width / 2,
end=t5.get_bottom() + DOWN * 0.2 + RIGHT * t5.width / 2,
stroke_width=6,
)
linha5.set_color(RED)
def atualizar_linha5(obj, dt):
tempo = self.time
nova_cor = interpolate_color(RED, BLUE, (np.sin(tempo * 2) + 1) / 2)
obj.set_color(nova_cor)
linha5.add_updater(atualizar_linha5)
self.play(FadeIn(linha5))
self.wait(1)
grupo_titulo5 = VGroup(t5, linha5)
self.play(grupo_titulo5.animate.scale(0.9).to_corner(UL), run_time=1.5)
self.wait(1)
# --- Enunciado ---
enunciado = Paragraph(
"Em março de 2017, Taís começou a trabalhar como manicure e comprou 8 vidros de esmalte. Após isso, a cada mês, ela comprou",
"2 vidros de esmalte a mais do que havia comprado no mês anterior. Em agosto de 2017, o preço de cada vidro de esmalte",
"era R$ 3,75. A quantia gasta por Taís, em agosto de 2017, na compra desses vidros de esmalte foi:",
alignment="left",
line_spacing=0.8,
font="CMU Serif"
).scale(0.35)
enunciado.next_to(grupo_titulo5, DOWN, buff=0.3)
enunciado.align_to(grupo_titulo5, LEFT)
self.play(Write(enunciado, run_time=2))
self.wait(1)
formula_geral1 = MathTex(r'a_n = a_1 + (n - 1) \cdot r').scale(0.7)
formula_geral1.next_to(enunciado, DOWN, buff=0.3)
formula_geral1.align_to(enunciado, LEFT)
self.play(Write(formula_geral1))
self.wait(1)
# --- Alternativas ---
alternativas = VGroup(
Tex("A) R\$ 37{,}50", font_size=24),
Tex("B) R\$ 45{,}00", font_size=24),
Tex("C) R\$ 52{,}50", font_size=24),
Tex("D) R\$ 67{,}50", font_size=24),
Tex("E) R\$ 75{,}00", font_size=24),
).arrange(DOWN, aligned_edge=LEFT)
alternativas.next_to(enunciado, DOWN, buff=1.6).align_to(enunciado, LEFT)
self.play(Write(alternativas))
self.wait(1)
# --- Resolução PARTE 1 ---
parte1 = VGroup(
MathTex(r"a_1 = 8", font_size=26),
MathTex(r"r = 2", font_size=26),
MathTex(r"n = 6", font_size=26, color=BLUE),
MathTex(r"a_6 = 8 + (6 - 1) \cdot 2", font_size=26),
MathTex(r"a_6 = 8 + 10 = 18", font_size=26),
).arrange(DOWN, aligned_edge=LEFT, buff=0.3)
parte1.next_to(alternativas, RIGHT, buff=1)
parte1.align_to(alternativas, UP)
for linha in parte1:
self.play(Write(linha))
self.wait(0.5)
# --- Resolução PARTE 2 ---
parte2 = VGroup(
MathTex(r"\text{Custo} = 18 \cdot 3{,}75", font_size=26),
MathTex(r"\text{Custo} = 67{,}50", font_size=26),
MathTex(r"\therefore\ \boxed{\text{R\$ 67{,}50}}", font_size=26, color=YELLOW),
).arrange(DOWN, aligned_edge=LEFT, buff=0.3)
parte2.next_to(parte1, RIGHT, buff=1)
parte2.align_to(parte1, UP)
for linha in parte2:
self.play(Write(linha))
self.wait(0.5)
# --- Destacar alternativa correta (letra D) ---
alternativa_correta = alternativas[3]
self.play(Circumscribe(alternativa_correta, color=YELLOW))
self.play(Indicate(alternativa_correta, color=YELLOW))
self.play(alternativa_correta.animate.set_color(YELLOW))
self.wait(3)
Código-fonte
exercicio2.py
from manim import *
class cena(Scene):
def construct(self):
# Título centralizado
titulo = Text("Questão Progressão Aritmética (SAEPE - 2021)", font="Fira Sans").scale(0.5)
self.play(Write(titulo))
self.wait(0.5)
# Linha exatamente do tamanho do texto
linha = Line(
start=titulo.get_bottom() + DOWN * 0.2 + LEFT * titulo.width / 2,
end=titulo.get_bottom() + DOWN * 0.2 + RIGHT * titulo.width / 2,
stroke_width=6
).set_color(RED)
# Atualizador de cor animada
linha.add_updater(lambda m, dt: m.set_color(interpolate_color(RED, BLUE, (np.sin(self.time * 2) + 1) / 2)))
self.play(FadeIn(linha))
self.wait(0.5)
# Agrupamento e movimento animado para o canto superior esquerdo
grupo_titulo = VGroup(titulo, linha)
self.play(grupo_titulo.animate.scale(0.9).to_corner(UL))
self.wait(1)
# Enunciado
enunciado = Paragraph(
r"Dentre os anos de 2000 e 2012, a exportação de uma fruta aumentou 5 000 toneladas a cada ano. Em 2010, a exportação foi",
r"de 103 000 toneladas. Quantas toneladas foram exportadas no ano 2000?",
alignment="left",
line_spacing=0.8,
font="CMU Serif"
).scale(0.35).next_to(grupo_titulo, DOWN, aligned_edge=LEFT)
self.play(Write(enunciado, run_time=2))
self.wait(0.5)
# Fórmula
formula = MathTex(r"a_n = a_1 + (n - 1) \cdot r").scale(0.65)
formula.next_to(enunciado, DOWN, buff=0.8).align_to(enunciado, LEFT)
self.play(Write(formula))
self.wait(0.5)
# Alternativas
alternativas = VGroup(
Tex("A) 58 000", font_size=24),
Tex("B) 53 000", font_size=24),
Tex("C) 9 800", font_size=24),
Tex("D) 7 923", font_size=24),
Tex("E) 5 300", font_size=24),
).arrange(DOWN, aligned_edge=LEFT, buff=0.3)
alternativas.next_to(formula, DOWN, buff=0.8).align_to(formula, LEFT)
self.play(Write(alternativas))
self.wait(1)
# Resolução passo a passo
passo1 = MathTex(r"a_{11} = 103\,000", font_size=26)
passo2 = MathTex(r"a_1 + 10 \cdot 5\,000 = 103\,000", font_size=26)
passo3 = MathTex(r"a_1 + 50\,000 = 103\,000", font_size=26)
passo4 = MathTex(r"a_1 = 103\,000 - 50\,000", font_size=26)
passo5 = MathTex(r"a_1 = 53\,000", font_size=26, color=YELLOW)
passos = VGroup(passo1, passo2, passo3, passo4, passo5).arrange(DOWN, aligned_edge=LEFT, buff=0.3)
passos.shift(RIGHT * 2.8 + DOWN * 1)
for p in passos:
self.play(Write(p))
self.wait(0.4)
# Destacar alternativa correta (letra B)
alternativa_correta = alternativas[1]
self.play(Circumscribe(alternativa_correta, color=YELLOW))
self.play(Indicate(alternativa_correta, color=YELLOW))
self.play(alternativa_correta.animate.set_color(YELLOW))
self.wait(2)