-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
206 lines (169 loc) · 7.78 KB
/
main.py
File metadata and controls
206 lines (169 loc) · 7.78 KB
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
"""Asteroids Game - Main Entry Point."""
import pygame
import sys
from src.game.constants import (
SCREEN_WIDTH, SCREEN_HEIGHT, PLAYER_LIVES, MASTER_VOLUME, SHOW_LOADING_SCREEN,
SOUND_PATH_SHOOT, SOUND_PATH_EXPLOSION, SOUND_PATH_THRUST, SOUND_PATH_COLLISION,
SOUND_VOLUME_SHOOT, SOUND_VOLUME_EXPLOSION, SOUND_VOLUME_THRUST, SOUND_VOLUME_COLLISION
)
from src.game.states import GameState, reset_game, draw_lives, draw_game_over
from src.entities.player import Player
from src.entities.asteroid import Asteroid, AnimatedAsteroid
from src.entities.asteroidfield import AsteroidField
from src.entities.shot import Shot
from src.utils.sound import get_sound_manager
from src.utils.background import BackgroundManager
from src.utils.loading import LoadingScreen
from src.utils.asset_manager import asset_manager
from src.utils.graphics_manager import graphics_manager
def main():
"""Main game function."""
print("Starting Asteroids!")
print(f"Screen width: {SCREEN_WIDTH}")
print(f"Screen height: {SCREEN_HEIGHT}")
# Initialize pygame
pygame.init()
# Create the game window
GAMESCREEN = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Asteroids")
# Initialize graphics manager after display is set
graphics_manager.initialize()
# Initialize sound system
sound_manager = get_sound_manager()
sound_manager.set_master_volume(MASTER_VOLUME)
# Initialize background system (starts generation in background)
background_manager = BackgroundManager()
background_manager.initialize()
# Start asset preloading
print("Starting asset preloading...")
asset_loading_thread = asset_manager.preload_assets_async()
# Show loading screen if enabled
if SHOW_LOADING_SCREEN:
loading_screen = LoadingScreen(GAMESCREEN, background_manager)
clock = pygame.time.Clock()
print("Showing loading screen...")
# Loading screen loop
loading_done = False
while not loading_done:
# Handle events during loading
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE or event.key == pygame.K_ESCAPE:
# Only allow exit if assets are loaded
if asset_manager.is_loading_complete():
print("Loading screen completed by user")
loading_done = True
break
# Update and draw loading screen
loading_complete = loading_screen.update_and_draw()
pygame.display.flip()
clock.tick(60)
if loading_complete:
loading_done = True
print("Loading complete, starting game!")
# Load sound effects
sound_manager.load_sound("shoot", SOUND_PATH_SHOOT, SOUND_VOLUME_SHOOT)
sound_manager.load_sound("explosion", SOUND_PATH_EXPLOSION, SOUND_VOLUME_EXPLOSION)
sound_manager.load_sound("thrust", SOUND_PATH_THRUST, SOUND_VOLUME_THRUST)
sound_manager.load_sound("collision", SOUND_PATH_COLLISION, SOUND_VOLUME_COLLISION)
# Initialize font
pygame.font.init()
font = pygame.font.Font(None, 74) # Large font for game over
ui_font = pygame.font.Font(None, 36) # Smaller font for UI
# Create sprite groups
updatable = pygame.sprite.Group()
drawable = pygame.sprite.Group()
shots = pygame.sprite.Group()
asteroids = pygame.sprite.Group()
# Set the sprite groups to the class containers
Player.containers = updatable, drawable
Shot.containers = updatable, drawable, shots
Asteroid.containers = updatable, drawable, asteroids
AnimatedAsteroid.containers = updatable, drawable, asteroids
AsteroidField.containers = updatable
# Create the game objects
player = Player(x=SCREEN_WIDTH / 2, y=SCREEN_HEIGHT / 2)
asteroidfield = AsteroidField()
clock = pygame.time.Clock()
# Game state variables
game_state = GameState.PLAYING
lives = PLAYER_LIVES
# Main game loop
RUNGAME = True
while RUNGAME:
# Handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNGAME = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNGAME = False
elif event.key == pygame.K_SPACE and game_state == GameState.GAME_OVER:
# Restart the game
game_state = GameState.PLAYING
lives = PLAYER_LIVES
reset_game(player, asteroidfield, shots, asteroids)
elif event.key == pygame.K_b and game_state == GameState.PLAYING:
# Change background during gameplay
background_manager.regenerate_background()
elif event.key == pygame.K_g and game_state == GameState.PLAYING:
# Cycle through graphics modes
graphics_manager.cycle_mode()
dt = clock.tick(60) / 1000 # Amount of seconds between each loop
# Render background based on graphics mode
if graphics_manager.should_show_background_image():
background_manager.render(GAMESCREEN)
else:
# Fill with solid color based on graphics mode
bg_color = graphics_manager.get_background_color()
GAMESCREEN.fill(bg_color)
if game_state == GameState.PLAYING:
# Update the game objects
updatable.update(dt)
# Check for player-asteroid collision
for asteroid in asteroids:
if player.is_vulnerable() and player.collision(asteroid):
# Play collision sound
from src.utils.sound import play_sound
play_sound("collision")
lives -= 1
if lives <= 0:
game_state = GameState.GAME_OVER
else:
# Reset game but keep lives
reset_game(player, asteroidfield, shots, asteroids)
break
# Check for shot-asteroid collision
for shot in shots:
for asteroid in asteroids:
if shot.collision(asteroid):
shot.kill()
new_asteroids = asteroid.split()
# Add any new smaller asteroids to the game
if new_asteroids:
for new_asteroid in new_asteroids:
asteroids.add(new_asteroid)
updatable.add(new_asteroid)
drawable.add(new_asteroid)
break
# Render the sprites
for sprite in drawable:
sprite.draw(GAMESCREEN)
# Draw UI elements
draw_lives(GAMESCREEN, lives, ui_font)
# Draw graphics mode indicator
mode_text = f"Graphics: {graphics_manager.get_current_mode().value.upper()} (Press G to change)"
mode_surface = pygame.font.Font(None, 24).render(mode_text, True, (200, 200, 200))
GAMESCREEN.blit(mode_surface, (10, SCREEN_HEIGHT - 30))
elif game_state == GameState.GAME_OVER:
# Draw game over screen
draw_game_over(GAMESCREEN, font)
# Update the display
pygame.display.flip()
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()