class DotWorld(): """Мир состоит только из одного существа, которое ходит и ищет пищу в пределах видимости.""" # Инициализация основных параметров def __init__(self, width, height, caption): pygame.init() # Размеры окна и заголовок self.width = width self.height = height self.size = (self.width, self.height) self.caption = caption pygame.display.set_caption(self.caption) # Экран с заданным размеров self.screen = pygame.display.set_mode(self.size) # Полноэкранный режим # self.screen = pygame.display.set_mode(self.size, pygame.FULLSCREEN) # Инициализация настроек self.config = Config() # Инициализация набора цветов self.colors = Colors() # Инициализация счетчика шагов self.step = 0 # Инициализация списков объектов (Точки и трав) self.dotsList = [] # Инициализация первой точки и добавление в список Точек self.firstDot = Dot() self.dotsList.append(self.firstDot) # Список координат трав self.grass = Grass() self.grassesCoords = self.grass.addGrass(self.width, self.height, self.grass.startQuantity) self.font = pygame.font.SysFont(None, 16) self.screen_rect = self.screen.get_rect() pygame.mouse.set_visible(False) # Функция запуска мира: def run_world(self): # Основной цикл while True: self._check_event() # Запуск счетчика + скорость self.step += self.firstDot.vel # Заполнение фона self.screen.fill(self.colors.DARKSLATEGREY) # Прорисовка трав for grassCoord in self.grassesCoords: pygame.draw.circle(self.screen, self.colors.LAVENDER, (grassCoord[0], grassCoord[1]), self.grass.grassRad) # Прорисовка Точки pygame.draw.circle(self.screen, self.config.STEELBLUE, (self.firstDot.dotX, self.firstDot.dotY), self.firstDot.dotRad) # Прорисовка окружности - границ сканера pygame.draw.circle(self.screen, self.config.PapayaWhip, (self.firstDot.dotX, self.firstDot.dotY), self.firstDot.scanRad, 1) # Определение новой целевой координаты Точки (куда она должна идти) # Сканирование вокруг Точки, определение целевой координаты target = self.firstDot.scanner(self.grassesCoords, self.width, self.height) # Изменение координат Точки в сторону целевой (движение) self.firstDot.moveTo(target) # Декремент_энергии self.firstDot.energyDecr(1) # Инкремент энергии, если трава съедена self.firstDot.eatGrass(target, self.grassesCoords, self.grass.energyIncr) pygame.draw.line(self.screen, self.config.PapayaWhip, (self.firstDot.dotX, self.firstDot.dotY), target, 3) # Восполнение запасов травы # Если количество травы меньше минимально установленной if len(self.grassesCoords) < self.grass.minQuantity: # Добавить координаты еще одной травы в список координат трав self.grass.addGrass(self.width, self.height) # Если энергия Точки на нуле, выйти из симуляции if self.firstDot.energy <= 0: sys.exit() # Вывод Легенды self.showLegend(" Energy", self.firstDot.energy, 5) self.showLegend(" En. of 1 dot", self.grass.energyIncr, 20) self.showLegend(" Target", target, 35) self.showLegend(" Current Coord.", (self.firstDot.dotX, self.firstDot.dotY), 50) pygame.display.flip() self.config.clock.tick(self.config.FPS) pygame.quit() # Инициализация необходимых методов: def _check_event(self): """Проверка событий""" for event in pygame.event.get(): # Если закрыто окно Pygame: if event.type == pygame.QUIT: # Выйти из программы sys.exit() if event.type == pygame.KEYDOWN: # Если нажата кнопка q: if event.key == pygame.K_q: # Выйти из программы sys.exit() def showLegend(self, caption, num, vIndent): """Показ легенды""" legend_str = f" {caption}: {num} " legend_image = self.font.render(legend_str, True, self.colors.GRAY) legend_rect = legend_image.get_rect() legend_rect.left = self.screen_rect.left + 5 legend_rect.top = vIndent # Рендер текстов, показателей, вывод на экран легенды self.screen.blit(legend_image, legend_rect)
class DotWorld(): # Инициализация основных параметров def __init__(self, width, height, caption): pygame.init() # Размеры окна и заголовок self.width = width self.height = height self.size = (self.width, self.height) self.caption = caption pygame.display.set_caption(self.caption) # Экран с заданным размеров self.screen = pygame.display.set_mode(self.size) # Полноэкранный режим # self.screen = pygame.display.set_mode(self.size, pygame.FULLSCREEN) # Инициализация настроек self.config = Config() # Инициализация набора цветов self.colors = Colors() # Инициализация счетчика шагов self.step = 0 # Инициализация списков объектов (Точки и трав) self.dotsList = [] # Инициализация первой точки и добавление в список Точек self.firstDot = Dot() self.dotsList.append(self.firstDot) # Список координат трав self.grass = Grass() self.grassesCoords = self.grass.addGrass(self.width, self.height, self.grass.startQuantity) # Поверхность для создания графика статистики self.statsurf = pygame.Surface((240, 240)) self.font_legend = pygame.font.SysFont("Roboto", 24) self.screen_rect = self.statsurf.get_rect() # Поверхность для создания симуляции self.simsurf = pygame.Surface((1040, 720)) self.font_tooltip = pygame.font.SysFont("Roboto", 12) pygame.mouse.set_visible(False) self.filename = "stat.csv" self.frame = 0 self.data = [["Time", "Population", "Resources", "Slows", "Middles", "Fasts"]] # Группы по скорости self.slowDots = [] self.middleDots = [] self.fastDots = [] self.time = [] self.population = [] self.resources = [] self.slows = [] self.middles = [] self.fasts = [] # Функция запуска мира: def run_world(self): # Основной цикл while True: self._check_event() # Запуск счетчика + скорость for dot in self.dotsList: self.step += dot.vel if dot.energy >= 1000: newDot = Dot(500) dot.energyDecr(500) self.dotsList.append(newDot) if newDot.dotColor == self.colors.BLUE: self.slowDots.append(newDot) elif newDot.dotColor == self.colors.FUCHSIA: self.middleDots.append(newDot) elif newDot.dotColor == self.colors.DARKKHAKI: self.fastDots.append(newDot) # Прорисовка поверхности симуляции self.screen.blit(self.simsurf, (240, 0)) # Заполнение фона self.simsurf.fill(self.colors.DARKSLATEGREY) # Прорисовка трав for grassCoord in self.grassesCoords: pygame.draw.circle(self.simsurf, self.colors.LAVENDER, (grassCoord[0], grassCoord[1]), self.grass.grassRad) # Прорисовка Точки for dot in self.dotsList: pygame.draw.circle(self.simsurf, dot.dotColor, (dot.dotX, dot.dotY), dot.dotRad) self.showTooltip(str(dot.energy), dot.dotX - 2 * dot.dotRad, dot.dotY + 2 * dot.dotRad) # Определение новой целевой координаты Точки (куда она должна идти) # Сканирование вокруг Точки, определение целевой координаты for dot in self.dotsList: target = dot.scanner(self.grassesCoords, self.width, self.height) # Изменение координат Точки в сторону целевой (движение) dot.moveTo(target) # Декремент_энергии dot.energyDecr(1) # Инкремент энергии, если трава съедена dot.eatGrass(target, self.grassesCoords, self.grass.energyIncr) # pygame.draw.line(self.screen, self.config.PapayaWhip, (dot.dotX, dot.dotY), target, 3) # Восполнение запасов травы # Если количество травы меньше минимально установленной grassesNum = len(self.grassesCoords) if grassesNum < self.grass.minQuantity: # Добавить координаты еще одной травы в список координат трав # (self.grass.minQuantity - grassesNum) self.grass.addGrass(self.width, self.height) # Если энергия Точки на нуле, удалить ее и вместо нее добавить 3 травинки for dot in self.dotsList: if dot.energy <= 0: # self.dotsList.remove(dot) # self.grass.addGrass(self.width, self.height, 3) self.dotsList.remove(dot) if dot.dotColor == self.colors.BLUE: try: self.slowDots.remove(dot) self.grass.addGrass(self.width, self.height, 30) except ValueError: continue elif dot.dotColor == self.colors.FUCHSIA: try: self.middleDots.remove(dot) # self.dotsList.remove(dot) self.grass.addGrass(self.width, self.height, 25) except ValueError: continue elif dot.dotColor == self.colors.DARKKHAKI: try: self.fastDots.remove(dot) # self.dotsList.remove(dot) self.grass.addGrass(self.width, self.height, 10) except ValueError: continue # Статистика slows = len(self.slowDots) middles = len(self.middleDots) fasts = len(self.fastDots) # Прорисовка статистики self.statsurf.fill(self.colors.WHITE) self.statsurf.set_alpha(200) # Сохранение данных в файле dotsNum = len(self.dotsList) if self.frame % self.config.FPS == 0: data = [f'sec_{int(self.frame // self.config.FPS)}', dotsNum, grassesNum, slows, middles, fasts] # data = [f'sec_{int(self.frame // 10)}', dotsNum, grassesNum, slows, middles, fasts] self.data.append(data) # Вывод Легенды self.showLegend("Resources", grassesNum, 10) self.showLegend("Population", dotsNum, 30) self.showLegend("Slow Dots", slows, 50) self.showLegend("Middle Dots", middles, 70) self.showLegend("Fast Dots", fasts, 90) self.screen.blit(self.statsurf, (0, 0)) # Если численность на нуле, выйти из симуляции if dotsNum == 0: self.writeStat(self.filename, self.data) self.save_plot(self.data) sys.exit() pygame.display.flip() self.config.clock.tick(self.config.FPS) self.frame += 1 pygame.quit() # Инициализация необходимых методов: def _check_event(self): """Проверка событий""" for event in pygame.event.get(): # Если закрыто окно Pygame: if event.type == pygame.QUIT: # Выйти из программы sys.exit() if event.type == pygame.KEYDOWN: # Если нажата кнопка q: if event.key == pygame.K_q: self.filename = f"stat_data/stat_{int(time.time())}.csv" self.writeStat(self.filename, self.data) self.save_plot(self.data) # Выйти из программы sys.exit() def showLegend(self, caption, num, vIndent): """Показ легенды""" legend_str = f" {caption}: {num} " legend_image = self.font_legend.render(legend_str, True, self.colors.BLACK) legend_rect = legend_image.get_rect() legend_rect.left = self.screen_rect.left + 5 legend_rect.top = vIndent # Рендер текстов, показателей, вывод на экран легенды self.statsurf.blit(legend_image, legend_rect) def showTooltip(self, text, xAxis, yAxis): """Показ легенды""" tooltip_image = self.font_tooltip.render(text, True, self.colors.BLACK) tooltip_rect = tooltip_image.get_rect() tooltip_rect.left = xAxis tooltip_rect.top = yAxis # Рендер текстов, показателей, вывод на экран легенды self.simsurf.blit(tooltip_image, tooltip_rect) def writeStat(self, filename, data): with open(filename, 'w') as f: writer = csv.writer(f) for row in data: writer.writerow(row) def save_plot(self, data): for row in data: self.time.append(row[0]) self.population.append(row[1]) self.resources.append(row[2]) self.slows.append(row[3]) self.middles.append(row[4]) self.fasts.append(row[5]) # pyplot styles # ['Solarize_Light2', '_classic_test_patch', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn', 'seaborn-bright', 'seaborn-colorblind', 'seaborn-dark', 'seaborn-dark-palette', 'seaborn-darkgrid', 'seaborn-deep', 'seaborn-muted', 'seaborn-notebook', 'seaborn-paper', 'seaborn-pastel', 'seaborn-poster', 'seaborn-talk', 'seaborn-ticks', 'seaborn-white', 'seaborn-whitegrid', 'tableau-colorblind10'] plt.style.use("ggplot") fig, ax = plt.subplots() ax.plot(self.population[1:]) ax.plot(self.resources[1:]) ax.plot(self.slows[1:]) ax.plot(self.middles[1:]) ax.plot(self.fasts[1:]) ax.legend(("Population", "Resources", "Slows", "Middles", "Fasts")) # ax.axis([0, int(self.x_values[-1][4:]), 0, 1000]) plt.savefig(f"stat_fig/stat_fig_{int(time.time())}.png", bbox_inches = "tight") # plt.show() return True