def __init__(self, surface, b_config, e_config): # UI stuff self.stfont = pygame.font.SysFont('Consolas', 15, bold=False) self.drawing = True self.surface = surface # neat-python variables self.b_conf = b_config self.e_conf = e_config self.b_pop = neat.Population(b_config) self.e_pop = neat.Population(e_config) self.b_brains = [ neat.nn.FeedForwardNetwork.create(self.b_pop.population[i], b_config) for i in self.b_pop.population ] self.e_brains = [ neat.nn.FeedForwardNetwork.create(self.e_pop.population[i], e_config) for i in self.e_pop.population ] # game objects self.bow_gen = [ BowCreature(self.surface, GameObjects.Bow(self.surface)) for i in range(0, len(self.b_pop.population)) ] self.enemy_gen = [ SquareCreature(self.surface, GameObjects.Enemy(self.surface, 100)) for i in range(0, len(self.e_pop.population)) ] self.managers = [ GameObjects.WaveManager([self.enemy_gen[i].game_model], self.bow_gen[i].game_model) for i in range(0, len(self.bow_gen)) ] self.timers = [0 for i in range(0, len(self.bow_gen))] # statistics self.generations = 1 self.avg_b_fitness = [] self.avg_e_fitness = [] self.kills = [] self.e_stdev = None self.b_stdev = None self.b_gen_fitness = [] self.e_gen_fitness = []
def multicycle(self): """Runs and draws a game cycle on multiple enemies and bows. Restarts when all timers reach 100/all enemies die.""" view_single = False mp = pygame.mouse.get_pos() mouse_ind = None # check if viewing a single bow-enemy pair if int(mp[1]) in range(12, 12 + 10 * len(self.bow_gen)) and int( mp[0]) in range(860, 990): mouse_ind = (mp[1] - 12) // 10 view_single = True # game loop for i in range(0, len(self.bow_gen)): if self.timers[i] < 100: # updating game objects b = self.bow_gen[i].game_model e = self.enemy_gen[i].game_model self.managers[i].detectCollisions() self.enemy_gen[i].avoided = self.managers[i].missed # setting input for enemy neural networks e_inp = [ b.draw_dx, b.draw_dy, (e.pos[0] - 255), (e.pos[1] - 255) ] for q in e.quadstat: if q: e_inp.append(100) else: e_inp.append(0) self.e_brains[i].activate(e_inp) # setting input for bow neural networks b_inp = [b.draw_dx, b.draw_dy] b_inp.extend([(e.pos[0] - 255), (e.pos[1] - 255), e.vel[0] * 3, e.vel[1] * 3]) self.b_brains[i].activate(b_inp) # drawing game objects and timer bars time_rect = pygame.Rect(860, 12 + 10 * i, (100 - self.timers[i]) * 1.3, 5) # check for high bow fitness, highlight timer bars c = (0, 255, 0) if self.generations > 1 and self.bow_gen[i].set_fitness( self.managers[i].avg_dist ) > self.avg_b_fitness[-1] + self.b_stdev * 1.2: c = (255, 0, 0) pygame.draw.rect(self.surface, c, time_rect) # listening for NN interaction, and updating game models b_out = [self.b_brains[i].values[ind] for ind in range(0, 3)] e_out = [self.e_brains[i].values[ind] for ind in range(0, 4)] self.enemy_gen[i].move_model(e_out) arrow = self.bow_gen[i].move_model(b_out) if arrow is not None: self.managers[i].add_arrow(arrow) # check if viewing a single bow-enemy pair, draw respective stats if (not view_single) or (i == mouse_ind): self.managers[i].draw() if view_single: self.enemy_gen[i].set_fitness() self.enemy_gen[i].draw_fitness(self.stfont, (600, 60)) self.bow_gen[i].set_fitness(self.managers[i].avg_dist) self.bow_gen[i].draw_fitness(self.stfont, (600, 400)) self.draw_nn(i, b_out) self.draw_nn(i, e_out, True) # countdown when stuck/unstuck, ending timer when enemy dies if len(self.managers[i].enemies) < 1: self.timers[i] = 150 self.bow_gen[i].killed = True elif not e.is_moving() or self.managers[ i].failed_shots > 15 or b.arrows > 18 or b.time_between_shots > 300: self.timers[i] += 0.2 else: self.timers[i] = 0 self.drawstats() # checking all generations finished, select, breed, and mutate for i in self.timers: if i < 100: return None self.b_gen_fitness, self.e_gen_fitness = [], [] self.b_pop.run(self.bow_ff, 1) self.e_pop.run(self.enemy_ff, 1) self.shuffle_pops() # update kill count for generation k = 0 for m in self.managers: if len(m.enemies) < 1: k += 1 self.kills.append(k) # reset timers and game models, brains self.bow_gen = [ BowCreature(self.surface, GameObjects.Bow(self.surface)) for i in range(0, len(self.b_pop.population)) ] self.enemy_gen = [ SquareCreature(self.surface, GameObjects.Enemy(self.surface, 100)) for i in range(0, len(self.e_pop.population)) ] self.managers = [ GameObjects.WaveManager([self.enemy_gen[i].game_model], self.bow_gen[i].game_model) for i in range(0, len(self.bow_gen)) ] self.timers = [0 for i in range(0, len(self.bow_gen))] self.b_brains = [ neat.nn.FeedForwardNetwork.create(self.b_pop.population[i], self.b_conf) for i in self.b_pop.population ] self.e_brains = [ neat.nn.FeedForwardNetwork.create(self.e_pop.population[i], self.e_conf) for i in self.e_pop.population ] self.generations += 1
def play_function(difficulty, value): # Define globals global main_menu global clock pygame.mixer.music.pause() # Заглушка value = None # Путь до изображений к игре path_from_background = 'Data\\Image\\Map1.png' path_from_person = pygame.image.load('Data\\Image\\12345.png') path_from_person = pygame.transform.scale2x(path_from_person) path_from_zombie = [ 'Data\\Image\\Zombie.png', 'Data\\Image\\Zombie1.png', 'Data\\Image\\Zombie2.png', 'Data\\Image\\Zombie3.png', 'Data\\Image\\Zombie4.png' ] # Изменение игровых коэфицентов в зависимости от сложности if difficulty[0] == 'EASY': add_hp, add_speed, add_damage = 0.0625, 0.0625, 0.0625 elif difficulty[0] == 'MEDIUM': add_hp, add_speed, add_damage = 0.125, 0.125, 0.125 else: add_hp, add_speed, add_damage = 0.25, 0.25, 0.25 counter_kill = 0 # Счётчик убийст зомби # Иницилизация групп # Сюда входят все обьекты кроме игрока и камеры all_sprite = pygame.sprite.Group() # Сюда входят только видимые обьекты visible_objects = pygame.sprite.Group() # Сюда входят только выстрелы bullet = pygame.sprite.Group() # Сюда входят только враги enemy = pygame.sprite.Group() # Шрифты применяющиеся в игре counter = pygame.font.Font(None, 48) # Для счётчика убийст зомби damage_indicator = pygame.font.Font(None, 16) # Для отображения дамага hp_indicator = pygame.font.Font(None, 32) # Для отоброжения хп персонажа # Добавления Фона background = GameObjects.GameObject((0, 0), path_from_background) background.set_mask() background.disabled_alpha() all_sprite.add(background) visible_objects.add(background) # Добавления игрока person = GameObjects.Person((900, 900), path_from_person, hp=10000, speed_move=(600, 600)) visible_objects.add(person) # Добавление границ wall_up = GameObjects.EmptyObject((0, 0), (WINDOW_SIZE[0] + 1, 1)) wall_botton = GameObjects.EmptyObject((0, WINDOW_SIZE[1] - 1), (WINDOW_SIZE[0] + 1, 1)) wall_left = GameObjects.EmptyObject((0, 0), (1, WINDOW_SIZE[1] + 1)) wall_right = GameObjects.EmptyObject((WINDOW_SIZE[0] - 1, 0), (1, WINDOW_SIZE[1] + 1)) # Создание камеры camera = GameObjects.TargetCamera( all_sprite, person, traffic_restriction=background.get_size(), flags=pygame.FULLSCREEN | pygame.HWSURFACE) screen = camera.get_screen() # Поялучаем экран камеры clock = pygame.time.Clock() # Регулятор FPS pause = False # Переменная отвечающая за паузу counter_shot = 0 # Основной цикл игры command_exit = False while not command_exit and person.get_hp() > 0: screen.fill((0, 0, 0)) # Избавление от шлейфов # Обрабатываем нажаните клавишь for event in pygame.event.get(): if event.type == pygame.QUIT: # По нажатию на кнопки выхода выход command_exit = True elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: # Если нажата, остановка игры pause = not pause if event.key == pygame.K_z: # Если нажата +100 к счётчику counter_kill += 100 elif event.key == pygame.K_g: # Если нажата, обнуляет счётчик counter_kill = 0 if not pause: # Получаем всё нажатые клавиши keys = pygame.key.get_pressed() buttons = pygame.mouse.get_pressed() # Обрабатываем все удержанные клавиши x, y = 0, 0 if keys[pygame.K_d]: x += 1 if keys[pygame.K_a]: x -= 1 if keys[pygame.K_w]: y -= 1 if keys[pygame.K_s]: y += 1 if buttons[0]: if not counter_shot % 2: person.shoot().add(all_sprite, visible_objects, bullet) if counter_shot == 999: counter_shot = 0 counter_shot += 1 # Определяем столкновение персонажа с границами top, botton, left, right = True, True, True, True if pygame.sprite.collide_rect(person, wall_up): top = False if pygame.sprite.collide_rect(person, wall_botton): botton = False if pygame.sprite.collide_rect(person, wall_left): left = False if pygame.sprite.collide_rect(person, wall_right): right = False # Устанавливаем куда персонаж не может ходить person.set_ability_move(top=top, botton=botton, left=left, right=right) # Двигаем камеру с персонажем camera.sled((x, y)) # Обнавление всех обьектов person.update() all_sprite.update() # Добавляем зомби если их < 100 if len(enemy) < 100: pos_spanw_x = randrange(-200, WINDOW_SIZE[0] * 1.5) if 0 < pos_spanw_x < WINDOW_SIZE[0]: pos_spanw_y = -200 if randrange( 2) else WINDOW_SIZE[1] * 1.5 else: pos_spanw_y = randrange(-200, WINDOW_SIZE[1] * 1.5) GameObjects.Enemy( (pos_spanw_x, pos_spanw_y), choice(path_from_zombie), speed_move=randrange(100, round(101 + counter_kill * add_speed)), target=person, damage=randrange(1, round(2 + counter_kill * add_damage)), rotate=(1, lambda: person.get_rect().center), hp=randrange(1, round(2 + counter_kill * add_hp))).add( all_sprite, visible_objects, enemy) # Изменяем скорость персанажу в зависимости от убитых зомби person.edit_speed_move(round(600 + (counter_kill**0.5))) # Обработка столкновение зомби с персонажем for enem in pygame.sprite.spritecollide( person, enemy, False, collided=pygame.sprite.collide_rect): if pygame.sprite.collide_mask(person, enem): person.hit(enem.get_damage()) pos = person.get_rect().center indicator = GameObjects.GameObject( (pos[0] + randrange(25), pos[1] + randrange(25)), path_image=damage_indicator.render( str(-enem.get_damage()), True, (255, 255, 0)), time_life=10) indicator.add(all_sprite, visible_objects) # Обработка пуль с зомби for bull, enem in pygame.sprite.groupcollide( bullet, enemy, False, False).items(): for enemys in enem: if pygame.sprite.collide_mask(bull, enemys): enemys.hit(bull.get_damage()) pos = enemys.get_rect().center indicator = GameObjects.GameObject( (pos[0] + randrange(25), pos[1] + randrange(25)), path_image=damage_indicator.render( str(-enemys.get_damage()), True, (255, 0, 0)), time_life=10) indicator.add(all_sprite, visible_objects) if randrange(4): bull.kill() if not enemys.get_hp(): counter_kill += 1 # Отрисовка всех элементов на экране visible_objects.draw(screen) xol = counter.render(f"Всего убито: {counter_kill}", True, [0, 0, 0]) screen.blit(xol, (0, 0)) xol = hp_indicator.render(f"Hp: {person.get_hp()}", True, [255, 0, 255]) screen.blit(xol, (WINDOW_SIZE[0] - xol.get_rect().size[0], WINDOW_SIZE[1] - xol.get_rect().size[1])) clock.tick(FPS) pygame.display.flip() # Вывод конечного экрана и выход в меню screen.blit( pygame.transform.scale(pygame.image.load("Data\\Image\\End.jpg"), WINDOW_SIZE), (0, 0)) pygame.display.flip() pygame.time.wait(2500) main_menu.reset(True) pygame.mixer.music.play(True) return
def play_function(): # Define globals global clock global cursor_angle global difficulty global screen_size flag = True pause_time = timedelta() delta_quit = timedelta() time_now = datetime.now() con = sqlite3.connect('records.db') cur = con.cursor() pygame.mouse.set_visible(False) # Путь до изображений к игре path_from_background = 'Data\\Image\\Map1.png' path_from_person = pygame.image.load('Data\\Image\\persona.png') path_from_person = pygame.transform.scale2x(path_from_person) path_from_zombie = [ 'Data\\Image\\Zombie.png', 'Data\\Image\\Zombie1.png', 'Data\\Image\\Zombie2.png', 'Data\\Image\\Zombie3.png', 'Data\\Image\\Zombie4.png' ] # Изменение игровых коэфицентов в зависимости от сложности if difficulty == 'EASY': add_hp, add_speed, add_damage = 0.0625, 0.0625, 0.0625 elif difficulty == 'MEDIUM': add_hp, add_speed, add_damage = 0.125, 0.125, 0.125 else: add_hp, add_speed, add_damage = 0.25, 0.25, 0.25 counter_kill = 0 # Счётчик убийст зомби # Иницилизация групп # Сюда входят все обьекты кроме игрока и камеры all_sprite = pygame.sprite.Group() # Сюда входят только видимые обьекты visible_objects = pygame.sprite.Group() # Сюда входят только выстрелы bullet = pygame.sprite.Group() # Сюда входят только враги enemy = pygame.sprite.Group() # Шрифты применяющиеся в игре counter = pygame.font.Font(None, 48) # Для счётчика убийст зомби damage_indicator = pygame.font.Font(None, 16) # Для отображения дамага bullet_reload_indicator = pygame.font.Font( None, 48) # Для отображения перезарядки hp_indicator = pygame.font.Font(None, 48) # Для отоброжения хп персонажа # Добавления Фона background = GameObjects.GameObject((0, 0), path_from_background) background.set_mask() background.disabled_alpha() all_sprite.add(background) visible_objects.add(background) # Добавления игрока person = GameObjects.Person((900, 900), path_from_person, hp=1000, speed_move=(600, 600)) visible_objects.add(person) # Добавление границ wall_up = GameObjects.EmptyObject((0, 0), (screen_size[0] + 1, 1)) wall_botton = GameObjects.EmptyObject((0, screen_size[0] - 1), (screen_size[0] + 1, 1)) wall_left = GameObjects.EmptyObject((0, 0), (1, screen_size[1] + 1)) wall_right = GameObjects.EmptyObject((screen_size[1] - 1, 0), (1, screen_size[1] + 1)) # Создание камеры camera = GameObjects.TargetCamera( all_sprite, person, traffic_restriction=background.get_size(), size=screen_size) # Поялучаем экран камеры screen = camera.get_screen() # Регулятор FPS clock = pygame.time.Clock() # Переменная отвечающая за паузу pause = False # Счетчик выстрелов counter_shot = 0 # Основной цикл игры command_exit = False while not command_exit and person.get_hp() > 0: screen.fill((0, 0, 0)) # Избавление от шлейфов # Обрабатываем нажаните клавишь for event in pygame.event.get(): if event.type == pygame.QUIT: # По нажатию на кнопки выхода выход delta = datetime.now() - time_now - delta_quit result = cur.execute( f"""INSERT INTO records(rec) VALUES('{delta.seconds}') """) con.commit() command_exit = True elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: # Если нажата, остановка игры if not pause: pause_time = datetime.now() else: delta_pause = pause_time - datetime.now() pause = not pause if event.key == pygame.K_z: # Если нажата, выход в меню delta = datetime.now() - time_now - delta_quit result = cur.execute( f"""INSERT INTO records(rec) VALUES('{delta.seconds}') """ ) con.commit() command_exit = True if not pause: # Получаем всё нажатые клавиши keys = pygame.key.get_pressed() buttons = pygame.mouse.get_pressed() try: delta_quit += delta_pause except: pass # Обрабатываем все удержанные клавиши x, y = 0, 0 if keys[pygame.K_d]: x += 1 if keys[pygame.K_a]: x -= 1 if keys[pygame.K_w]: y -= 1 if keys[pygame.K_s]: y += 1 if buttons[0]: try: person.shoot().add(all_sprite, visible_objects, bullet) except: pass if counter_shot == 999: counter_shot = 0 counter_shot += 1 # Определяем столкновение персонажа с границами top, botton, left, right = True, True, True, True if pygame.sprite.collide_rect(person, wall_up): top = False if pygame.sprite.collide_rect(person, wall_botton): botton = False if pygame.sprite.collide_rect(person, wall_left): left = False if pygame.sprite.collide_rect(person, wall_right): right = False # Устанавливаем куда персонаж не может ходить person.set_ability_move(top=top, botton=botton, left=left, right=right) # Двигаем камеру с персонажем camera.sled((x, y)) # Обнавление всех обьектов person.update() all_sprite.update() # Добавляем зомби если их < 30 if len(enemy) < 30: pos_spanw_x = randrange(-200, screen_size[0] * 1.5) if 0 < pos_spanw_x < screen_size[0]: pos_spanw_y = -200 if randrange( 2) else screen_size[1] * 1.5 else: pos_spanw_y = randrange(-200, screen_size[1] * 1.5) GameObjects.Enemy( (pos_spanw_x, pos_spanw_y), choice(path_from_zombie), speed_move=randrange(100, round(101 + counter_kill * add_speed)), target=person, damage=randrange(1, round(2 + counter_kill * add_damage)), rotate=(1, lambda: person.get_rect().center), hp=randrange(1, round(2 + counter_kill * add_hp))).add( all_sprite, visible_objects, enemy) # Изменяем скорость персанажу в зависимости от убитых зомби person.edit_speed_move(round(600 + (counter_kill**0.5))) # Обработка столкновение зомби с персонажем for enem in pygame.sprite.spritecollide( person, enemy, False, collided=pygame.sprite.collide_rect): if pygame.sprite.collide_mask(person, enem): person.hit(enem.get_damage()) pos = person.get_rect().center if person.get_hp() <= 0 and flag: flag = False delta = datetime.now() - time_now - delta_quit result = cur.execute( f"""INSERT INTO records(rec) VALUES('{delta.seconds}') """ ) con.commit() indicator = GameObjects.GameObject( (pos[0] + randrange(25), pos[1] + randrange(25)), path_image=damage_indicator.render( str(-enem.get_damage()), True, (255, 255, 0)), time_life=10) indicator.add(all_sprite, visible_objects) # Обработка пуль с зомби for bull, enem in pygame.sprite.groupcollide( bullet, enemy, False, False).items(): for enemys in enem: if pygame.sprite.collide_mask(bull, enemys): enemys.hit(bull.get_damage()) pos = enemys.get_rect().center indicator = GameObjects.GameObject( (pos[0] + randrange(25), pos[1] + randrange(25)), path_image=damage_indicator.render( str(-enemys.get_damage()), True, (255, 0, 0)), time_life=10) indicator.add(all_sprite, visible_objects) if randrange(4): bull.kill() if enemys.get_hp() <= 0: counter_kill += 1 # Отрисовка всех элементов на экране visible_objects.draw(screen) xol = counter.render(f"Всего убито: {counter_kill}", True, [0, 0, 0]) screen.blit(xol, (0, 0)) hp_ind = hp_indicator.render(f"Hp: {person.get_hp()}", True, [255, 0, 255]) screen.blit(hp_ind, (screen_size[0] - 200, screen_size[1] - 100)) bul = bullet_reload_indicator.render( f"Bullet: {60 - person.get_count()}", True, [255, 0, 255]) screen.blit(bul, (screen_size[0] - 200, 50)) cursor_angle += 1 screen.blit(pygame.transform.rotate(MANUAL_CURSOR, cursor_angle), (pygame.mouse.get_pos())) clock.tick(FPS) pygame.display.flip() pygame.display.flip() main() return