fix copying
This commit is contained in:
parent
802ba51875
commit
aa82295182
@ -36,7 +36,11 @@ class Doodle(ABC):
|
||||
# All references to _pos_vec are internal to the class,
|
||||
# so it will be trivial to swap this out later.
|
||||
self._pos_vec = (0, 0)
|
||||
if parent:
|
||||
self._register()
|
||||
|
||||
def _register(self):
|
||||
""" register with parent and world """
|
||||
if self._parent:
|
||||
# register with parent for updates
|
||||
self._parent.add(self)
|
||||
world.add(self)
|
||||
@ -63,20 +67,20 @@ class Doodle(ABC):
|
||||
|
||||
Additionally, while a shallow copy is enough for most
|
||||
cases, it will be possible for child classes to override
|
||||
this to opt for a deepcopy or other logic.
|
||||
this.
|
||||
"""
|
||||
new = copy.copy(self)
|
||||
world.add(new)
|
||||
new._register()
|
||||
return new
|
||||
|
||||
def color(self, r: int, g: int, b: int) -> "Doodle":
|
||||
def color(self, color: tuple[int, int, int]) -> "Doodle":
|
||||
"""
|
||||
Color works as a kind of setter function.
|
||||
|
||||
The only unique part is that it returns self, accomodating the
|
||||
chained object pattern.
|
||||
"""
|
||||
self._color = (r, g, b)
|
||||
self._color = color
|
||||
return self
|
||||
|
||||
def pos(self, x: float, y: float) -> "Doodle":
|
||||
@ -111,11 +115,11 @@ class Doodle(ABC):
|
||||
"""
|
||||
x = random.random() * world.WIDTH
|
||||
y = random.random() * world.HEIGHT
|
||||
r, g, b = Color.random()
|
||||
color = Color.random()
|
||||
# again here, we opt to use the setters so that
|
||||
# future extensions to their behavior will be
|
||||
# used by all downstream functions
|
||||
return self.pos(x, y).color(r, g, b)
|
||||
return self.pos(x, y).color(color)
|
||||
|
||||
@property
|
||||
def x(self) -> float:
|
||||
@ -265,10 +269,13 @@ class Group(Doodle):
|
||||
in some languages would be much trickier to pull off.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._doodles = []
|
||||
|
||||
def __repr__(self):
|
||||
return f"Group(pos={self.pos_vec}, doodles={len(self._doodles)})"
|
||||
|
||||
def draw(self, screen):
|
||||
"""
|
||||
Groups, despite being an abstract concept, are drawable.
|
||||
@ -285,11 +292,16 @@ class Group(Doodle):
|
||||
|
||||
We are storing a list, so deep copies are necessary.
|
||||
"""
|
||||
new = copy.deepcopy(self)
|
||||
world.add(new)
|
||||
new = copy.copy(self)
|
||||
new._register()
|
||||
new._doodles = []
|
||||
for child in self._doodles:
|
||||
child = copy.copy(child)
|
||||
child._parent = new
|
||||
child._register()
|
||||
return new
|
||||
|
||||
def color(self, r: int, g: int, b: int) -> "Doodle":
|
||||
def color(self, color: tuple[int, int, int]) -> "Doodle":
|
||||
"""
|
||||
Another override.
|
||||
|
||||
@ -299,9 +311,9 @@ class Group(Doodle):
|
||||
|
||||
We don't cascade pos() calls, why not?
|
||||
"""
|
||||
super().color(r, g, b)
|
||||
super().color(color)
|
||||
for d in self._doodles:
|
||||
d.color(r, g, b)
|
||||
d.color(color)
|
||||
return self
|
||||
|
||||
def add(self, doodle: "Doodle") -> "Group":
|
||||
@ -338,7 +350,7 @@ class Circle(Doodle):
|
||||
self._radius = 0
|
||||
|
||||
def __repr__(self):
|
||||
return f"Circle(pos={self.pos_vec}, radius={self._radius}, {self._color})"
|
||||
return f"Circle(pos={self.pos_vec}, radius={self._radius}, {self._color}, parent={self._parent}))"
|
||||
|
||||
def draw(self, screen):
|
||||
pygame.draw.circle(screen, self._color, self.pos_vec, self._radius)
|
||||
@ -359,4 +371,4 @@ class Circle(Doodle):
|
||||
def random(self) -> "Doodle":
|
||||
super().random()
|
||||
# constrain to 10-100
|
||||
return self.radius(random.random*90 + 10)
|
||||
return self.radius(random.random()*90 + 10)
|
||||
|
16
src/doodles/examples/copies.py
Normal file
16
src/doodles/examples/copies.py
Normal file
@ -0,0 +1,16 @@
|
||||
from doodles.doodles import Group, Line, Circle, Color
|
||||
|
||||
def original():
|
||||
g = Group()
|
||||
c = Circle(g).radius(80).color(Color.RED).pos(0, 0)
|
||||
for _ in range(15):
|
||||
c = c.copy().move(45, 45)
|
||||
return g
|
||||
|
||||
r = original()
|
||||
r.copy().move(200, 0).color(Color.GREEN)
|
||||
r.copy().move(400, 0).color(Color.BLUE)
|
||||
|
||||
# from doodles.world import world
|
||||
# for d in world._drawables:
|
||||
# print(" >", d)
|
@ -1,10 +1,13 @@
|
||||
from doodles.doodles import Group, Line
|
||||
from doodles.layouts import make_grid, copies
|
||||
from doodles.layouts import make_grid
|
||||
|
||||
# Create a group of lines all with same origin, different angles.
|
||||
g = Group()
|
||||
for d in range(0, 180, 10):
|
||||
Line(g).vec(d, 200 - d)
|
||||
def same_spiral():
|
||||
while True:
|
||||
# Create a group of lines all with same origin, different angles.
|
||||
g = Group()
|
||||
for d in range(0, 180, 10):
|
||||
Line(g).vec(d, 200 - d)
|
||||
yield g
|
||||
|
||||
# Make copies, moving each one and modifying the color
|
||||
make_grid(copies(g), 3, 4, 250, 140, x_offset=70, y_offset=20)
|
||||
make_grid(same_spiral(), 3, 4, 250, 140, x_offset=70, y_offset=20)
|
||||
|
@ -5,21 +5,9 @@ def make_grid(iterable, cols, rows, width, height, *, x_offset=0, y_offset=0):
|
||||
Arranges the objects in iterable in a grid with the given parameters.
|
||||
"""
|
||||
try:
|
||||
doodle = next(iterable)
|
||||
for c in range(cols):
|
||||
for r in range(rows):
|
||||
doodle.pos(width * c + x_offset, height * r + y_offset)
|
||||
doodle = next(iterable)
|
||||
doodle.pos(width * c + x_offset, height * r + y_offset)
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
|
||||
def copies(doodle):
|
||||
"""
|
||||
Lazily makes an infinite number of copies of a given doodle.
|
||||
|
||||
Can be combined with things like `make_grid` that require
|
||||
an iterable of doodles to repeat.
|
||||
"""
|
||||
while True:
|
||||
yield doodle.copy()
|
||||
|
@ -29,7 +29,7 @@ def main(modname: str):
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
world.render()
|
||||
# print(f"world contains {world._drawables}")
|
||||
#print(f"world contains {len(world._drawables)}")
|
||||
pygame.display.flip()
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user