-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgame_sim.py
166 lines (128 loc) · 6.05 KB
/
game_sim.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
import pygame
from game_objects import Tank, HUD
from game_agents import *
class Game:
def __init__(self, length=800, width=800):
# Save the parameters of the simulation
self.canvas_length = length # Default is 800
self.canvas_width = width # Default is 800
# Initialize pygame library
pygame.init()
# Initialize the window, set caption
self.screen = pygame.display.set_mode((self.canvas_length, self.canvas_width))
pygame.display.set_caption('Reinforcement Learning: Tanks')
# Create a new surface to be used as a background for setting caption, HUD and other stuff
bg = pygame.Surface(self.screen.get_size())
# convert with no arguments will make sure our background is the same format as the display window
self.background = bg.convert()
# Set the color as black
self.background.fill((0, 0, 0))
self.player_agents = []
self.player_agents.append(HumanAgent(name='Human', game_obj=self))
self.player_agents.append(RLAgent(name='RL Agent', game_obj=self))
# Create all sprites
self.all_player_sprites = pygame.sprite.RenderPlain(())
self.all_projectile_sprites = pygame.sprite.RenderPlain(())
# Create an HUD
self.hud_sprite = HUD(game_obj=self)
# Create a clock
self.clock = pygame.time.Clock()
# Game state variables
self.round_not_over = True
def start_round(self):
# Create tank(s) for the human agent
tank1 = Tank(game_obj=self, image_name='images/tank1.bmp',
init_direction=90, agent=self.player_agents[0],
x=10, y=10)
self.all_player_sprites.add(tank1)
# Create tank(s) for the computer agent
tank2 = Tank(game_obj=self, image_name='images/tank2.bmp',
init_direction=270, agent=self.player_agents[1],
x=750, y=750)
self.all_player_sprites.add(tank2)
# Call update methods of all the sprites
self.all_player_sprites.update()
self.all_projectile_sprites.update()
# Update the player sprites and projectiles
self.screen.blit(self.background, (0, 0))
self.all_player_sprites.draw(self.screen)
self.all_projectile_sprites.draw(self.screen)
pygame.display.flip()
self.round_not_over = True
def play_round(self):
game_running = True
while self.round_not_over:
# This will ensure that the game doesn't run faster than 60 FPS
self.clock.tick(60)
keys = pygame.key.get_pressed()
events = pygame.event.get()
# Check for "quit" events
for event in events:
if event.type == QUIT:
game_running = False
self.round_not_over = False
elif event.type == KEYDOWN and event.key == K_ESCAPE:
game_running = False
self.round_not_over = False
# Tell agents to take actions
for agent in self.player_agents:
agent.take_action(keys=keys, events=events)
# Call update methods of all the sprites
self.all_player_sprites.update()
self.all_projectile_sprites.update()
# Update the player sprites and projectiles
self.screen.blit(self.background, (0, 0))
self.all_player_sprites.draw(self.screen)
self.all_projectile_sprites.draw(self.screen)
pygame.display.flip()
return game_running
def show_welcome_screen(self):
self.background.fill((0, 0, 0))
if pygame.font:
font = pygame.font.Font(None, 36)
text = font.render("The tank which shoots down the other, wins.", 1, (255, 255, 255))
text_pos = text.get_rect(centerx=self.background.get_width() / 2, centery=30)
self.background.blit(text, text_pos)
text = font.render("Press Enter to start.", 1, (255, 255, 255))
text_pos = text.get_rect(centerx=self.background.get_width() / 2, centery=60)
self.background.blit(text, text_pos)
# blit() superimposes the Surface() objects on one another and flip() swaps the double/single buffered displays
self.screen.blit(self.background, (0, 0))
pygame.display.flip()
show_title = True
while show_title:
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == K_RETURN:
show_title = False
self.background.fill((0, 0, 0))
self.hud_sprite.update()
def show_winner(self):
self.background.fill((0, 0, 0))
from operator import attrgetter
winner = max(self.player_agents, key=attrgetter('score'))
if pygame.font:
font = pygame.font.Font(None, 36)
text = font.render("Winner: " + winner.name, 1, (255, 255, 255))
text_pos = text.get_rect(centerx=self.background.get_width() / 2, centery=30)
self.background.blit(text, text_pos)
text = font.render("Press Esc to quit.", 1, (255, 255, 255))
text_pos = text.get_rect(centerx=self.background.get_width() / 2, centery=60)
self.background.blit(text, text_pos)
# blit() superimposes the Surface() objects on one another and flip() swaps the double/single buffered displays
self.screen.blit(self.background, (0, 0))
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == K_ESCAPE:
return
def run(self):
self.show_welcome_screen()
going = True
while going:
# Keep playing rounds until the end condition is hit
self.start_round()
going = self.play_round()
# Update the HUD after each round
self.hud_sprite.update()
# Print winner on the screen
self.show_winner()