首页 > 解决方案 > NEAT 实施 - 代码准备。创建多个对象的问题

问题描述

我创建了简单的游戏。现在我想实现 NEAT 来学习和控制我的游戏。

我按照本教程进行操作,但是发现了问题。

作为游戏准备的一部分,YT 上的作者修改了他的游戏以创建鸟类种群。就我而言,这将是一群船只。

据我了解,我需要在某个地方创建一个列表ships[]并循环for ship in ships: ...。问题是,我不知道该放在哪里。

这是我的main.py文件(我认为所有更改都应该在这里完成):

import sys
import pygame
import os
import neat
from rocket import Rocket


class Game(object):
    def __init__(self):
        # configuration
        self.tps_max = 60.0
        # initialization
        pygame.init()
        self.screen = pygame.display.set_mode((1280, 720))
        self.screen_rect = self.screen.get_rect()
        self.tps_clock = pygame.time.Clock()
        self.tps_delta = 0.0
        self.player = Rocket(self)
        game = True
        while game is True:
            # Handle events
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit(0)
                elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                    sys.exit(0)

            # ticking
            self.tps_delta += self.tps_clock.tick() / 1000.0
            while self.tps_delta > 1 / self.tps_max:
                self.tick()
                self.tps_delta -= 1 / self.tps_max

            # drawing
            self.screen.fill((164, 222, 245))
            self.draw()
            pygame.display.flip()

    def tick(self):
        # check input
        self.player.tick()

    def draw(self):
        self.player.draw()

# def run(): to be continued
#    config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet,
#    neat.DefaultStagnation, config_path)
#
#    p = neat.Population(config)
#    p.add_reporter(neat.StdOutReporter(True))
#    stats = neat.StatisticsReporter()
#    p.add_reporter = stats
#
#    winner =p.run(Rocket.tick() , 50)


if __name__ == "__main__":
    #  local_dir = os.path.dirname(__file__)
    #  config_path = os.path.join(local_dir, "config-feedforward.txt")
    #  run(config_path)
    Game()

我的rocket.py文件(我希望这里没有变化):

import pygame
import random
import math
import sys
from pygame.math import Vector2

pygame.font.init()
font = pygame.font.Font(None, 30)
clock = pygame.time.Clock()
start_time = pygame.time.get_ticks()


class Rocket(object):

    def __init__(self, game):
        self.game = game
        size = self.game.screen.get_size()
        self.speed = 3.0
        self.wind_force = 0.4
        self.wind_angle = random.randint(0, 359)
        self.current_force = 0.2
        self.current_angle = random.randint(0, 359)
        self.random_change = 0
        self.pos = Vector2(size[0] / 2, size[1] / 2)
        self.offset = 0
        self.score = 0
        self.counting_time= 0
        self.counting_seconds = 0
        self.vel = Vector2(0, 0)
        self.acc = Vector2(0, 0)
        # heading vector

        self.heading = self.vel.angle_to(Vector2(0, 1))
        self.angle_speed = 0
        self.heading = random.randint(0, 359)

    def addforce(self, force):
        self.acc += force

    def tick(self):
        # Input

        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_w]:
            self.addforce(Vector2(0, -self.speed * 0.6).rotate(self.heading))
        if pressed[pygame.K_s]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading))
        if pressed[pygame.K_d]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading - 90))
        if pressed[pygame.K_a]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading + 90))
        if pressed[pygame.K_q]:
            self.angle_speed -= 1
        if pressed[pygame.K_e]:
            self.angle_speed += 1
        # Physics

        self.wind_angle = (self.wind_angle + 0.5 * random.randint(-3, 3)) % 360
        self.wind_force += ((random.randint(-2, 3)) / 1000)

        self.current_angle = (self.current_angle + 0.5 * random.randint(-2, 2)) % 360
        self.current_force += ((random.randint(-2, 3)) / 1000)

        self.vel *= 0.5
        self.vel += Vector2(0, self.wind_force).rotate(self.wind_angle)
        self.vel += Vector2(0, self.current_force).rotate(self.current_angle)
        self.vel += self.acc
        self.pos += self.vel
        self.acc *= 0.5
        self.angle_speed *= 0.3

        self.heading = (self.heading + self.angle_speed) % 360
        # offset
        # check distance from centre to vessel pos
        self.offset = math.hypot(((self.vel[0] - self.pos[0]) + 640), ((self.vel[1] - self.pos[1]) + 360))
        # offset as 1
        self.offset /= 400
        # offset as accuracy in %
        self.offset = int((1 - self.offset) * 100)
        self.counting_time = pygame.time.get_ticks() - start_time
        self.counting_seconds = (int((self.counting_time / 1000)))
        self.score = round((self.counting_seconds * 10 + self.offset))
        self.score += self.score
        if self.pos.x < 0 or self.pos.x > 1280 or self.pos.y < 0 or self.pos.y > 720:
            pygame.quit()
            sys.exit(0)
        else:
            pass

    def draw(self):

        # base shape
        vessel = [Vector2(5, 10), Vector2(-5, 10), Vector2(-5, -10), Vector2(0, -15), Vector2(5, -10)]
        wind_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15), Vector2(20, 0),
                      Vector2(20, 10)]
        current_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15),
                         Vector2(20, 0),
                         Vector2(20, 10)]

        # rotating points

        vessel = [p.rotate(self.heading) for p in vessel]
        wind_arrow = [p.rotate(self.wind_angle + 90) for p in wind_arrow]
        current_arrow = [p.rotate(self.current_angle + 90) for p in current_arrow]

        # centered position & scale
        vessel = [self.pos + p * 6 for p in vessel]
        wind_arrow = [self.pos + p for p in wind_arrow]
        current_arrow = [self.pos + p for p in current_arrow]
        # draw shape

        pygame.draw.polygon(self.game.screen, (255, 177, 10), vessel)
        pygame.draw.polygon(self.game.screen, (233, 66, 245), wind_arrow)
        pygame.draw.polygon(self.game.screen, (22, 57, 217), current_arrow)
        pygame.draw.circle(self.game.screen, (255, 255, 255,), (640, 360), 5, 3)

        def write(text, location, color=(0, 0, 0)):
            self.game.screen.blit(font.render(text, True, color), location)

        write("Accuracy: " + str(self.offset) + ' %', (20, 10))
        write('Wind direction: ' + str(round(self.wind_angle)) + " deg . Wind force: " + str(
            round((self.wind_force * 10), 2)), (20, 40))
        write('Current direction: ' + str(round(self.current_angle)) + " deg . Current force: " + str(
            round(self.current_force, 2)),
              (20, 60))
        if self.pos.x < 200 or self.pos.x > 1080 or self.pos.y < 200 or self.pos.y > 520:
            write('OUT OF POSITION!', (560, 320))
            # pygame.time.wait(2000)

        else:

            pass

        write("Time: " + str(self.counting_seconds) + " s", (200,10))
        write("Total score: " + str(self.score), (400, 10))

简洁的FLappy Birds代码

另一个问题是def eval_genomes(genomes, config):小鸟游戏中的功能。

我的游戏中的哪个函数与 def 相关eval_genomes(genomes, config)?它是课堂上tick()的功能吗?Game还是我需要在我的main.py课外创建它Game

标签: pythonpygameneat

解决方案


对于def eval_genomes(genomes, config):功能,您必须插入事件处理和滴答声。您可以通过将这些代码块转换为方法class Game然后将其插入到函数中来做到这一点。

也在函数def eval_genomes(genomes, config):中创建列表。


推荐阅读