-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame.py
397 lines (312 loc) · 13.5 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
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
import pygame
import os
import random
from DataConfig import *
# Initialize Pygame
pygame.init()
pygame.mixer.init() # Initialize mixer for music and sound effects
# Initialize Player and Item Class
from Player import Player
from Item import Item
# Setup display
pygame.display.set_icon(pygame.image.load('resources/appico.ico')
)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Michaels Abenteuer")
# Load images
bg_image = pygame.image.load(os.path.join(IMAGE_PATH, 'bg.jpeg')).convert()
bg_image = pygame.transform.scale(bg_image, (SCREEN_WIDTH, SCREEN_HEIGHT))
ts_bg_image = pygame.image.load(os.path.join(IMAGE_PATH, 'ts-bg.jpeg')).convert()
ts_bg_image = pygame.transform.scale(ts_bg_image, (SCREEN_WIDTH, SCREEN_HEIGHT))
# Load heart image for lives display
heart_image = pygame.image.load(os.path.join(IMAGE_PATH, 'heart.png')).convert_alpha()
heart_image = pygame.transform.scale(heart_image, (30, 30))
# Load background music
try:
pygame.mixer.music.load(os.path.join(SOUND_PATH, 'bg.mp3'))
pygame.mixer.music.play(-1) # Play the music in a loop
except pygame.error as e:
print(f"Error loading or playing background music: {e}")
# Load sound effects
try:
noice_sound = pygame.mixer.Sound(os.path.join(SFX_PATH, 'noice.mp3'))
game_over_sound = pygame.mixer.Sound(os.path.join(SFX_PATH, 'gvyeh.mp3'))
last_life_sound = pygame.mixer.Sound(os.path.join(SFX_PATH, 'last_life.mp3'))
except pygame.error as e:
print(f"Error loading 'noice.mp3' sound effect: {e}")
# Initialize player and groups
player = Player()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
items = pygame.sprite.Group()
# Flags
double_points_active = False
vgr_active = False
play_noice = False
last_noice_played_time = 0
last_life_text_displayed = False
collected100pts1up = False
daytime = True
# Chances
vodka_spawn_rate = 0
paulaner_spawn_rate = 0
bitburger_spawn_rate = 0
spawn_chance_1up = 0.000
apple_chance = 0.50
additional_powerup_chance = 0
# Milestones
last_score_milestone = 0
# Variables for "LAST LIFE" text flashing
last_life_flash_timer = 0
last_life_flash_color = RED
# Main game loop
clock = pygame.time.Clock()
score = 0
running = True
paused = False
font = pygame.font.SysFont(None, 36)
def render_text_with_outline(text, font, color, outline_color, pos):
text_surface = font.render(text, True, color)
outline_surface = font.render(text, True, outline_color)
text_rect = text_surface.get_rect(center=pos)
# Draw outline (shifted slightly)
screen.blit(outline_surface, (text_rect.x - 1, text_rect.y - 1))
screen.blit(outline_surface, (text_rect.x + 1, text_rect.y - 1))
screen.blit(outline_surface, (text_rect.x - 1, text_rect.y + 1))
screen.blit(outline_surface, (text_rect.x + 1, text_rect.y + 1))
# Draw main text
screen.blit(text_surface, text_rect)
# Function to convert screen to grayscale
def grayscale(surface):
arr = pygame.surfarray.pixels3d(surface)
arr = arr.dot([0.2989, 0.587, 0.114]) # Convert to grayscale using luminosity method
arr = arr.reshape((*arr.shape, 1)).repeat(3, axis=2)
return pygame.surfarray.make_surface(arr)
# Title screen loop
def show_title_screen():
flash_timer = 0
show_text = True
text_visible = True
show_title_screen = True
while show_title_screen:
for event in pygame.event.get():
if event.type == pygame.QUIT:
show_title_screen = False
running = False
elif event.type == pygame.KEYDOWN:
show_title_screen = False
# Draw title screen background
screen.blit(ts_bg_image, (0, 0))
# Draw game title
title_font = pygame.font.SysFont(None, 72)
title_text = title_font.render("Michaels Abenteuer", True, WHITE)
title_rect = title_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
screen.blit(title_text, title_rect)
# Draw creator's name
creator_font = pygame.font.SysFont(None, 24)
creator_text = creator_font.render("(c) Copy05 2019", True, WHITE)
creator_rect = creator_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT - 30))
screen.blit(creator_text, creator_rect)
# Flashing text "1 Credit. Press to play"
if text_visible:
flash_timer += 1
if flash_timer >= 0.5 * FPS: # Flash every 0.5 seconds
flash_timer = 0
show_text = not show_text
if show_text:
text = "1 Credit. Press to play"
pos = (SCREEN_WIDTH // 2, SCREEN_HEIGHT - 60)
render_text_with_outline(text, creator_font, YELLOW, BLACK, pos)
# Flip the display
pygame.display.flip()
# Cap the frame rate
clock.tick(FPS)
# Show Title Screen
show_title_screen()
# Game loop
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
paused = not paused # Toggle pause
if paused:
# Pause the music
pygame.mixer.music.pause()
# Draw background (grayscale)
screen.blit(grayscale(bg_image), (0, 0))
# Draw "Paused" text
paused_text = font.render("PAUSED", True, WHITE)
paused_rect = paused_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
screen.blit(paused_text, paused_rect)
# Draw the score below "Paused" text
score_text = font.render(f'Score: {score}', True, WHITE)
score_rect = score_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 40))
screen.blit(score_text, score_rect)
# Flip the display
pygame.display.flip()
# Cap the frame rate
clock.tick(FPS)
continue
# Unpause the music
pygame.mixer.music.unpause()
# Draw background
screen.blit(bg_image, (0, 0))
# FPS Counter [You can remove this in production]
# pygame.display.set_caption(f"Michaels Abenteuer | FPS: {int(clock.get_fps())}")
# Spawn new items
if len(items) < 10: # Limit the number of items on screen
item_types = ['beer', 'beer2', "beer3", 'vodka', 'beer4', 'apple', 'double_points', 'vgr', '1up']
probabilities = [0.49, 0.29, paulaner_spawn_rate, vodka_spawn_rate, bitburger_spawn_rate, apple_chance, 0.002 + additional_powerup_chance, 0.003 + additional_powerup_chance, spawn_chance_1up] # Example probabilities (49% beer, 39% beer2, 50% apple, 0.02% double points, 0.00% - 0.09% 1up)
item_type = random.choices(item_types, weights=probabilities)[0]
item = Item(item_type)
# Check for overlapping items
overlapping = pygame.sprite.spritecollide(item, items, False)
while overlapping: # Keep repositioning until no overlap
item.rect.x = random.randint(0, SCREEN_WIDTH - ITEM_WIDTH)
item.rect.y = random.randint(-SCREEN_HEIGHT, -ITEM_HEIGHT - ITEM_SPAWN_DISTANCE)
overlapping = pygame.sprite.spritecollide(item, items, False)
all_sprites.add(item)
items.add(item)
# Update
all_sprites.update()
# Check for collisions
hits = pygame.sprite.spritecollide(player, items, dokill=True) # Remove items on collision
for hit in hits:
if hit.item_type == 'beer':
if apple_chance < MAX_APPLE_CHANCE:
apple_chance += 0.001
score += 2 if double_points_active else 1
elif hit.item_type == 'beer2':
if apple_chance < MAX_APPLE_CHANCE:
apple_chance += 0.001
score += 4 if double_points_active else 2
elif hit.item_type == 'beer3':
if apple_chance < MAX_APPLE_CHANCE:
apple_chance += 0.001
score += 4 if double_points_active else 2
elif hit.item_type == 'vodka':
if apple_chance < MAX_APPLE_CHANCE:
apple_chance += 0.001
score += 8 if double_points_active else 4
elif hit.item_type == 'beer4':
if apple_chance < MAX_APPLE_CHANCE:
apple_chance += 0.001
score += 16 if double_points_active else 8
elif hit.item_type == 'apple':
if not vgr_active:
player.lose_life()
if player.lives == 1:
last_life_sound.play()
last_life_text_displayed = True
last_life_text_timer = 2 * FPS
score -= 2 if double_points_active else 1
else:
score += 2 if double_points_active else 1
elif hit.item_type == 'double_points':
# Activate double points
double_points_active = True
double_points_timer = DOUBLE_POINTS_TIMER * FPS # 10 seconds
elif hit.item_type == 'vgr':
# Activate double points
vgr_active = True
vgr_timer = VGR_TIMER * FPS # 10 seconds
elif hit.item_type == '1up':
player.lives += 1
spawn_chance_1up = 0.000
collected100pts1up = False
# Check if score contains "69" and play "noice.mp3"
if '69' in str(score):
current_time = pygame.time.get_ticks()
if not play_noice and current_time - last_noice_played_time > NOICE_COOLDOWN:
noice_sound.play()
play_noice = True
last_noice_played_time = current_time
else:
play_noice = False
# ------------------------------------------------------------------------
# MILESTONES (Infinitly):
# Increasse Speed and Apple Chance for every 100 score and Unlock more stuff
# ------------------------------------------------------------------------
if score // 100 > last_score_milestone:
apple_chance += 0.001
# Increasse Additional Power Up Chance by 0,01% Capped at 2%
if additional_powerup_chance < 0.02:
additional_powerup_chance += 0.001
last_score_milestone = score // 100
if player.lives < DEFAULT_LIFES:
spawn_chance_1up += UP_POINT_INCREASE # +0,1% Spawn Rate for 1up
if last_score_milestone == 1:
paulaner_spawn_rate = 0.30 # Paulaner Spawn Rate: 30%
apple_chance += 0.003
if last_score_milestone == 2:
vodka_spawn_rate = 0.25 # Vodka Spawn Rate: 25%
apple_chance += 0.004
if last_score_milestone == 5:
bitburger_spawn_rate = 0.22 # BitBurger Spawn Rate: 22%
# Switch Between Day and Night Time
if last_score_milestone % 9 == 0:
daytime = not daytime
if daytime:
bg_image = pygame.image.load(os.path.join(IMAGE_PATH, 'bg.jpeg')).convert()
else:
bg_image = pygame.image.load(os.path.join(IMAGE_PATH, 'bg-night.jpg')).convert()
bg_image = pygame.transform.scale(bg_image, (SCREEN_WIDTH, SCREEN_HEIGHT))
# Draw / render
all_sprites.draw(screen)
# Draw score
score_text = font.render(f'Score: {score}', True, WHITE)
screen.blit(score_text, (10, 10))
# Draw Apple Protection status
if vgr_active:
y_pos = 80 if double_points_active else 50
vgr_text = font.render(f'Invincibility: 0:{vgr_timer // FPS:02}', True, YELLOW)
screen.blit(vgr_text, (10, y_pos))
# Update VGR timer
vgr_timer -= 1
if vgr_timer <= 0:
vgr_active = False
# Draw Double Points status
if double_points_active:
double_points_text = font.render(f'Double Score: 0:{double_points_timer // FPS:02}', True, YELLOW)
screen.blit(double_points_text, (10, 50))
# Update double points timer
double_points_timer -= 1
if double_points_timer <= 0:
double_points_active = False
# Draw lives
for i in range(player.lives):
screen.blit(heart_image, (SCREEN_WIDTH - (i + 1) * 35, 10))
# Show the "LAST LIFE" Text at the center of the game to warn the user that it is their last life.
if last_life_text_displayed:
# Update the flash timer and toggle color if necessary
last_life_flash_timer += 1
if last_life_flash_timer >= 0.5 * FPS: # 0.5 seconds
last_life_flash_timer = 0
last_life_flash_color = YELLOW if last_life_flash_color == RED else RED
last_life_text = font.render("LAST LIFE", True, last_life_flash_color)
last_life_rect = last_life_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
screen.blit(last_life_text, last_life_rect)
last_life_text_timer -= 1
if last_life_text_timer <= 0:
last_life_text_displayed = False
# Check game over condition
if player.lives <= 0 or score < 0:
pygame.mixer.music.pause()
game_over_sound.play()
# Display game over text
game_over_text = font.render("GAME OVER", True, RED)
screen.blit(game_over_text, (SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2))
# Flip the display
pygame.display.flip()
# Wait for the sound effect to finish playing
pygame.time.wait(3000)
# Exit the game loop
running = False
# Flip the display
pygame.display.flip()
# Ensure program maintains a rate of FPS frames per second
clock.tick(FPS)
# Quit Pygame
pygame.quit()