add z indexing

This commit is contained in:
James Turk 2024-04-21 22:34:36 -05:00
parent fca6d11504
commit 802ba51875
5 changed files with 68 additions and 10 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -29,6 +29,7 @@ def main(modname: str):
pygame.quit()
sys.exit()
world.render()
# print(f"world contains {world._drawables}")
pygame.display.flip()

View File

@ -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)