MrVirabyan

Untitled

Jul 23rd, 2022
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.96 KB | None | 0 0
  1. import pygame
  2. import random
  3. import sys
  4. import math
  5. import neat
  6.  
  7. width = 1300
  8. height = 1100
  9. bg = (213,193,154,255)
  10.  
  11. generation = 0
  12.  
  13. class Car:
  14.  
  15. # list of available cars, take random everytime
  16. car_sprites = ("Audi", "Black_viper", "Orange", "Police", "Taxi")
  17.  
  18. def __init__(self):
  19. self.random_sprite()
  20.  
  21. self.angle = 0
  22. self.speed = 5
  23.  
  24. self.radars = []
  25. self.collision_points = []
  26.  
  27. self.is_alive = True
  28. self.goal = False
  29. self.distance = 0
  30. self.time_spent = 0
  31.  
  32. def random_sprite(self):
  33. self.car_sprite = pygame.image.load('sprites/' + random.choice(self.car_sprites) + '.png')
  34. self.car_sprite = pygame.transform.scale(self.car_sprite,
  35. (math.floor(self.car_sprite.get_size()[0]/2), math.floor(self.car_sprite.get_size()[1]/2)))
  36. self.car = self.car_sprite
  37.  
  38. # recompute
  39. self.pos = [650, 930]
  40. self.compute_center()
  41.  
  42. def compute_center(self):
  43. self.center = (self.pos[0] + (self.car.get_size()[0]/2), self.pos[1] + (self.car.get_size()[1] / 2))
  44.  
  45. def draw(self, screen):
  46. screen.blit(self.car, self.pos)
  47. self.draw_radars(screen)
  48.  
  49. def draw_center(self, screen):
  50. pygame.draw.circle(screen, (0,72,186), (math.floor(self.center[0]), math.floor(self.center[1])), 5)
  51.  
  52. def draw_radars(self, screen):
  53. for r in self.radars:
  54. p, d = r
  55. pygame.draw.line(screen, (183,235,70), self.center, p, 1)
  56. pygame.draw.circle(screen, (183,235,70), p, 5)
  57.  
  58. def compute_radars(self, degree, road):
  59. length = 0
  60. x = int(self.center[0] + math.cos(math.radians(360 - (self.angle + degree))) * length)
  61. y = int(self.center[1] + math.sin(math.radians(360 - (self.angle + degree))) * length)
  62.  
  63. while not road.get_at((x, y)) == bg and length < 300:
  64. length = length + 1
  65. x = int(self.center[0] + math.cos(math.radians(360 - (self.angle + degree))) * length)
  66. y = int(self.center[1] + math.sin(math.radians(360 - (self.angle + degree))) * length)
  67.  
  68. dist = int(math.sqrt(math.pow(x - self.center[0], 2) + math.pow(y - self.center[1], 2)))
  69. self.radars.append([(x, y), dist])
  70.  
  71. def compute_collision_points(self):
  72. self.compute_center()
  73. lw = 65
  74. lh = 65
  75.  
  76. lt = [self.center[0] + math.cos(math.radians(360 - (self.angle + 20))) * lw, self.center[1] + math.sin(math.radians(360 - (self.angle + 20))) * lh]
  77. rt = [self.center[0] + math.cos(math.radians(360 - (self.angle + 160))) * lw, self.center[1] + math.sin(math.radians(360 - (self.angle + 160))) * lh]
  78. lb = [self.center[0] + math.cos(math.radians(360 - (self.angle + 200))) * lw, self.center[1] + math.sin(math.radians(360 - (self.angle + 200))) * lh]
  79. rb = [self.center[0] + math.cos(math.radians(360 - (self.angle + 340))) * lw, self.center[1] + math.sin(math.radians(360 - (self.angle + 340))) * lh]
  80.  
  81. self.collision_points = [lt, rt, lb, rb]
  82.  
  83. def draw_collision_points(self, road, screen):
  84. if not self.collision_points:
  85. self.compute_collision_points()
  86.  
  87. for p in self.collision_points:
  88. if(road.get_at((int(p[0]), int(p[1]))) == bg):
  89. pygame.draw.circle(screen, (255,0,0), (int(p[0]), int(p[1])), 5)
  90. else:
  91. pygame.draw.circle(screen, (15,192,252), (int(p[0]), int(p[1])), 5)
  92.  
  93. def check_collision(self, road):
  94. self.is_alive = True
  95.  
  96. for p in self.collision_points:
  97. try:
  98. if road.get_at((int(p[0]), int(p[1]))) == bg:
  99. self.is_alive = False
  100. break
  101. except IndexError:
  102. self.is_alive = False
  103.  
  104. def rotate(self, angle):
  105. orig_rect = self.car_sprite.get_rect()
  106. rot_image = pygame.transform.rotate(self.car_sprite, angle)
  107. rot_rect = orig_rect.copy()
  108. rot_rect.center = rot_image.get_rect().center
  109. rot_image = rot_image.subsurface(rot_rect).copy()
  110.  
  111. self.car = rot_image
  112.  
  113. def get_data(self):
  114. radars = self.radars
  115. data = [0, 0, 0, 0, 0]
  116.  
  117. for i, r in enumerate(radars):
  118. data[i] = int(r[1] / 30)
  119.  
  120. return data
  121.  
  122. def get_reward(self):
  123. return self.distance / 50.0
  124.  
  125. def update(self, road):
  126. # set some fixed speed
  127. self.speed = 5
  128.  
  129. # rotate
  130. self.rotate(self.angle)
  131.  
  132. # move
  133. self.pos[0] += math.cos(math.radians(360 - self.angle)) * self.speed
  134. if self.pos[0] < 20:
  135. self.pos[0] = 20
  136. elif self.pos[0] > width - 120:
  137. self.pos[0] = width - 120
  138.  
  139. self.pos[1] += math.sin(math.radians(360 - self.angle)) * self.speed
  140. if self.pos[1] < 20:
  141. self.pos[1] = 20
  142. elif self.pos[1] > height - 120:
  143. self.pos[1] = height - 120
  144.  
  145. # update distance & time spent
  146. self.distance += self.speed
  147. self.time_spent += 1 # aka turns
  148.  
  149. # compute/check collision points & create radars
  150. self.compute_collision_points()
  151. self.check_collision(road)
  152.  
  153. self.radars.clear()
  154. for d in range(-90, 120, 45):
  155. self.compute_radars(d, road)
  156.  
  157. start = False
  158.  
  159. def run_generation(genomes, config):
  160.  
  161. nets = []
  162. cars = []
  163.  
  164. # init genomes
  165. for i, g in genomes:
  166. net = neat.nn.FeedForwardNetwork.create(g, config)
  167. nets.append(net)
  168. g.fitness = 0 # every genome is not successful at the start
  169.  
  170. # init cars
  171. cars.append(Car())
  172.  
  173. # init the game
  174. pygame.init()
  175. screen = pygame.display.set_mode((width, height))
  176. clock = pygame.time.Clock()
  177. road = pygame.image.load('sprites/road.png')
  178.  
  179. font = pygame.font.SysFont("Roboto", 40)
  180. heading_font = pygame.font.SysFont("Roboto", 80)
  181.  
  182. # the LOOP
  183. global generation
  184. global start
  185. generation += 1
  186.  
  187. while True:
  188. for event in pygame.event.get():
  189. if event.type == pygame.QUIT:
  190. sys.exit(0)
  191. elif event.type == pygame.KEYDOWN:
  192. if event.key == pygame.K_SPACE:
  193. start = True
  194.  
  195. if not start:
  196. continue
  197.  
  198. # input each car data
  199. for i, car in enumerate(cars):
  200. output = nets[i].activate(car.get_data())
  201. i = output.index(max(output))
  202.  
  203. if i == 0:
  204. car.angle += 5
  205. elif i == 1:
  206. car.angle = car.angle
  207. elif i == 2:
  208. car.angle -= 5
  209.  
  210. # now, update car and set fitness (for alive cars only)
  211. cars_left = 0
  212. for i, car in enumerate(cars):
  213. if car.is_alive:
  214. cars_left += 1
  215. car.update(road)
  216. genomes[i][1].fitness += car.get_reward() # new fitness (aka car instance success)
  217.  
  218. # check if cars left
  219. if not cars_left:
  220. break
  221.  
  222. # display stuff
  223. screen.blit(road, (0, 0))
  224.  
  225. for car in cars:
  226. if car.is_alive:
  227. car.draw(screen)
  228. # car.draw_center(screen)
  229. # car.draw_collision_points(road, screen)
  230.  
  231. label = heading_font.render("Поколение: " + str(generation), True, (73,168,70))
  232. label_rect = label.get_rect()
  233. label_rect.center = (width / 1.5, 300)
  234. screen.blit(label, label_rect)
  235.  
  236. label = font.render("Машин осталось: " + str(cars_left), True, (51,59,70))
  237. label_rect = label.get_rect()
  238. label_rect.center = (width / 1.5, 375)
  239. screen.blit(label, label_rect)
  240.  
  241. pygame.display.flip()
  242. clock.tick(30)
  243.  
  244. if __name__ == "__main__":
  245. # setup config
  246. config_path = "./config-feedforward.txt"
  247. config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, config_path)
  248.  
  249. # init NEAT
  250. p = neat.Population(config)
  251.  
  252. # run NEAT
  253. p.run(run_generation, 1000)
Advertisement
Add Comment
Please, Sign In to add comment