-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame.py
328 lines (273 loc) · 12.8 KB
/
game.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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
import pygame, random
import json
from boss_laser import BossLaser
from shooter import Shooter
from object import Object
from object import grid
from invader import Invader, BonusShip, Boss
from laser import Laser
class Game:
def __init__(self, screen_width, screen_height, menu_state, selected_character_index, selected_level_index,username):
self.screen_width = screen_width
self.screen_height = screen_height
self.menu_state = menu_state
self.selected_character_index = selected_character_index
self.selected_level_index = selected_level_index
self.shooter_group = pygame.sprite.GroupSingle()
self.shooter_group.add(Shooter(self.screen_width, self.screen_height, self.selected_character_index))
self.object = self.create_object()
self.invaders_group = pygame.sprite.Group()
self.invader_direction = 1
self.invader_lasers_group = pygame.sprite.Group()
self.bonus_ship_group = pygame.sprite.GroupSingle()
# Initialize boss_group here, before using it
self.boss_group = pygame.sprite.GroupSingle()
self.lives = 3
self.run = True
self.score = 0
self.highscore = 0
self.explosion_sound = pygame.mixer.Sound("Sounds/explosion.ogg")
# Create invaders after boss_group initialization
self.create_invaders()
self.boss_lasers_group = pygame.sprite.Group()
self.last_boss_shot = 0
self.username = username
self.user_data = self.load_user_data()
self.highscore = self.get_user_highscore(username, self.selected_level_index)
def create_object(self):
object_width = len(grid[0]) * 3
total_object_width = 4 * object_width
gap = (self.screen_width - total_object_width) / 5
objects = []
for i in range(4):
offset_x = (i * object_width) + (i + 1) * gap
obj = Object(offset_x, self.screen_height - 100)
objects.append(obj)
return objects
def create_invaders(self):
if self.selected_level_index == 0:
for row in range(5):
for column in range(11):
x = 75 + column * 55
y = 30 + row * 55
if column == row or column == 10 - row:
invader_type = 1 if row < 2 else 2
invader = Invader(invader_type, x, y)
self.invaders_group.add(invader)
elif self.selected_level_index == 1:
for row in range(5):
if row == 1 or row == 3:
continue
for column in range(11):
x = 75 + column * 55
y = 30 + row * 55
invader_type = 1 if row < 2 else 2
invader = Invader(invader_type, x, y)
self.invaders_group.add(invader)
elif self.selected_level_index == 2:
for row in range(5):
for column in range(5):
x = 150 + column * 55
y = 100 + row * 55
invader_type = 1 if row < 2 else 2
invader = Invader(invader_type, x, y)
self.invaders_group.add(invader)
elif self.selected_level_index == 3:
for row in range(5):
for column in range(11):
x = 75 + column * 55
y = 30 + row * 55
invader_type = 1 if row < 2 else 2
invader = Invader(invader_type, x, y)
self.invaders_group.add(invader)
elif self.selected_level_index == 4:
self.boss_group.add(Boss(self.screen_width, self.screen_height))
def move_invaders(self):
self.invaders_group.update(self.invader_direction)
invader_sprites = self.invaders_group.sprites()
for invader in invader_sprites:
if invader.rect.right >= self.screen_width:
self.invader_direction = -1
self.invader_move_down(1)
elif invader.rect.left <= 0:
self.invader_direction = 1
self.invader_move_down(1) # could remove this property
def invader_move_down(self, distance):
if self.invaders_group:
for invader in self.invaders_group.sprites():
invader.rect.y += distance
def create_bonus_ship(self):
if self.selected_level_index == 0:
self.bonus_ship_group.add(BonusShip(self.screen_width))
def check_for_collisions(self):
# Shooter's lasers
if self.shooter_group.sprite.lasers_group:
for laser_sprite in self.shooter_group.sprite.lasers_group:
# Kiểm tra va chạm giữa laser của người chơi và các invaders
invaders_hit = pygame.sprite.spritecollide(laser_sprite, self.invaders_group, True)
if invaders_hit:
for invader in invaders_hit:
self.score += invader.type * 100
self.check_for_highscore()
laser_sprite.kill()
# Kiểm tra va chạm giữa laser và bonus ship
if pygame.sprite.spritecollide(laser_sprite, self.bonus_ship_group, True):
self.score += 500
self.check_for_highscore()
laser_sprite.kill()
# Kiểm tra va chạm giữa laser và boss
if pygame.sprite.spritecollide(laser_sprite, self.boss_group, False):
self.score += 500
self.check_for_highscore()
laser_sprite.kill()
self.boss_group.sprite.take_damage()
# Kiểm tra va chạm với các khối block
for obj in self.object:
if pygame.sprite.spritecollide(laser_sprite, obj.blocks_group, True):
laser_sprite.kill()
# Invader lasers
if self.invader_lasers_group:
for laser_sprite in self.invader_lasers_group:
# Kiểm tra va chạm giữa laser của invader và shooter
if pygame.sprite.spritecollide(laser_sprite, self.shooter_group, False):
laser_sprite.kill()
self.lives -= 1
if self.lives == 0:
self.game_over()
return "lose"
# Kiểm tra va chạm với các khối block
for obj in self.object:
if pygame.sprite.spritecollide(laser_sprite, obj.blocks_group, True):
laser_sprite.kill()
# Invaders hitting blocks
if self.invaders_group:
for invader in self.invaders_group:
for obj in self.object:
pygame.sprite.spritecollide(invader, obj.blocks_group, True)
# Kiểm tra va chạm với shooter
if pygame.sprite.spritecollide(invader, self.shooter_group, False):
self.game_over()
return "lose"
# Boss collisions
for laser in self.shooter_group.sprite.lasers_group:
for boss in self.boss_group:
if laser.rect.colliderect(boss.rect):
laser.kill() # Remove the laser
boss.kill() # Remove the boss (or just damage it)
self.score += 200 # Add 200 points for hitting the boss
break
if self.boss_group.sprite:
boss = self.boss_group.sprite
# Kiểm tra va chạm giữa boss và các khối block
for obj in self.object:
pygame.sprite.spritecollide(boss, obj.blocks_group, True)
# Kiểm tra va chạm giữa boss và shooter
if pygame.sprite.spritecollide(boss, self.shooter_group, False):
#print("shooter hit")
self.lives = 0 # Trừ một mạng khi boss va chạm với shooter
if self.lives == 0:
self.game_over()
return "lose"
if self.boss_lasers_group:
for boss_laser in self.boss_lasers_group:
# Check collision between boss laser and shooter
if pygame.sprite.spritecollide(boss_laser, self.shooter_group, False):
boss_laser.kill()
self.lives -= 1
if self.lives == 0:
self.game_over()
return "lose"
# Boss lasers shouldn't pass through blocks
for obj in self.object:
if pygame.sprite.spritecollide(boss_laser, obj.blocks_group, True):
boss_laser.kill()
if self.selected_level_index == 4:
if len(self.boss_group) == 0:
return "win"
else: # Các ván thường
if len(self.invaders_group) == 0:
return "win"
return None
def game_over(self):
self.run = False
def reset(self):
self.run = True
self.lives = 3
self.shooter_group.sprite.reset()
self.invader_lasers_group.empty()
self.bonus_ship_group.empty()
self.object = self.create_object()
self.score = 0
if self.selected_level_index == 0:
self.invaders_group.empty()
self.create_invaders()
def invader_shoot_laser(self):
if self.invaders_group.sprites():
random_invader = random.choice(self.invaders_group.sprites())
laser_sprite = Laser(random_invader.rect.center, -6, self.screen_height)
self.invader_lasers_group.add(laser_sprite)
def boss_shoot_laser(self):
if self.boss_group.sprite: # Kiểm tra nếu boss còn sống
boss_position = self.boss_group.sprite.rect.center
boss_laser = BossLaser(boss_position, 1, self.screen_height) # Hướng bắn là -1
self.boss_lasers_group.add(boss_laser)
def draw_level(self, screen):
font_path = 'fonts/SVN-Determination Sans.otf'
font = pygame.font.Font(font_path, 20)
level_text = f"Level: {self.selected_level_index + 1}"
if self.selected_level_index == 0: # Level 1 shows invaders
text_surface = font.render(level_text, True, (255, 255, 255))
else: # Subsequent levels show only text
text_surface = font.render("", True, (255, 0, 0))
screen.blit(text_surface, (10, 10))
def update(self):
# Update all sprites in the game
self.shooter_group.update()
self.invaders_group.update(self.invader_direction)
self.boss_group.update() # Update the boss in Level 5
self.boss_lasers_group.update()
self.move_invaders()
self.create_bonus_ship()
self.check_for_collisions()
if self.selected_level_index == 4: # Chỉ gọi boss bắn đạn ở level 5
current_time = pygame.time.get_ticks()
if current_time - self.last_boss_shot > 1000: # 1000 ms = 1 giây
self.boss_shoot_laser()
self.last_boss_shot = current_time
def draw(self, screen):
# Draw all sprites on the screen
self.shooter_group.draw(screen)
self.invaders_group.draw(screen)
self.bonus_ship_group.draw(screen)
self.boss_lasers_group.draw(screen)
self.boss_group.draw(screen) # Draw the boss in level 5
for obj in self.object:
obj.blocks_group.draw(screen)
self.draw_level(screen)
def check_for_highscore(self):
if self.score > self.highscore:
self.highscore = self.score
self.update_user_highscore(self.username, self.selected_level_index,self.score)
def load_user_data(self):
try:
with open('user_data.json', 'r') as f:
return json.load(f)
except FileNotFoundError:
return {}
def save_user_data(self):
with open('user_data.json', 'w') as f:
json.dump(self.user_data, f, indent=4)
def get_user_highscore(self, username, level):
user_data = self.user_data.get(username, {})
user_level_data = user_data.get('levels', {})
return user_level_data.get(str(level), 0)
def update_user_highscore(self, username, level, new_score):
if username in self.user_data:
user_level_data = self.user_data[username].get('levels', {})
if str(level) in user_level_data:
if new_score > user_level_data[str(level)]:
user_level_data[str(level)] = new_score
else:
user_level_data[str(level)] = new_score
self.user_data[username]['levels'] = user_level_data
self.save_user_data()