You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
5.8 KiB
192 lines
5.8 KiB
# coding:utf-8
|
|
|
|
import pygame
|
|
import sys
|
|
from pygame.locals import *
|
|
import random
|
|
import math
|
|
|
|
import forAI
|
|
|
|
BACKGROUND = (255, 255, 255)
|
|
SCREEN_SIZE = (800, 600)
|
|
MAX = 0
|
|
Generation = 0
|
|
|
|
class Plane():
|
|
def __init__(self, plane_image):
|
|
self.plane_image = plane_image
|
|
self.rect = plane_image.get_rect()
|
|
|
|
self.width = self.rect[2]
|
|
self.height = self.rect[3]
|
|
self.x = SCREEN_SIZE[0] / 2 - self.width / 2
|
|
self.y = SCREEN_SIZE[1] - self.height
|
|
|
|
self.move_x = 0
|
|
self.speed = 2
|
|
|
|
self.alive = True
|
|
|
|
def update(self):
|
|
self.x += self.move_x * self.speed
|
|
if self.x+self.width > SCREEN_SIZE[0]:#飞出右边
|
|
self.x =0 # 如果超出屏幕则还原
|
|
elif self.x<0:#左边
|
|
self.x = SCREEN_SIZE[0]-self.width#如果超出屏幕则还原
|
|
|
|
def draw(self, screen):
|
|
screen.blit(self.plane_image, (self.x, self.y, self.width, self.height))
|
|
|
|
def is_dead(self, enemies):
|
|
# if self.x < -self.width or self.x + self.width > SCREEN_SIZE[0] + self.width:
|
|
# return True
|
|
|
|
for eneme in enemies:
|
|
if self.collision(eneme):
|
|
return True
|
|
return False
|
|
|
|
def collision(self, enemy):
|
|
if not (self.x > enemy.x + enemy.width or self.x + self.width < enemy.x or self.y > enemy.y + enemy.height or self.y + self.height < enemy.y):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def get_Xs(self, enemies, Size=4):##计算x轴相对位置
|
|
Xs = []
|
|
|
|
for i in range(Size):
|
|
Xs.append(0.0)
|
|
|
|
Xs[0] = (self.x * 1.0 / SCREEN_SIZE[0])
|
|
index = 1
|
|
for eneme in enemies:
|
|
Xs[index] = eneme.x * 1.0 / SCREEN_SIZE[0]
|
|
index += 1
|
|
Xs[index] = eneme.y * 1.0 / SCREEN_SIZE[1]
|
|
index += 1
|
|
if len(enemies) > 0 and self.x < enemies[0].x:
|
|
Xs[index] = -1.0
|
|
#index += 1
|
|
else:
|
|
Xs[index] = 1.0
|
|
#print("---------" + str(index) + "---------")
|
|
|
|
return Xs
|
|
|
|
|
|
class Enemy():
|
|
def __init__(self, enemy_image):
|
|
self.enemy_image = enemy_image
|
|
self.rect = enemy_image.get_rect()
|
|
|
|
self.width = self.rect[2]
|
|
self.height = self.rect[3]
|
|
self.x = random.choice(range(0, int(SCREEN_SIZE[0] - self.width / 2), 71))
|
|
self.y = 0
|
|
|
|
def update(self):
|
|
self.y += 6
|
|
|
|
def draw(self, screen):
|
|
screen.blit(self.enemy_image, (self.x, self.y, self.width, self.height))
|
|
|
|
def is_out(self):
|
|
return True if self.y >= SCREEN_SIZE[1] else False
|
|
|
|
|
|
class Game():
|
|
def __init__(self):
|
|
pygame.init()
|
|
self.screen = pygame.display.set_mode(SCREEN_SIZE)
|
|
self.clock = pygame.time.Clock()
|
|
pygame.display.set_caption('AI躲核弹')
|
|
|
|
self.ai = forAI.NeuroEvolution()
|
|
self.generation = 0
|
|
self.max_enemes = 1
|
|
# 加载飞机、敌机图片
|
|
self.plane_image = pygame.image.load('plane.png')
|
|
self.enemy_image = pygame.image.load('enemy.png')
|
|
|
|
def start(self):
|
|
self.score = 0
|
|
self.planes = []
|
|
self.enemes = []
|
|
|
|
self.gen = self.ai.next_generation()#AI初始化
|
|
for i in range(len(self.gen)):
|
|
plane = Plane(self.plane_image)
|
|
self.planes.append(plane)
|
|
|
|
self.generation += 1
|
|
self.alives = len(self.planes)
|
|
|
|
def update(self, screen):
|
|
global MAX,Generation
|
|
self.gen_enemes()
|
|
for i in range(len(self.planes)):
|
|
if self.planes[i].alive:
|
|
Xs = self.planes[i].get_Xs(self.enemes)
|
|
res = self.gen[i].feed_forward(Xs)
|
|
if res[0] < 0.45:
|
|
self.planes[i].move_x = -1
|
|
elif res[0] > 0.55:
|
|
self.planes[i].move_x = 1
|
|
self.planes[i].update()
|
|
self.planes[i].draw(screen)
|
|
for eneme in self.enemes[:]:
|
|
if self.planes[i].collision(eneme):
|
|
self.alives -= 1
|
|
self.enemes.remove(eneme)
|
|
self.planes[i].alive = False
|
|
self.ai.network_score(self.score, self.gen[i])#评分
|
|
if self.is_ai_all_dead():
|
|
self.start()
|
|
break
|
|
for eneme in self.enemes[:]:
|
|
eneme.update()
|
|
eneme.draw(screen)
|
|
if eneme.is_out():
|
|
self.score += 1
|
|
self.enemes.remove(eneme)
|
|
end = '\r'
|
|
if(self.score!=0):
|
|
if(self.generation>Generation):#分数大于最大值或者子代更迭才显示
|
|
Generation=self.generation
|
|
print(" 迭代次数:{}, 存活飞机数:{},得分:{}".format(self.generation, self.alives, self.score), end)
|
|
if(self.score>MAX):
|
|
MAX=self.score
|
|
print(" 迭代次数:{}, 存活飞机数:{},得分:{}".format(self.generation, self.alives, self.score), end)
|
|
|
|
def run(self, FPS=100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000):
|
|
while True:
|
|
for event in pygame.event.get():
|
|
if event.type == QUIT:
|
|
pygame.quit()
|
|
sys.exit()
|
|
|
|
self.screen.fill(BACKGROUND) #背景色
|
|
|
|
self.update(self.screen)
|
|
|
|
pygame.display.update()
|
|
self.clock.tick(FPS)
|
|
|
|
def gen_enemes(self):
|
|
if len(self.enemes) < self.max_enemes:
|
|
enemy = Enemy(self.enemy_image)
|
|
self.enemes.append(enemy)
|
|
|
|
def is_ai_all_dead(self):
|
|
for plane in self.planes:
|
|
if plane.alive:
|
|
return False
|
|
return True
|
|
|
|
|
|
game = Game()
|
|
game.start()
|
|
game.run()
|