diff --git a/src/doodles/doodles.py b/src/doodles/doodles.py index b1ea391..c1720e7 100644 --- a/src/doodles/doodles.py +++ b/src/doodles/doodles.py @@ -57,6 +57,13 @@ class Doodle(ABC): """ pass + def update(self) -> None: + """ + An optional method, if implemented will be called every frame, + allowing for animation of properties. + """ + pass + def copy(self) -> "Doodle": """ It will be useful to have the ability to obtain a copy diff --git a/src/doodles/examples/balls.py b/src/doodles/examples/balls.py new file mode 100644 index 0000000..1dccb0e --- /dev/null +++ b/src/doodles/examples/balls.py @@ -0,0 +1,44 @@ +from doodles.doodles import Group, Circle, Color +import random +from doodles.world import world + +""" +Demonstrates two different update strategies. + +This uses the Template Method pattern, by implementing update +the behavior of an object can be overriden. + +Sometimes a default method would be supplied, but just as often +it is left as a pass-through like we see here. + +Objects without an update method are static. +""" + +class Ball(Circle): + def __init__(self): + super().__init__() + self.speed = 0.005 + random.random() * 0.005 + + def update(self): + self.move(0, self.speed) + if self.y > world.HEIGHT + 20: + self.move(0, -world.HEIGHT-20) + +balls = [Ball().pos(40*i, 0).radius(10).color(Color.BLUE) for i in range(21)] + + +class GravityBall(Circle): + def __init__(self): + super().__init__() + self.accel = 0.0000001 # accel per frame + self.speed = random.random() * 0.002 + + def update(self): + self.speed += self.accel + self.move(0, self.speed) + if self.y > world.HEIGHT - 10: + self.speed *= -0.98 # dampening + self.pos(self.x, world.HEIGHT - 10.01) + + +grav = [GravityBall().pos(20+40*i, 0).radius(10).color(Color.PURPLE) for i in range(21)] diff --git a/src/doodles/main.py b/src/doodles/main.py index 2ada071..f4bc92f 100644 --- a/src/doodles/main.py +++ b/src/doodles/main.py @@ -1,4 +1,5 @@ import sys +import time import copy import random import math @@ -7,6 +8,8 @@ import importlib import typer from .world import world +FPS = 60 +MS_PER_FRAME = 1000 / 60 def main(modname: str): pygame.init() @@ -23,13 +26,18 @@ def main(modname: str): except ImportError: raise ImportError(f"Tried to import {modname} and doodles.examples.{modname}") + elapsed = last_update = 0 + while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() + elapsed = pygame.time.get_ticks() - last_update + while elapsed > MS_PER_FRAME: + elapsed -= MS_PER_FRAME + world.tick() world.render() - #print(f"world contains {len(world._drawables)}") pygame.display.flip() diff --git a/src/doodles/world.py b/src/doodles/world.py index 170b97e..1cf1d9c 100644 --- a/src/doodles/world.py +++ b/src/doodles/world.py @@ -57,6 +57,10 @@ class World: def add(self, drawable): self._drawables.append(drawable) + def tick(self): + for d in self._drawables: + d.update() + def render(self): """ Draw world to screen