From 78428cb8fc57a6f2b674cf161d3d351c1b83e2f1 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 23 Mar 2024 23:24:24 +0300 Subject: [PATCH] add anim3 --- mod_graph/anim3.py | 146 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 mod_graph/anim3.py diff --git a/mod_graph/anim3.py b/mod_graph/anim3.py new file mode 100644 index 0000000..2295a2b --- /dev/null +++ b/mod_graph/anim3.py @@ -0,0 +1,146 @@ +""" + https://stepik.org/lesson/468998/step/8?unit=459819 + + Два квадрата, один управляется стрелками, другой клавишами WASD + Для выхода нужно нажать Q или Esc + + Библиотека graph: https://kpolyakov.spb.ru/download/pygraph.zip +""" + +import graph +from graph import * + +from typing import NamedTuple +import types + +consts = types.SimpleNamespace() +consts.VK_Q = 81 +consts.VK_W = 87 +consts.VK_A = 65 +consts.VK_S = 83 +consts.VK_D = 68 + + +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 __sub__(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 + + +data = {"delta_a": Point(0, 0), "delta_b": Point(0, 0), "callbacks": []} + + +def square_a_on_scene(start_pos=None): + start_pos = start_pos or Point(0, 0) + + scene_sz = Point(300, 300) + box_sz = Point(40, 40) + box_offset = Point(80, 80) + + brushColor("Blue") + rectangle(*start_pos, *(start_pos + scene_sz)) + brushColor("Yellow") + + box_pos = start_pos + box_offset + obj = rectangle(*box_pos, *(box_pos + box_sz)) + + def update(): + delta = data["delta_a"] + coord = Point(xCoord(obj), yCoord(obj)) - start_pos + if ( + coord.x + delta.x < 0 + or coord.x + box_sz.x + delta.x > scene_sz.x + or coord.y + delta.y < 0 + or coord.y + box_sz.y + delta.y > scene_sz.y + ): + return + moveObjectBy(obj, delta.x, delta.y) + + data.setdefault("callbacks", []).append(update) + + +def square_b(start_pos=None): + start_pos = start_pos or Point(0, 0) + + scene_sz = Point(300, 300) + box_sz = Point(40, 40) + box_offset = Point(200, 200) + + brushColor("Yellow") + + box_pos = start_pos + box_offset + obj = rectangle(*box_pos, *(box_pos + box_sz)) + + def update(): + delta = data["delta_b"] + coord = Point(xCoord(obj), yCoord(obj)) - start_pos + if ( + coord.x + delta.x < 0 + or coord.x + box_sz.x + delta.x > scene_sz.x + or coord.y + delta.y < 0 + or coord.y + box_sz.y + delta.y > scene_sz.y + ): + return + moveObjectBy(obj, delta.x, delta.y) + + data.setdefault("callbacks", []).append(update) + + +def keyPressed(event): + match event.keycode: + case graph.VK_LEFT: + data["delta_a"] = Point(-5, 0) + case graph.VK_RIGHT: + data["delta_a"] = Point(5, 0) + case graph.VK_UP: + data["delta_a"] = Point(0, -5) + case graph.VK_DOWN: + data["delta_a"] = Point(0, 5) + case consts.VK_A: + data["delta_b"] = Point(-5, 0) + case consts.VK_D: + data["delta_b"] = Point(5, 0) + case consts.VK_W: + data["delta_b"] = Point(0, -5) + case consts.VK_S: + data["delta_b"] = Point(0, 5) + case consts.VK_Q | graph.VK_ESCAPE: + killTimer(data["update_timer"]) + close() + + +def update(): + for callback in data["callbacks"]: + callback() + data["delta_a"] = Point(0, 0) + data["delta_b"] = Point(0, 0) + + +def main(): + canvasSize(300, 300) + square_a_on_scene() + square_b() + + data["update_timer"] = onTimer(update, 40) + onKey(keyPressed) + run() + + +main()