-
Notifications
You must be signed in to change notification settings - Fork 1
/
Bird.py
90 lines (67 loc) · 2.4 KB
/
Bird.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import pygame
from NeuralNetwork import *
class Bird:
def __init__(self, img, neural_network=None, activation_type = "tanh"):
# Display parameters
self.img = img
self.width = self.img.get_width()
self.height = self.img.get_height()
# Position and derivative parameters
self.x = 30
self.y = 300
self.velocity = 0
self.gravity = 0.225
self.score = 0
# Fitness parameters
self.fitness = 0
self.time_alive = 0
self.center_dist = 0
if neural_network is not None:
self.nn = neural_network.copy()
else:
self.nn = NeuralNetwork(4,8,2,activation_type=activation_type)
def display(self, screen):
screen.blit(self.img, (self.x, self.y))
def jump(self):
if self.velocity >= 0:
self.velocity = -2
# Updates position parameters and derivatives
# Returns True if bird died, False if alive
def update(self, pipe, dt):
self.time_alive += 1
self.velocity += self.gravity
self.y += self.velocity * dt
if self.y <= 0:
self.y = 0
elif self.y >= 380:
# Game over if bird falls to ground
self.y = 380
return True
return self.is_collision(pipe)
def is_collision(self, pipe):
if pipe.x <= self.x + self.width and pipe.x + pipe.width >= self.x:
lower_pipe_height = pipe.height + pipe.gap
if self.y <= pipe.height or self.y >= lower_pipe_height - self.height:
return True
return False
def mutate(self, rate = 0.1):
self.nn.mutate(rate)
# Main function that calls the NN and get the output of it.
# Returns True if need to jump.
def predict_action(self, pipe):
inputs = []
# Inputs divided by max value to normalize
inputs.append(self.y / 400)
inputs.append(pipe.height / 400)
inputs.append(np.maximum(0, pipe.x / 300))
inputs.append(self.velocity / 4)
output = self.nn.predict(inputs)[0]
if output[0] > output[1]:
return True
else:
return False
def died(self, pipe, score):
self.score = score
# Center of pipe y
pipe_y = pipe.height + pipe.gap / 2
self.center_dist = np.abs(self.y - pipe_y)