ajout d’Observer, le composant physique suit l’entité

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.
This commit is contained in:
papush! 2019-12-07 12:33:50 +01:00
parent 237abb4aa3
commit e8be8b52ab
8 changed files with 42 additions and 22 deletions

View File

@ -96,6 +96,8 @@ En termes de patrons de conception utilisés :
nimporte où dans le code plutôt que davoir à passer des nimporte où dans le code plutôt que davoir à passer des
références de partout, références de partout,
- observateur, pour synchroniser les propriétés des composants.
Évolutions futures possibles : Évolutions futures possibles :

View File

@ -3,9 +3,15 @@ from ..servers.physics import PhysicsServer
class CollideRect(Component): class CollideRect(Component):
def __init__(self, rect, static=True, solid=True): def __init__(self, parent, rect, static=True, solid=True):
super().__init__() super().__init__(parent)
self.rect = rect 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.static = static
self.solid = solid self.solid = solid
self.vx = 0 self.vx = 0

View File

@ -2,8 +2,9 @@ from abc import abstractmethod
class Component: class Component:
def __init__(self): def __init__(self, parent):
self.parent = None self.parent = parent
self.parent.add(self)
@abstractmethod @abstractmethod
def register(self): def register(self):

View File

@ -3,8 +3,8 @@ from ..servers.graphics import GraphicsServer
class Sprite(Component): class Sprite(Component):
def __init__(self, surf, z): def __init__(self, parent, surf, z):
super().__init__() super().__init__(parent)
self.surf = surf self.surf = surf
self.width = self.surf.get_width() self.width = self.surf.get_width()
self.z = z self.z = z

View File

@ -1,5 +1,8 @@
class Entity: from .observer import Observer
class Entity(Observer):
def __init__(self): def __init__(self):
super().__init__()
self._components = [] self._components = []
self.x = 0 self.x = 0
self.y = 0 self.y = 0
@ -7,7 +10,6 @@ class Entity:
def add(self, component): def add(self, component):
self._components.append(component) self._components.append(component)
component.parent = self
def register(self): def register(self):
for component in self._components: for component in self._components:

14
engine/observer.py Normal file
View File

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

View File

@ -33,7 +33,7 @@ class PhysicsServer(Server):
d.rect.x = d.parent.x d.rect.x = d.parent.x
break break
d.parent.x += 1 if d.vx > 0 else -1 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)): for y in range(abs(d.vy)):
stop = False stop = False
for s in self._static: for s in self._static:
@ -45,6 +45,6 @@ class PhysicsServer(Server):
d.rect.y = d.parent.y d.rect.y = d.parent.y
break break
d.parent.y += 1 if d.vy > 0 else -1 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.vx = 0
d.vy = 0 d.vy = 0

View File

@ -27,20 +27,19 @@ class Level(Entity):
wall.fill((0, 0, 255)) wall.fill((0, 0, 255))
for x, y in product(range(w), range(h)): for x, y in product(range(w), range(h)):
if desc.get_at((x, y)) == (0, 0, 255): 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.surf.blit(wall, (x * S, y * S))
self.add(Sprite(self.surf, 0)) Sprite(self, self.surf, 0)
class MovingEntity(Entity): class MovingEntity(Entity):
def __init__(self, surf): def __init__(self, surf):
super().__init__() super().__init__()
sprite = Sprite(surf, 1) sprite = Sprite(self, surf, 1)
self.add(sprite) self.phys = CollideRect(
self.phys = CollideRect(Rect(self.x, self.y, self,
sprite.width, sprite.width), Rect(self.x, self.y, sprite.width, sprite.width),
static=False) static=False)
self.add(self.phys)
class Ghost(MovingEntity): class Ghost(MovingEntity):
@ -65,16 +64,12 @@ class Lvl0(Scene):
p = pacman.phys p = pacman.phys
inputs = key.get_pressed() inputs = key.get_pressed()
if inputs[K_UP]: if inputs[K_UP]:
# entity.y -= 2
p.vy = -v p.vy = -v
if inputs[K_DOWN]: if inputs[K_DOWN]:
# entity.y += 2
p.vy = v p.vy = v
if inputs[K_LEFT]: if inputs[K_LEFT]:
# entity.x -= 2
p.vx = -v p.vx = -v
if inputs[K_RIGHT]: if inputs[K_RIGHT]:
# entity.x += 2
p.vx = v p.vx = v
pacman.script = pacman_script pacman.script = pacman_script
pacman.x = pacman.phys.rect.x = S*15 pacman.x = pacman.phys.rect.x = S*15