From 47c826a5f8201b0fca0a3d53ff2a74247b75db7b Mon Sep 17 00:00:00 2001 From: Dmitry Date: Thu, 14 Mar 2024 16:54:52 +0300 Subject: [PATCH] add anim1.py --- mod_graph/anim1.py | 131 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 mod_graph/anim1.py diff --git a/mod_graph/anim1.py b/mod_graph/anim1.py new file mode 100644 index 0000000..4099bb8 --- /dev/null +++ b/mod_graph/anim1.py @@ -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()