add anim1.py
This commit is contained in:
parent
77b0ef184d
commit
47c826a5f8
131
mod_graph/anim1.py
Normal file
131
mod_graph/anim1.py
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
"""
|
||||||
|
Анимация квадратов
|
||||||
|
https://stepik.org/lesson/468998/step/4?unit=459819
|
||||||
|
|
||||||
|
3: "Квадрат двигается справа налево"
|
||||||
|
4: "Два квадрата двигаются в противоположных направлениях"
|
||||||
|
|
||||||
|
Библиотека graph: https://kpolyakov.spb.ru/download/pygraph.zip
|
||||||
|
"""
|
||||||
|
|
||||||
|
from graph import *
|
||||||
|
|
||||||
|
from typing import NamedTuple
|
||||||
|
|
||||||
|
|
||||||
|
class Point(NamedTuple):
|
||||||
|
"""
|
||||||
|
Вспомогательный класс для упрощения работы с координатами (сложение)
|
||||||
|
"""
|
||||||
|
|
||||||
|
x: int | float
|
||||||
|
y: int | float
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
if isinstance(other, self.__class__):
|
||||||
|
return self.__class__(self.x + other.x, self.y + other.y)
|
||||||
|
if isinstance(other, (int, float)):
|
||||||
|
return self.__class__(self.x + other, self.y + other)
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
|
||||||
|
def make_title(n, name, start, font=("Arial", 15), n_color="indigo"):
|
||||||
|
pos = Point(10, 20) + start
|
||||||
|
n_width = Point(35, 0)
|
||||||
|
l1 = label(f"«{n}»", *pos, font=font, foreground=n_color)
|
||||||
|
l2 = label(f": {name}", *(pos + n_width), font=font)
|
||||||
|
return l1, l2
|
||||||
|
|
||||||
|
|
||||||
|
def square_left_to_right(start_pos=None):
|
||||||
|
start_pos = start_pos or Point(0, 0)
|
||||||
|
|
||||||
|
make_title(3, "Квадрат двигается справа налево", start_pos)
|
||||||
|
title_height = Point(0, 60)
|
||||||
|
|
||||||
|
start_pos = start_pos + title_height
|
||||||
|
scene_sz = Point(300, 300)
|
||||||
|
box_sz = Point(40, 40)
|
||||||
|
box_offset = Point(220, 5)
|
||||||
|
|
||||||
|
brushColor("Blue")
|
||||||
|
rectangle(*start_pos, *(start_pos + scene_sz)) # Размер фона
|
||||||
|
brushColor("Yellow")
|
||||||
|
obj = rectangle(
|
||||||
|
*(start_pos + box_offset), *(start_pos + box_offset + box_sz)
|
||||||
|
) # Создаем объект, который у нас в виде прямоугольника
|
||||||
|
|
||||||
|
data = {"done": False} # состояние объекта для контроля таймера из вне функции
|
||||||
|
|
||||||
|
def update(): # Создаем процедуру, которая отвечает за анимацию
|
||||||
|
# Она будет перемещать объект obj по оси x на -5 по оси y на 0 пикселей
|
||||||
|
moveObjectBy(obj, -5, 0)
|
||||||
|
if xCoord(obj) <= 1: # Если x координата меньше 1
|
||||||
|
killTimer(timer)
|
||||||
|
data["done"] = True
|
||||||
|
|
||||||
|
timer = onTimer(update, 40) # Каждые 50 мс будет запускаться процедура update
|
||||||
|
return (data,)
|
||||||
|
|
||||||
|
|
||||||
|
def two_squares(start_pos=None):
|
||||||
|
start_pos = start_pos or Point(0, 0)
|
||||||
|
|
||||||
|
make_title(4, "Два квадрата двигаются в\nпротивоположных направлениях", start_pos)
|
||||||
|
title_height = Point(0, 90)
|
||||||
|
|
||||||
|
start_pos = start_pos + title_height
|
||||||
|
scene_sz = Point(300, 300)
|
||||||
|
box_sz = Point(40, 40)
|
||||||
|
box1_offset = Point(220, 5)
|
||||||
|
box2_offset = Point(0, 250)
|
||||||
|
|
||||||
|
brushColor("Blue")
|
||||||
|
rectangle(*start_pos, *(start_pos + scene_sz))
|
||||||
|
brushColor("Yellow")
|
||||||
|
box1 = rectangle(*(start_pos + box1_offset), *(start_pos + box1_offset + box_sz))
|
||||||
|
box2 = rectangle(*(start_pos + box2_offset), *(start_pos + box2_offset + box_sz))
|
||||||
|
timer1 = None
|
||||||
|
timer2 = None
|
||||||
|
|
||||||
|
data1 = {"done": False}
|
||||||
|
data2 = {"done": False}
|
||||||
|
|
||||||
|
def update_box1():
|
||||||
|
moveObjectBy(box1, -5, 0)
|
||||||
|
if xCoord(box1) <= 1:
|
||||||
|
killTimer(timer1)
|
||||||
|
data1["done"] = True
|
||||||
|
|
||||||
|
def update_box2():
|
||||||
|
moveObjectBy(box2, 5, 0)
|
||||||
|
if xCoord(box2) >= scene_sz.x - box_sz.x:
|
||||||
|
killTimer(timer2)
|
||||||
|
data2["done"] = True
|
||||||
|
|
||||||
|
timer1 = onTimer(update_box1, 40)
|
||||||
|
timer2 = onTimer(update_box2, 40)
|
||||||
|
|
||||||
|
return data1, data2
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
canvasSize(400, 800)
|
||||||
|
state = [
|
||||||
|
*square_left_to_right(),
|
||||||
|
*two_squares(Point(0, 350))
|
||||||
|
]
|
||||||
|
|
||||||
|
watch_timer = None
|
||||||
|
|
||||||
|
# выход по завершении всех анимаций
|
||||||
|
def watch_done():
|
||||||
|
if all(x["done"] for x in state):
|
||||||
|
killTimer(watch_timer)
|
||||||
|
close()
|
||||||
|
|
||||||
|
watch_timer = onTimer(watch_done, 6000)
|
||||||
|
run()
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user