import logging import pygame from config import INITIAL_SNAKE_SIZE, MAP_RESOLUTION, TILE_SIZE, SNAKE_COLOR, BACKGROUND_COLOR, APPLE_COLOR from utils import make_slot, Direction, random_slot logger = logging.getLogger(__name__) class Snake: def __init__(self, ): self.slots = [make_slot(21, 16)] * INITIAL_SNAKE_SIZE self._direction = None # type: Direction self.dead = False def add_slot(self, left: int, top: int): self.slots.append(make_slot(left, top)) def move(self, screen: pygame.Surface, apple: 'Apple'): if self.direction is None: return [] new_head = self.slots[0].move(*self.direction.value) if new_head.collidelist(self.slots[1:]) > -1: self.dead = True return [] if new_head.right > MAP_RESOLUTION[0]: new_head = pygame.Rect(0, new_head.top, TILE_SIZE, TILE_SIZE) elif new_head.left < 0: new_head = pygame.Rect(MAP_RESOLUTION[0] - TILE_SIZE, new_head.top, TILE_SIZE, TILE_SIZE) if new_head.bottom > MAP_RESOLUTION[1]: new_head = pygame.Rect(new_head.left, 0, TILE_SIZE, TILE_SIZE) elif new_head.top < 0: new_head = pygame.Rect(new_head.left, MAP_RESOLUTION[1] - TILE_SIZE, TILE_SIZE, TILE_SIZE) self.slots.insert(0, new_head) screen.fill(SNAKE_COLOR, new_head) if not new_head.colliderect(apple.rect): old_tail = self.slots.pop() screen.fill(BACKGROUND_COLOR, old_tail) return [old_tail, new_head] return [new_head] @property def head(self) -> pygame.Rect: return self.slots[0] @head.setter def head(self, value: pygame.Rect): self.slots.pop(0) self.slots.insert(0, value) @property def direction(self) -> Direction: return self._direction @direction.setter def direction(self, value: Direction): if not value.is_opposed_to(self.direction): self._direction = value else: logger.debug('Move prohibited : tried to change to an opposed direction') class Apple: def __init__(self): self.rect = random_slot() self.score = 10 def display(self, screen: pygame.Surface) -> pygame.Rect: screen.fill(APPLE_COLOR, self.rect) return self.rect def renew(self): self.rect = random_slot() logger.debug(f'Apple generated at {self.rect.left / TILE_SIZE} {self.rect.top / TILE_SIZE}')