2024-04-06 10:30:07 +00:00
|
|
|
|
from random import sample
|
|
|
|
|
import pygame
|
|
|
|
|
from coords import Coords
|
|
|
|
|
from common import DrawableGameObject, FONT_NAME
|
|
|
|
|
from maze import get_maze_sz
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Coin(DrawableGameObject):
|
|
|
|
|
"""объект монетки"""
|
|
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
|
self,
|
|
|
|
|
coords: Coords,
|
|
|
|
|
parent: DrawableGameObject,
|
|
|
|
|
assets: dict | None = None,
|
|
|
|
|
):
|
|
|
|
|
super().__init__(coords, parent, assets)
|
2024-04-07 17:37:02 +00:00
|
|
|
|
self._surface = pygame.image.load(self.assets["coin.png"]).convert_alpha()
|
2024-04-06 10:30:07 +00:00
|
|
|
|
self.rect = self.surface.get_rect()
|
|
|
|
|
self.rect.topleft = coords
|
|
|
|
|
# уменьшаем размер монетки
|
|
|
|
|
sf = Coords(0.7, 0.7)
|
|
|
|
|
self._surface, self.rect = self.scene.scale_box(self.surface, self.rect, sf)
|
|
|
|
|
|
|
|
|
|
def draw(self):
|
|
|
|
|
self.parent.surface.blit(self.surface, self.rect)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def bounding_rect(self) -> pygame.Rect:
|
|
|
|
|
new_rect = self.surface.get_bounding_rect()
|
|
|
|
|
new_rect.center = self.rect.center
|
|
|
|
|
return new_rect
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Coins(DrawableGameObject):
|
|
|
|
|
"""объект коллекции монеток"""
|
|
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
|
self,
|
|
|
|
|
parent: DrawableGameObject,
|
|
|
|
|
maze: list[list[int]],
|
|
|
|
|
box_sz: Coords,
|
|
|
|
|
count: int,
|
|
|
|
|
assets: dict | None = None,
|
|
|
|
|
):
|
|
|
|
|
super().__init__(Coords.zero(), parent, assets)
|
|
|
|
|
self.box_sz = box_sz
|
|
|
|
|
self._capacity = count
|
|
|
|
|
|
|
|
|
|
free_points = []
|
|
|
|
|
excluded = Coords(0, 1), get_maze_sz(maze) - Coords(1, 2)
|
|
|
|
|
for i, row in enumerate(maze):
|
|
|
|
|
for j, item in enumerate(row):
|
|
|
|
|
p = Coords(j, i)
|
|
|
|
|
if item < 1 and p not in excluded:
|
|
|
|
|
free_points.append(p)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
coin_points = sample(free_points, min(count, len(free_points)))
|
|
|
|
|
self.coins = [
|
|
|
|
|
Coin(point.transform(box_sz), self, self.assets) for point in coin_points
|
|
|
|
|
]
|
|
|
|
|
self.collected_coins = []
|
|
|
|
|
|
|
|
|
|
# Надпись, если все монетки собраны
|
|
|
|
|
font = pygame.font.SysFont(FONT_NAME, 30)
|
|
|
|
|
text = "Все монетки собраны!"
|
|
|
|
|
self.done_txt = font.render(text, 1, "#050366e3")
|
|
|
|
|
self.done_txt_rect = self.done_txt.get_rect()
|
|
|
|
|
self.done_txt_rect.topleft = Coords(10, 10)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def capacity(self) -> int:
|
|
|
|
|
return self._capacity
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def coins_left(self) -> int:
|
|
|
|
|
return len(self.coins)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def coins_collected(self) -> int:
|
|
|
|
|
return self.capacity - self.coins_left
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def all_collected(self) -> int:
|
|
|
|
|
return self.coins_left == 0
|
|
|
|
|
|
|
|
|
|
def draw(self):
|
|
|
|
|
for coin in self.collected_coins:
|
|
|
|
|
coin.draw()
|
|
|
|
|
for coin in self.coins:
|
|
|
|
|
coin.draw()
|
|
|
|
|
if self.all_collected:
|
|
|
|
|
self.parent.surface.blit(self.done_txt, self.done_txt_rect)
|
|
|
|
|
|
|
|
|
|
def add_to_collected(self, coin: Coin):
|
|
|
|
|
last_pos = Coords(10, 10)
|
|
|
|
|
if self.collected_coins:
|
|
|
|
|
last_pos = Coords(*self.collected_coins[-1].rect.topright)
|
|
|
|
|
last_pos -= Coords(coin.rect.width // 2, 0)
|
|
|
|
|
coin.coords = last_pos
|
|
|
|
|
self.collected_coins.append(coin)
|
|
|
|
|
|
|
|
|
|
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)
|