-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathDinosaur.py
185 lines (156 loc) · 6.69 KB
/
Dinosaur.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import subprocess
try:
import tensorflow as tf
except ImportError as err:
subprocess.check_call(['pip', 'install', 'tensorflow'])
subprocess.check_call(['pip', 'install', 'Pillow'])
import tensorflow as tf
import pygame
import os
import glob
from NeuralNetwork import NeuralNetwork
import numpy as np
from tensorflow.keras.preprocessing.image import load_img, img_to_array
# Bring images from assets
RUNNING = [os.path.join("Assets/Dino", "DinoRun1.png"),
os.path.join("Assets/Dino", "DinoRun2.png")]
JUMPING = [os.path.join("Assets/Dino", "DinoJump.png")]
DUCKING = [os.path.join("Assets/Dino", "DinoDuck1.png"),
os.path.join("Assets/Dino", "DinoDuck2.png")]
CLASSES = ["JUMP", "DUCK", "RIGHT"]
class Dinosaur(NeuralNetwork):
# Define as global the starting position for the dinosaur
X_POS = 80
Y_POS = 310
Y_POS_DUCK = 340
JUMP_VEL = 8.5
def __init__(self, id, mask_color = None, autoplay = False):
# As 'NeuralNetwork' serves as base class for the dinosaur, start its 'brain'
super().__init__()
self.id = id
self.color = mask_color
self.autoPlay = autoplay
self.duck_img = self.load_images(DUCKING)
self.run_img = self.load_images(RUNNING)
self.jump_img = self.load_images(JUMPING)
self.resetStatus()
# If a tensorflow model is provided, load it
model_file = glob.glob('*.h5')
if model_file:
# Cargar el modelo si el archivo existe
self.model = tf.keras.models.load_model(model_file[0])
self.model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
# Basic state the dinosaur is in when spawning
def resetStatus(self):
self.dino_duck = False
self.dino_run = True
self.dino_jump = False
self.step_index = 0
self.jump_vel = self.JUMP_VEL
self.image = self.run_img[0]
self.dino_rect = self.image.get_rect()
self.dino_rect.x = self.X_POS
self.dino_rect.y = self.Y_POS
self.alive = True
self.score = 0
# Load the image form assets masking it with a layer of the selected color for this dino
def load_images(self, base_name):
images = []
for image_path in base_name:
result = pygame.image.load(image_path).convert_alpha()
# Apply the color mask if a color is selected
if self.color:
result.fill(self.color, special_flags=pygame.BLEND_ADD)
images.append(result)
return images
# Update the dinosaur's status
def update(self, userInput):
# Execute the corresponding actions for the current state
if self.dino_duck:
self.duck()
if self.dino_run:
self.run()
if self.dino_jump:
self.jump()
if self.step_index >= 10:
self.step_index = 0
# Set the next state for the dinosaur. The selection mode depends on the playmode selected for the game.
if self.autoPlay:
if userInput == "JUMP" and not self.dino_jump:
self.dino_duck = False
self.dino_run = False
self.dino_jump = True
elif userInput == "DUCK":
self.dino_duck = True
self.dino_run = False
self.dino_jump = False
elif not (self.dino_jump or userInput == "DUCK"):
self.dino_duck = False
self.dino_run = True
self.dino_jump = False
else:
if userInput[pygame.K_UP] and not self.dino_jump:
self.dino_duck = False
self.dino_run = False
self.dino_jump = True
elif userInput[pygame.K_DOWN]:
self.dino_duck = True
self.dino_run = False
self.dino_jump = False
elif not (self.dino_jump or userInput[pygame.K_DOWN]):
self.dino_duck = False
self.dino_run = True
self.dino_jump = False
def duck(self):
# Change the image every 5 frames to walk
self.image = self.duck_img[self.step_index // 5]
# If we duck on mid-air, fall faster by aumenting rapidly the dinosaur's height until reaching ground
if (self.dino_rect.y < self.Y_POS):
self.dino_rect.y += self.JUMP_VEL * 6
if (self.dino_rect.y >= self.Y_POS_DUCK):
self.dino_rect.y = self.Y_POS_DUCK
# Set the ducking position when grounded
else:
self.dino_rect = self.image.get_rect()
self.dino_rect.x = self.X_POS
self.dino_rect.y = self.Y_POS_DUCK
self.jump_vel = self.JUMP_VEL
self.step_index += 1
def run(self):
# Change the image every 5 frames to walk
self.image = self.run_img[self.step_index // 5]
# Set the running position
self.dino_rect = self.image.get_rect()
self.dino_rect.x = self.X_POS
self.dino_rect.y = self.Y_POS
self.step_index += 1
def jump(self):
# Change the image
self.image = self.jump_img[0]
# Reduce the dinosaur's position until the jumping speed is negative; then fall
if self.dino_jump:
self.dino_rect.y -= self.jump_vel * 4
self.jump_vel -= 0.8
if self.jump_vel < - self.JUMP_VEL:
self.dino_jump = False
self.jump_vel = self.JUMP_VEL
# Draw the element on screen
def draw(self, SCREEN):
SCREEN.blit(self.image, (self.dino_rect.x, self.dino_rect.y))
# When playing in automatic mode using the tensorflow model, takes a frame and sends it to the model to define the next action
def predict(self):
self.autoPlay = True
# Take a screenshot and arrange the image
# ===================== ARREGLAR TAMAÑO DE IMAGEN, NORMALIZACIÓN Y CANTIDAD DE CLASES PREDICHAS DE SER NECESARIO ===============
img = load_img("./images/live/temp.png", color_mode='grayscale', target_size=(600,400))
img_array = img_to_array(img)
img_array = img_array / 255.0 # Normaliza los valores de píxeles entre 0 y 1
img_array = np.expand_dims(img_array, axis=0) # Agrega una dimensión extra para el batch
# Use the model to make a decision based on the screenshot
predictions = self.model.predict(img_array)
predicted_class_index = np.argmax(predictions)
# ==============================================================================================================================
# Call the update method with the result
self.update(CLASSES[predicted_class_index])