import os import pygame from display import Scaling, INTERNAL_WIDTH, INTERNAL_HEIGHT from stats import Stats DEBUG = os.getenv("DEBUG") class FieldSprite(pygame.sprite.Sprite): def __init__(self, area: tuple): super().__init__() self.color = (0,255,0,255) self.dead = False self.area = area self.rect = Scaling.area_to_rect(self.area) self.image = pygame.Surface(self.rect.size, pygame.SRCALPHA) self.image.fill(self.color) def update(self, dt = 0): if dt and self.dead: self.color = ( self.color[0], self.color[1], self.color[2], self.color[3] - dt/4) if self.color[3] <= 0: self.kill() else: self.image.fill(self.color) class SliceSprite(FieldSprite): def __init__(self, area: tuple ): super().__init__(area) self.color = (255,255,0,255) self.image.fill(self.color) self.dead = True class Field(pygame.sprite.LayeredUpdates): initial_area = (320_000, 220_000) def __init__(self): super().__init__() self.add(FieldSprite( (0, 0, *__class__.initial_area) )) self.area_full = __class__.initial_area[0] * __class__.initial_area[1] def calculate_current_area(self): return sum( s.area[2]*s.area[3] for s in self.active_sprites() ) def update_stats(self): """ calculates remaining area and remaining percentage """ Stats.percent = 100 * self.calculate_current_area() / self.area_full if DEBUG: print(f"FIELD: {Stats.percent}") def slice( self, pos: tuple, direction: bool, thickness: int) -> pygame.Rect: """ Slice one area into two areas """ # Slicing hits the area? for overlap in self.get_sprites_at(Scaling.scale_to_display(pos)): if not overlap.dead: break else: return None # Save the area information and remove the sprite ax, ay, aw, ah = overlap.area overlap.remove(self) # create new areas if there is any space if direction: x1 = ax x2 = pos[0] - thickness x3 = pos[0] + thickness x4 = ax + aw if x2 > x1: self.add(FieldSprite( (x1, ay, x2-x1, ah) )) if x4 > x3: self.add(FieldSprite( (x3, ay, x4-x3, ah) )) self.add(SliceSprite( (x2, ay, x3-x2, ah) )) return Scaling.area_to_rect((x2, ay, x3-x2, ah)) y1 = ay y2 = pos[1] - thickness y3 = pos[1] + thickness y4 = ay + ah if y2 > y1: self.add(FieldSprite( (ax, y1, aw, y2-y1) )) if y4 > y3: self.add(FieldSprite( (ax, y3, aw, y4-y3) )) self.add(SliceSprite( (ax, y2, aw, y3-y2) )) return Scaling.area_to_rect((ax, y2, aw, y3-y2)) def active_sprites(self): """ Returns all sprites that are not dead """ return [s for s in self.sprites() if not s.dead] def kill_if_not_colliding(self, sprites): """ If there is empty fields that are not yet dead kill them """ for field in self.active_sprites(): for enemy in sprites: if enemy.rect.colliderect(field.rect): break else: field.dead = True