phantomcastle use overlap
This commit is contained in:
parent
f1b7b2e860
commit
b8ecdd8f23
@ -262,11 +262,29 @@ class DrawableGameObject(ABC):
|
||||
self.rect = pygame.Rect(coords, coords)
|
||||
self.assets = assets or (parent.assets if parent else None)
|
||||
self._surface = None
|
||||
self._mask = None
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.__class__.__name__}({self.coords})"
|
||||
|
||||
@property
|
||||
def surface(self) -> pygame.Surface | None:
|
||||
return self._surface or (self.parent.surface if self.parent else None)
|
||||
|
||||
@property
|
||||
def mask(self) -> pygame.Mask | None:
|
||||
if not self._mask:
|
||||
self._mask = pygame.mask.from_surface(self.surface.convert_alpha())
|
||||
return self._mask
|
||||
|
||||
def overlap(self, rect: pygame.Rect, mask: pygame.Mask) -> bool:
|
||||
if not self.rect.colliderect(rect):
|
||||
return False
|
||||
|
||||
offset = Coords(*self.rect.topleft) - Coords(*rect.topleft)
|
||||
overlap = mask.overlap(self.mask, offset)
|
||||
return overlap is not None
|
||||
|
||||
@property
|
||||
def scene(self):
|
||||
return self.parent.scene if self.parent else self
|
||||
@ -321,10 +339,9 @@ class Hero(DrawableGameObject, EventHandler):
|
||||
|
||||
def _check_collision(self, coords):
|
||||
"""Проверка пересечения со стенами"""
|
||||
new_rect = self.surface.get_bounding_rect()
|
||||
new_rect = self.rect.copy()
|
||||
new_rect.topleft = coords
|
||||
new_rect.scale_by_ip(0.99, 0.99)
|
||||
return self.scene.walls.check_collision(new_rect)
|
||||
return self.scene.walls.check_collision(new_rect, self.mask)
|
||||
|
||||
@property
|
||||
def speed(self):
|
||||
@ -378,7 +395,7 @@ class Hero(DrawableGameObject, EventHandler):
|
||||
def move(self, direction: Direction, step: int = 1):
|
||||
self.update_direction(direction)
|
||||
self.coords += direction.as_coords() * step * self.speed // 3
|
||||
self.scene.coins.collect(self.rect)
|
||||
self.scene.coins.collect(self)
|
||||
|
||||
def handle_event(self, event: pygame.event.Event):
|
||||
if not self.active:
|
||||
@ -449,9 +466,9 @@ class Walls(DrawableGameObject):
|
||||
for block in self.blocks:
|
||||
block.draw()
|
||||
|
||||
def check_collision(self, rect: pygame.Rect) -> bool:
|
||||
def check_collision(self, rect: pygame.Rect, mask: pygame.Mask) -> bool:
|
||||
for block in self.blocks:
|
||||
if block.rect.colliderect(rect):
|
||||
if block.overlap(rect, mask):
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -552,8 +569,8 @@ class Coins(DrawableGameObject):
|
||||
coin.coords = last_pos
|
||||
self.collected_coins.append(coin)
|
||||
|
||||
def collect(self, rect: pygame.Rect):
|
||||
mined = [*filter(lambda coin: coin.bounding_rect.colliderect(rect), self.coins)]
|
||||
def collect(self, actor: DrawableGameObject):
|
||||
mined = [*filter(lambda coin: coin.overlap(actor.rect, actor.mask), self.coins)]
|
||||
for coin in mined:
|
||||
self.coins.remove(coin)
|
||||
self.add_to_collected(coin)
|
||||
|
@ -177,11 +177,29 @@ class DrawableGameObject(ABC):
|
||||
self.rect = pygame.Rect(coords, coords)
|
||||
self.assets = assets or (parent.assets if parent else None)
|
||||
self._surface = None
|
||||
self._mask = None
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.__class__.__name__}({self.coords})"
|
||||
|
||||
@property
|
||||
def surface(self) -> pygame.Surface | None:
|
||||
return self._surface or (self.parent.surface if self.parent else None)
|
||||
|
||||
@property
|
||||
def mask(self) -> pygame.Mask | None:
|
||||
if not self._mask:
|
||||
self._mask = pygame.mask.from_surface(self.surface.convert_alpha())
|
||||
return self._mask
|
||||
|
||||
def overlap(self, rect: pygame.Rect, mask: pygame.Mask) -> bool:
|
||||
if not self.rect.colliderect(rect):
|
||||
return False
|
||||
|
||||
offset = Coords(*self.rect.topleft) - Coords(*rect.topleft)
|
||||
overlap = mask.overlap(self.mask, offset)
|
||||
return overlap is not None
|
||||
|
||||
@property
|
||||
def scene(self):
|
||||
return self.parent.scene if self.parent else self
|
||||
@ -236,10 +254,9 @@ class Hero(DrawableGameObject, KeysHandler):
|
||||
|
||||
def _check_collision(self, coords):
|
||||
"""Проверка пересечения со стенами"""
|
||||
new_rect = self.surface.get_bounding_rect()
|
||||
new_rect = self.rect.copy()
|
||||
new_rect.topleft = coords
|
||||
new_rect.scale_by_ip(0.99, 0.99)
|
||||
return self.scene.walls.check_collision(new_rect)
|
||||
return self.scene.walls.check_collision(new_rect, self.mask)
|
||||
|
||||
@property
|
||||
def speed(self):
|
||||
@ -293,7 +310,7 @@ class Hero(DrawableGameObject, KeysHandler):
|
||||
def move(self, direction: Direction, step: int = 1):
|
||||
self.update_direction(direction)
|
||||
self.coords += direction.as_coords() * step * self.speed // 3
|
||||
self.scene.coins.collect(self.rect)
|
||||
self.scene.coins.collect(self)
|
||||
|
||||
def handle_keys(self, keys_pressed):
|
||||
if not self.active:
|
||||
@ -362,9 +379,9 @@ class Walls(DrawableGameObject):
|
||||
for block in self.blocks:
|
||||
block.draw()
|
||||
|
||||
def check_collision(self, rect: pygame.Rect) -> bool:
|
||||
def check_collision(self, rect: pygame.Rect, mask: pygame.Mask) -> bool:
|
||||
for block in self.blocks:
|
||||
if block.rect.colliderect(rect):
|
||||
if block.overlap(rect, mask):
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -463,8 +480,8 @@ class Coins(DrawableGameObject):
|
||||
coin.coords = last_pos
|
||||
self.collected_coins.append(coin)
|
||||
|
||||
def collect(self, rect: pygame.Rect):
|
||||
mined = [*filter(lambda coin: coin.bounding_rect.colliderect(rect), self.coins)]
|
||||
def collect(self, actor: DrawableGameObject):
|
||||
mined = [*filter(lambda coin: coin.overlap(actor.rect, actor.mask), self.coins)]
|
||||
for coin in mined:
|
||||
self.coins.remove(coin)
|
||||
self.add_to_collected(coin)
|
||||
|
Loading…
Reference in New Issue
Block a user