import pygame from game_object import GameObject from snake_segment import SnakeSegment from snake_state_machine import SnakeStateMachine from wall import Wall from prey import Prey class Snake(GameObject): def __init__(self, start_position: tuple|list, length: int, radius: float|int, color: tuple) -> None: self.__segments = [SnakeSegment(center=(start_position[0]+2*radius*idx, start_position[1]), radius=radius, color=color) for idx in range(length)] self.__state_machine = SnakeStateMachine() self.__is_dead = False self.__shall_grow = False def __collides_with_wall(self, obj: GameObject): return isinstance(obj, Wall) and self.get_bounding_boxes()[0].collidelist(obj.get_bounding_boxes()) > -1 def __collides_with_self(self, obj: GameObject): return isinstance(obj, Snake) and self.get_bounding_boxes()[0].collidelist(obj.get_bounding_boxes()[1:]) > -1 def __collides_with_prey(self, obj: GameObject): return isinstance(obj, Prey) and self.get_bounding_boxes()[0].colliderect(obj.get_bounding_boxes()[0]) def __update_on_collision(self, game_objs: list[GameObject]) -> None: for obj in game_objs: if self.__collides_with_wall(obj) or self.__collides_with_self(obj): self.__is_dead = True elif self.__collides_with_prey(obj): self.__shall_grow = True def draw(self, surface: pygame.Surface) -> None: for segment in self.__segments: segment.draw(surface) def update(self, user_input: int, game_objs: list[GameObject]) -> None: self.__shall_grow = False if not self.__is_dead: self.__update_on_collision(game_objs) if not self.__is_dead: self.__state_machine.update(user_input) new_head = self.__state_machine.get_state().get_next_head(self.__segments[0]) self.__segments.insert(0, new_head) if not self.__shall_grow: self.__segments.pop() def get_bounding_boxes(self) -> list[pygame.rect.Rect]: return [seg.get_bounding_boxes()[0] for seg in self.__segments] def is_dead(self): return self.__is_dead