class Game: def __init__(self): pygame.init() self.CLOCK = Clock() self.ROWS_COLS = 15 self.GRID_SIZE = 50 self.SCREEN_SIZE = self.GRID_SIZE * self.ROWS_COLS self.DISPLAY = display.set_mode((self.SCREEN_SIZE, self.SCREEN_SIZE)) self.BACKGROUND_COLOR = (0, 0, 0) self.GRID_COLOR = (100, 100, 100) self.SNAKE_COLOR = (0, 255, 0) self.apple_generator = AppleGenerator(self.ROWS_COLS, self.GRID_SIZE) self.apple = self.apple_generator.generate_apple(self.snake) mid = (self.ROWS_COLS // 2) * self.GRID_SIZE self.start_x_y = (mid, mid) self.snake = Snake(self.start_x_y, self.GRID_SIZE, self.SCREEN_SIZE, self.SNAKE_COLOR, self.spawn_apple) self.exit_clicked = None self.playing = None def start(self): self.playing = True self.exit_clicked = False self.reset() while self.playing: self.CLOCK.tick(10) delay(50) if not self.exit_clicked: for event in pygame.event.get(): if event.type == pygame.QUIT: # noinspection PyAttributeOutsideInit self.exit_clicked = True self.playing = False # Doesn't close immediately. Will still run a few cycles. pygame.quit() if not self.exit_clicked: self.snake.move() self.playing = self.playing and not self.snake.has_collided if self.playing: self.draw_game() elif not self.exit_clicked: print('Score: ', len(self.snake.body) + 1) self.message_box('You lost!', 'Play again?') self.reset() # noinspection PyAttributeOutsideInit self.playing = True def spawn_apple(self): self.apple = self.apple_generator.generate_apple(self.snake) self.snake.set_apple(self.apple) def reset(self): self.snake = Snake(self.start_x_y, self.GRID_SIZE, self.SCREEN_SIZE, self.SNAKE_COLOR, self.spawn_apple) self.spawn_apple() def draw_game(self): self.DISPLAY.fill(self.BACKGROUND_COLOR) self.draw_grid() self.snake.draw(self.DISPLAY) self.apple.draw(self.DISPLAY) display.update() def draw_grid(self): x, y = 0, 0 for i in range(self.ROWS_COLS): x += self.GRID_SIZE y += self.GRID_SIZE draw.line(self.DISPLAY, self.GRID_COLOR, (x, 0), (x, self.SCREEN_SIZE)) draw.line(self.DISPLAY, self.GRID_COLOR, (0, y), (self.SCREEN_SIZE, y)) @staticmethod def message_box(subject, content): root = tk.Tk() root.attributes("-topmost", True) root.withdraw() messagebox.showinfo(subject, content) # noinspection PyBroadException try: root.destroy() except: pass
class PlaySnake: def __init__(self, maze_size=_MAZE_SIZE, start_location=Coordinate(int(_MAZE_SIZE / 2), int(_MAZE_SIZE / 2)), tick_interval=1): self._maze_size = maze_size self._snake = Snake(head=start_location) self._food = None self._running = False self._timer = None self._tick_interval = tick_interval self._tick_count = 0 @property def score(self): return self._snake.length @property def running(self): return self._running @property def direction(self): return self._snake.heading @direction.setter def direction(self, direction): self._snake.heading = direction @property def game_map(self): game_map = [[0 for x in range(self._maze_size)] for y in range(self._maze_size)] for segment in self._snake.map: game_map[segment.x][segment.y] = 1 game_map[self._snake.head.x][self._snake.head.y] = 2 game_map[self._food.location.x][self._food.location.y] = 3 return game_map def start(self): if self._running: return self._timer = Timer(self._tick_interval, self._tick) self._food = Food(maze_size=self._maze_size, snake_map=self._snake.map) self._timer.start() self._running = True def stop(self): if self._timer: self._timer.cancel() self._running = False self._timer = None def _tick(self): if not self._running: return self._timer = Timer(self._tick_interval, self._tick) self._timer.start() if self._snake.new_head(self._snake.heading) == self._food.location: self._snake.move(maze_size=self._maze_size, grow=True) self._food = Food(maze_size=self._maze_size, snake_map=self._snake.map) else: self._snake.move(maze_size=self._maze_size, grow=False) if not self._snake.alive: self.stop()