diff --git a/src/doodles/doodles.py b/src/doodles/doodles.py index 71ce213..d0b78ed 100644 --- a/src/doodles/doodles.py +++ b/src/doodles/doodles.py @@ -28,6 +28,7 @@ class Doodle(ABC): def __init__(self, parent=None): self._parent = parent self._color = parent._color if parent else Color.BLACK + self._z_index = 0 # Is storing this vector in a tuple the right thing to do? # It might make more sense to store _x and _y, or use # a library's optimized 2D vector implementation. @@ -38,6 +39,7 @@ class Doodle(ABC): if parent: # register with parent for updates self._parent.add(self) + world.add(self) @abstractmethod def draw(self, screen) -> None: @@ -63,7 +65,9 @@ class Doodle(ABC): cases, it will be possible for child classes to override this to opt for a deepcopy or other logic. """ - return copy.copy(self) + new = copy.copy(self) + world.add(new) + return new def color(self, r: int, g: int, b: int) -> "Doodle": """ @@ -84,6 +88,13 @@ class Doodle(ABC): self._pos_vec = (x, y) return self + def z_index(self, z: float) -> "Doodle": + """ + Setter for z_index + """ + self._z_index = z + return self + def move(self, dx: float, dy: float) -> "Doodle": """ This shifts the vector by a set amount. @@ -137,6 +148,10 @@ class Doodle(ABC): return self._parent.y + self._pos_vec[1] return self._pos_vec[1] + # @property + # def z_index(self) -> float: + # return self._z_index + @property def pos_vec(self) -> (float, float): """ @@ -259,12 +274,10 @@ class Group(Doodle): Groups, despite being an abstract concept, are drawable. To draw a group is to draw everything in it. - The draw logic is to just call the draw method of all children. - This works because we know that all doodles are guaranteed - to have such a method. + This is done by default, since all drawables will be + registered with the scene upon creation. """ - for d in self._doodles: - d.draw(screen) + pass def copy(self) -> "Group": """ @@ -272,7 +285,9 @@ class Group(Doodle): We are storing a list, so deep copies are necessary. """ - return copy.deepcopy(self) + new = copy.deepcopy(self) + world.add(new) + return new def color(self, r: int, g: int, b: int) -> "Doodle": """ @@ -311,3 +326,37 @@ class Group(Doodle): # if we understand the implications of tightly # binding the implementations of these two classes. return self + + +class Circle(Doodle): + def __init__(self, parent=None): + """ + This is a less interesting class than Line, but very similar. + """ + super().__init__(parent) + # circle is a position & radius + self._radius = 0 + + def __repr__(self): + return f"Circle(pos={self.pos_vec}, radius={self._radius}, {self._color})" + + def draw(self, screen): + pygame.draw.circle(screen, self._color, self.pos_vec, self._radius) + + def radius(self, r: float) -> "Doodle": + """ + A setter for the circle's radius. + """ + self._radius = r + return self + + def grow(self, by: float): + """ + Modify radius by an amount. (Negative to shrink.) + """ + return self.radius(self._radius + by) + + def random(self) -> "Doodle": + super().random() + # constrain to 10-100 + return self.radius(random.random*90 + 10) diff --git a/src/doodles/examples/circles.py b/src/doodles/examples/circles.py new file mode 100644 index 0000000..5cdc805 --- /dev/null +++ b/src/doodles/examples/circles.py @@ -0,0 +1,10 @@ +from doodles.doodles import Group, Circle, Color +from doodles.world import world + +c = Circle() + +g = Group().pos(400, 300) +for r in range(20, 50, 5): + Circle(g).radius(r).color(*Color.random()).z_index(-r) +for r in range(60, 150, 10): + Circle(g).radius(r).color(*Color.random()).z_index(-r) diff --git a/src/doodles/layouts.py b/src/doodles/layouts.py index 6ecc814..d8fc1da 100644 --- a/src/doodles/layouts.py +++ b/src/doodles/layouts.py @@ -1,4 +1,3 @@ -from .world import world def make_grid(iterable, cols, rows, width, height, *, x_offset=0, y_offset=0): @@ -10,7 +9,6 @@ def make_grid(iterable, cols, rows, width, height, *, x_offset=0, y_offset=0): for c in range(cols): for r in range(rows): doodle.pos(width * c + x_offset, height * r + y_offset) - world.add(doodle) doodle = next(iterable) except StopIteration: pass diff --git a/src/doodles/main.py b/src/doodles/main.py index 506369d..fca9440 100644 --- a/src/doodles/main.py +++ b/src/doodles/main.py @@ -29,6 +29,7 @@ def main(modname: str): pygame.quit() sys.exit() world.render() + # print(f"world contains {world._drawables}") pygame.display.flip() diff --git a/src/doodles/world.py b/src/doodles/world.py index 36ea360..170b97e 100644 --- a/src/doodles/world.py +++ b/src/doodles/world.py @@ -62,7 +62,7 @@ class World: Draw world to screen """ self.screen.fill(self.background_color) - for d in self._drawables: + for d in sorted(self._drawables, key=lambda d: d._z_index): d.draw(self.screen)