From e8be8b52aba5856de126690934a7245c71fd915c Mon Sep 17 00:00:00 2001 From: papush! Date: Sat, 7 Dec 2019 12:33:50 +0100 Subject: [PATCH] =?UTF-8?q?ajout=20d=E2=80=99Observer,=20le=20composant=20?= =?UTF-8?q?physique=20suit=20l=E2=80=99entit=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit implémentation du patron Observateur dans la classe Observer qui permet à un objet d’être notifié quand une propriété d’un autre objet est modifiée. CollideRect observe maintenant les propriétés x et y de l’entité à laquelle il appartient et met à jour son rect accordément. --- doc/notes.txt | 2 ++ engine/components/collide_rect.py | 10 ++++++++-- engine/components/component.py | 5 +++-- engine/components/sprite.py | 4 ++-- engine/entity.py | 6 ++++-- engine/observer.py | 14 ++++++++++++++ engine/servers/physics.py | 4 ++-- scenes/lvl0.py | 19 +++++++------------ 8 files changed, 42 insertions(+), 22 deletions(-) create mode 100644 engine/observer.py diff --git a/doc/notes.txt b/doc/notes.txt index 8965532..8e6477e 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -96,6 +96,8 @@ En termes de patrons de conception utilisés : n’importe où dans le code plutôt que d’avoir à passer des références de partout, + - observateur, pour synchroniser les propriétés des composants. + Évolutions futures possibles : diff --git a/engine/components/collide_rect.py b/engine/components/collide_rect.py index 83a636b..d4fc82a 100644 --- a/engine/components/collide_rect.py +++ b/engine/components/collide_rect.py @@ -3,9 +3,15 @@ from ..servers.physics import PhysicsServer class CollideRect(Component): - def __init__(self, rect, static=True, solid=True): - super().__init__() + def __init__(self, parent, rect, static=True, solid=True): + super().__init__(parent) self.rect = rect + def x_change_cb(x): + self.rect.x = x + def y_change_cb(y): + self.rect.y = y + parent.subscribe('x', x_change_cb) + parent.subscribe('y', y_change_cb) self.static = static self.solid = solid self.vx = 0 diff --git a/engine/components/component.py b/engine/components/component.py index fb3c5e6..9da54ce 100644 --- a/engine/components/component.py +++ b/engine/components/component.py @@ -2,8 +2,9 @@ from abc import abstractmethod class Component: - def __init__(self): - self.parent = None + def __init__(self, parent): + self.parent = parent + self.parent.add(self) @abstractmethod def register(self): diff --git a/engine/components/sprite.py b/engine/components/sprite.py index c506a66..6f1d72f 100644 --- a/engine/components/sprite.py +++ b/engine/components/sprite.py @@ -3,8 +3,8 @@ from ..servers.graphics import GraphicsServer class Sprite(Component): - def __init__(self, surf, z): - super().__init__() + def __init__(self, parent, surf, z): + super().__init__(parent) self.surf = surf self.width = self.surf.get_width() self.z = z diff --git a/engine/entity.py b/engine/entity.py index 8e0571e..8252e78 100644 --- a/engine/entity.py +++ b/engine/entity.py @@ -1,5 +1,8 @@ -class Entity: +from .observer import Observer + +class Entity(Observer): def __init__(self): + super().__init__() self._components = [] self.x = 0 self.y = 0 @@ -7,7 +10,6 @@ class Entity: def add(self, component): self._components.append(component) - component.parent = self def register(self): for component in self._components: diff --git a/engine/observer.py b/engine/observer.py new file mode 100644 index 0000000..1fa15da --- /dev/null +++ b/engine/observer.py @@ -0,0 +1,14 @@ +class Observer(object): + def __init__(self): + super().__setattr__('_subscribers', {}) + + def subscribe(self, name, cb): + if name not in self._subscribers: + self._subscribers[name] = [] + self._subscribers[name].append(cb) + + def __setattr__(self, name, val): + if name in self._subscribers: + for cb in self._subscribers[name]: + cb(val) + super().__setattr__(name, val) diff --git a/engine/servers/physics.py b/engine/servers/physics.py index b9953df..ef78b34 100644 --- a/engine/servers/physics.py +++ b/engine/servers/physics.py @@ -33,7 +33,7 @@ class PhysicsServer(Server): d.rect.x = d.parent.x break d.parent.x += 1 if d.vx > 0 else -1 - d.rect.x = d.parent.x + # d.rect.x = d.parent.x for y in range(abs(d.vy)): stop = False for s in self._static: @@ -45,6 +45,6 @@ class PhysicsServer(Server): d.rect.y = d.parent.y break d.parent.y += 1 if d.vy > 0 else -1 - d.rect.y = d.parent.y + # d.rect.y = d.parent.y d.vx = 0 d.vy = 0 diff --git a/scenes/lvl0.py b/scenes/lvl0.py index fd3637d..0565726 100644 --- a/scenes/lvl0.py +++ b/scenes/lvl0.py @@ -27,20 +27,19 @@ class Level(Entity): wall.fill((0, 0, 255)) for x, y in product(range(w), range(h)): if desc.get_at((x, y)) == (0, 0, 255): - self.add(CollideRect(Rect(x * S, y * S, S, S))) + CollideRect(self, Rect(x * S, y * S, S, S)) self.surf.blit(wall, (x * S, y * S)) - self.add(Sprite(self.surf, 0)) + Sprite(self, self.surf, 0) class MovingEntity(Entity): def __init__(self, surf): super().__init__() - sprite = Sprite(surf, 1) - self.add(sprite) - self.phys = CollideRect(Rect(self.x, self.y, - sprite.width, sprite.width), - static=False) - self.add(self.phys) + sprite = Sprite(self, surf, 1) + self.phys = CollideRect( + self, + Rect(self.x, self.y, sprite.width, sprite.width), + static=False) class Ghost(MovingEntity): @@ -65,16 +64,12 @@ class Lvl0(Scene): p = pacman.phys inputs = key.get_pressed() if inputs[K_UP]: - # entity.y -= 2 p.vy = -v if inputs[K_DOWN]: - # entity.y += 2 p.vy = v if inputs[K_LEFT]: - # entity.x -= 2 p.vx = -v if inputs[K_RIGHT]: - # entity.x += 2 p.vx = v pacman.script = pacman_script pacman.x = pacman.phys.rect.x = S*15