반응형
파이썬의 for 루프를 설명하기 위한 애니메이션입니다.
설명하기 위한 for 루프를 사용한 파이썬 코드는 1에서 100까지 합을 구한는 코드
sum = 0
for i in range(1,101,1):
sum = sum + i
애니메이션의 핵심은, 변수 i와 sum의 값이 for 루프를 돌면서 어떻게 변하는 지를 잘 보여주는 것.
이를 위해서 i값과 sum값이 차례로 위 쪽으로 이동하면서 변하는 객체를 만들어서 처리해야겠습니다. 사다리 모양이어서 객체 이름은 VarLadder로. `변수를 처리하는 사다리` 정도의 의미 .^^
작성된 VarLadder 클래스에 대한 코드는 아래와 같습니다.
class VarLadder(VGroup):
CONFIG = {
"rect_cnt": 3,
"decimal_scale": 0.7,
"rect_width": 0.5,
"rect_height": 0.4
}
def __init__(self, **kwargs):
digest_config(self, kwargs, locals())
super().__init__(**kwargs)
self.gen_objects()
def gen_objects(self):
def get_rect(idx):
stroke_width = 0
if idx == self.rect_cnt - 1:
stroke_width = 3
r = Rectangle(fill_opacity=0, stroke_width=stroke_width, stroke_opacity=0.8, stroke_color=GREY, )
r.set_width(self.rect_width, stretch=True)
r.set_height(self.rect_height, stretch=True)
return r
rects = VGroup(*[get_rect(i) for i in range(self.rect_cnt + 2)])
rects.arrange(DOWN, buff=0)
decimals=[]
for i in range(1,4):
decimal = self.get_decimals(0, rects[i], color=BLACK)
decimals.append(decimal)
self.add(rects, *decimals)
self.rects = rects
self.decimals = decimals
self.cur_seq=0
def get_decimals(self, num=0, rect=None, color=WHITE):
t = DecimalNumber(num, num_decimal_places=0, color=color)
t.scale(self.decimal_scale)
if rect is not None:
t.move_to(rect)
return t
def set_decimal(self, d0=None, d1=None, d2=None):
d = self.decimals
if d0 is not None:
d[0].set_value(d0)
d[0].set_color(WHITE)
else:
d[0].set_color(BLACK)
if d1 is not None:
d[1].set_value(d1)
d[1].set_color(WHITE)
else:
d[1].set_color(BLACK)
if d2 is not None:
d[2].set_value(d2)
d[2].set_color(WHITE)
else:
d[2].set_color(BLACK)
def push(self, n, scene, run_time=1):
d = self.decimals
r = self.rects
d_new = self.get_decimals(num=n, color=BLACK )
d_new.move_to(self.rects[4])
scene.play(
d_new.set_color, WHITE,
d_new.move_to, r[3],
d[2].move_to, r[2],
d[1].move_to, r[1],
d[0].move_to, r[0],
d[0].set_color, BLACK,
run_time=run_time,
)
d[0] = d[1]
d[1] = d[2]
d[2] = d_new
def push2(self, n, scene, run_time=1,):
d = self.decimals
r = self.rects
d_new = self.get_decimals(num=n, color=BLACK)
d_new.move_to(self.rects[3])
scene.play(
d_new.set_color, WHITE,
d_new.move_to, r[2],
d[1].move_to, r[1],
d[0].move_to, r[0],
d[0].set_color, BLACK,
run_time=run_time,
)
d[0] = d[1]
d[1] = d_new
class VarLadderTest(Scene):
def construct(self):
ladder = VarLadder()
# ladder.set_decimal(None, 1, 2)
# self.add(ladder)
# self.wait()
#
# ladder.push(3, self)
# ladder.push(4, self)
# ladder.push(5, self)
ladder.set_decimal(None,0,None)
self.add(ladder)
self.wait()
ladder.push2(1, self)
ladder.push2(3, self)
ladder.push2(5, self)
좀 더 일반적으로 사용할 수 있는 컴포넌트로 만들고도 싶었으나, 시간이 없어서, 그냥 for 루프에서의 i와 sum에서 사용할 수 있는 정도의 기능만을 넣었습니다.
i 처럼 sequential하게 증가할 때 사용하는 메서드로 push를, sum처럼 sequential하지 않은 것은 push2 메서드를 사용하면 됩니다.
음성은 네이버 클로바 서비스를 이용해서 만들고, 이 파일을 manim에서 직접 호출하는 방식으로 만들어 봤습니다.
만들어진 동영상은,
전체 소스 코드는,
class VarLadder(VGroup):
CONFIG = {
"rect_cnt": 3,
"decimal_scale": 0.7,
"rect_width": 0.5,
"rect_height": 0.4
}
def __init__(self, **kwargs):
digest_config(self, kwargs, locals())
super().__init__(**kwargs)
self.gen_objects()
def gen_objects(self):
def get_rect(idx):
stroke_width = 0
if idx == self.rect_cnt - 1:
stroke_width = 3
r = Rectangle(fill_opacity=0, stroke_width=stroke_width, stroke_opacity=0.8, stroke_color=GREY, )
r.set_width(self.rect_width, stretch=True)
r.set_height(self.rect_height, stretch=True)
return r
rects = VGroup(*[get_rect(i) for i in range(self.rect_cnt + 2)])
rects.arrange(DOWN, buff=0)
decimals=[]
for i in range(1,4):
decimal = self.get_decimals(0, rects[i], color=BLACK)
decimals.append(decimal)
self.add(rects, *decimals)
self.rects = rects
self.decimals = decimals
self.cur_seq=0
def get_decimals(self, num=0, rect=None, color=WHITE):
t = DecimalNumber(num, num_decimal_places=0, color=color)
t.scale(self.decimal_scale)
if rect is not None:
t.move_to(rect)
return t
def set_decimal(self, d0=None, d1=None, d2=None):
d = self.decimals
if d0 is not None:
d[0].set_value(d0)
d[0].set_color(WHITE)
else:
d[0].set_color(BLACK)
if d1 is not None:
d[1].set_value(d1)
d[1].set_color(WHITE)
else:
d[1].set_color(BLACK)
if d2 is not None:
d[2].set_value(d2)
d[2].set_color(WHITE)
else:
d[2].set_color(BLACK)
def push(self, n, scene, run_time=1):
d = self.decimals
r = self.rects
d_new = self.get_decimals(num=n, color=BLACK )
d_new.move_to(self.rects[4])
scene.play(
d_new.set_color, WHITE,
d_new.move_to, r[3],
d[2].move_to, r[2],
d[1].move_to, r[1],
d[0].move_to, r[0],
d[0].set_color, BLACK,
run_time=run_time,
)
d[0] = d[1]
d[1] = d[2]
d[2] = d_new
def push2(self, n, scene, run_time=1,):
d = self.decimals
r = self.rects
d_new = self.get_decimals(num=n, color=BLACK)
d_new.move_to(self.rects[3])
scene.play(
d_new.set_color, WHITE,
d_new.move_to, r[2],
d[1].move_to, r[1],
d[0].move_to, r[0],
d[0].set_color, BLACK,
run_time=run_time,
)
d[0] = d[1]
d[1] = d_new
class VarLadderTest(Scene):
def construct(self):
ladder = VarLadder()
# ladder.set_decimal(None, 1, 2)
# self.add(ladder)
# self.wait()
#
# ladder.push(3, self)
# ladder.push(4, self)
# ladder.push(5, self)
ladder.set_decimal(None,0,None)
self.add(ladder)
self.wait()
ladder.push2(1, self)
ladder.push2(3, self)
ladder.push2(5, self)
여기에 사용된 음성 파일은,
-끝-
반응형
'Programming > Manim Project' 카테고리의 다른 글
원 위의 점이 돌면서 사인/코사인 곡선 그리기 (0) | 2020.09.15 |
---|---|
원 위의 점이 이동하면서 사인 곡선 그리기 (1) | 2020.09.14 |
[컴포넌트]VerticalBarChart 만들기 (3. 사용법) (0) | 2020.05.17 |
[컴포넌트]VerticalBarChart 만들기 (2. 핵심코드 설명) (0) | 2020.05.16 |
[컴포넌트]VerticalBarChart 만들기 (1. 설계/소스) (0) | 2020.05.16 |