moved animation code to more general interface, and updated clock example
This commit is contained in:
parent
fdd7ee24d3
commit
ec7bbad372
@ -12,11 +12,13 @@ This is a reasonable example of when two classes might reasonable share a file.
|
||||
"""
|
||||
import random
|
||||
import copy
|
||||
import time
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Callable, Self
|
||||
from typing import Callable, Self, Any
|
||||
from .color import Color
|
||||
from .world import world
|
||||
|
||||
UpdateCallable = Callable[[float], Any]
|
||||
|
||||
class Doodle(ABC):
|
||||
"""
|
||||
@ -38,7 +40,7 @@ class Doodle(ABC):
|
||||
|
||||
# annotations for instance attributes
|
||||
_parent: Self | None
|
||||
_updates: list[Callable]
|
||||
_updates: list[tuple[str, UpdateCallable]]
|
||||
_color: tuple[int, int, int]
|
||||
_alpha: int
|
||||
_z_index: float
|
||||
@ -110,17 +112,11 @@ class Doodle(ABC):
|
||||
new._register()
|
||||
return new
|
||||
|
||||
# Dynamic Update Logic ############
|
||||
# animate #######################
|
||||
|
||||
# These methods relate to a WIP feature
|
||||
# designed to demonstrate a functional hybrid
|
||||
# approach to having objects update themselves.
|
||||
#
|
||||
# This feature isn't complete, or documented yet.
|
||||
# TODO
|
||||
|
||||
def register_update(self, method, *args):
|
||||
self._updates.append((method, args))
|
||||
def animate(self, prop_name: str, update_func: UpdateCallable) -> Self:
|
||||
self._updates.append((prop_name, update_func))
|
||||
return self
|
||||
|
||||
def update(self) -> None:
|
||||
"""
|
||||
@ -130,9 +126,16 @@ class Doodle(ABC):
|
||||
Can be overriden (see examples.balls)
|
||||
to provide per-object update behavior.
|
||||
"""
|
||||
for method, args in self._updates:
|
||||
evaled_args = [arg() for arg in args]
|
||||
method(*evaled_args)
|
||||
cur_time = time.time()
|
||||
|
||||
for prop, anim_func in self._updates:
|
||||
# attributes on Doodle are set via setter functions
|
||||
# prop is the name of a setter function, which we
|
||||
# retrieve here, and then populate with the result
|
||||
# of anim_func(time)
|
||||
setter = getattr(self, prop)
|
||||
new_val = anim_func(cur_time)
|
||||
setter(new_val)
|
||||
|
||||
# Setters #######################
|
||||
|
||||
|
@ -1,9 +1,22 @@
|
||||
import time
|
||||
from doodles import Circle, Color, Line, Group
|
||||
|
||||
|
||||
def color_func(t):
|
||||
print("updating color")
|
||||
cycle = [Color.RED, Color.ORANGE, Color.GREEN, Color.BLUE]
|
||||
return cycle[int(t) % 4]
|
||||
|
||||
|
||||
def create():
|
||||
g = Group().pos(400, 300)
|
||||
Circle(g).radius(300).color(Color.BLACK).z(1)
|
||||
Circle(g).radius(290).color(Color.BROWN).z(10)
|
||||
Circle(g).radius(20).color(Color.BLACK).z(50)
|
||||
Line(g).vec(lambda: time.time() % 60 / 60 * 360, 200).z(100)
|
||||
# Line(g).vec(
|
||||
# lambda: time.time() % 60 / 60 * 360,
|
||||
# 200
|
||||
# ).z(100)
|
||||
|
||||
l = Line(g).vec(0, 200).z(100).animate("degrees", lambda t: t % 60 / 60 * 360)
|
||||
l.animate("color", color_func)
|
||||
|
@ -63,7 +63,7 @@ class Line(Doodle):
|
||||
self._offset_vec = (x, y)
|
||||
return self
|
||||
|
||||
def vec(self, degrees: float | Callable, magnitude: float):
|
||||
def vec(self, degrees: float, magnitude: float):
|
||||
"""
|
||||
Alternate setter, to create offset vector from angle & length.
|
||||
|
||||
@ -72,14 +72,16 @@ class Line(Doodle):
|
||||
directly (`to`), but there is also an alternate option
|
||||
that handles commonly used case.
|
||||
"""
|
||||
if callable(degrees):
|
||||
self.register_update(
|
||||
self.to,
|
||||
lambda: magnitude * math.cos(math.radians(degrees())),
|
||||
lambda: magnitude * math.sin(math.radians(degrees())),
|
||||
)
|
||||
return self
|
||||
return self.to(
|
||||
magnitude * math.cos(math.radians(degrees)),
|
||||
magnitude * math.sin(math.radians(degrees)),
|
||||
)
|
||||
|
||||
def degrees(self, degrees: float):
|
||||
"""
|
||||
Alternate setter, like calling vec(new_degrees, old_magnitude).
|
||||
"""
|
||||
magnitude = math.sqrt(self._offset_vec[0]**2 + self._offset_vec[1]**2)
|
||||
return self.to(
|
||||
magnitude * math.cos(math.radians(degrees)),
|
||||
magnitude * math.sin(math.radians(degrees)),
|
||||
|
Loading…
Reference in New Issue
Block a user