Enhance Asteroids game with resizable window, WASD controls, particle effects, and improved ship graphics

This commit is contained in:
mordag
2026-01-16 08:14:55 -05:00
parent b1b1d43309
commit f3492a66ca

View File

@@ -8,7 +8,7 @@ pygame.init()
# Set up the display # Set up the display
width, height = 800, 600 width, height = 800, 600
screen = pygame.display.set_mode((width, height)) screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
pygame.display.set_caption("Asteroids") pygame.display.set_caption("Asteroids")
# Colors # Colors
@@ -17,7 +17,7 @@ BLACK = (0, 0, 0)
# Ship # Ship
ship_size = 20 ship_size = 20
ship_pos = [width // 2, height // 2] ship_pos = [float(width // 2), float(height // 2)]
ship_angle = 0 ship_angle = 0
ship_speed = 0 ship_speed = 0
@@ -29,6 +29,9 @@ bullet_speed = 10
asteroids = [] asteroids = []
asteroid_count = 10 asteroid_count = 10
# Particles
particles = []
# Score # Score
score = 0 score = 0
font = pygame.font.Font(None, 36) font = pygame.font.Font(None, 36)
@@ -43,7 +46,37 @@ def create_asteroid():
speed = random.uniform(0.5, 2) speed = random.uniform(0.5, 2)
angle = random.uniform(0, 2 * math.pi) angle = random.uniform(0, 2 * math.pi)
sides = random.choice([5, 6]) sides = random.choice([5, 6])
return {"pos": [x, y], "size": size, "speed": speed, "angle": angle, "sides": sides} return {"pos": [float(x), float(y)], "size": size, "speed": speed, "angle": angle, "sides": sides}
def create_explosion(x, y, color=WHITE):
for _ in range(20):
angle = random.uniform(0, 2 * math.pi)
speed = random.uniform(1, 5)
size = random.randint(1, 4)
lifetime = random.randint(20, 40)
particles.append({
"pos": [float(x), float(y)],
"vel": [math.cos(angle) * speed, math.sin(angle) * speed],
"size": size,
"lifetime": lifetime,
"max_lifetime": lifetime,
"color": color
})
def create_thrust_particles():
if ship_speed > 0:
for _ in range(3):
angle = ship_angle + math.pi + random.uniform(-0.5, 0.5)
speed = random.uniform(2, 4)
particles.append({
"pos": [ship_pos[0] - math.cos(ship_angle) * ship_size,
ship_pos[1] + math.sin(ship_angle) * ship_size],
"vel": [math.cos(angle) * speed, math.sin(angle) * speed],
"size": random.randint(2, 3),
"lifetime": random.randint(10, 20),
"max_lifetime": random.randint(10, 20),
"color": (255, 165, 0)
})
def draw_polygon(surface, color, pos, size, sides, angle=0): def draw_polygon(surface, color, pos, size, sides, angle=0):
points = [] points = []
@@ -66,6 +99,9 @@ while True:
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
pygame.quit() pygame.quit()
sys.exit() sys.exit()
elif event.type == pygame.VIDEORESIZE:
width, height = event.w, event.h
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
elif event.type == pygame.KEYDOWN: elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q or event.key == pygame.K_ESCAPE: if event.key == pygame.K_q or event.key == pygame.K_ESCAPE:
pygame.quit() pygame.quit()
@@ -76,12 +112,14 @@ while True:
if not game_over: if not game_over:
# Ship movement # Ship movement
keys = pygame.key.get_pressed() keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]: if keys[pygame.K_LEFT] or keys[pygame.K_a]:
ship_angle += 0.1 ship_angle += 0.1
if keys[pygame.K_RIGHT]: if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
ship_angle -= 0.1 ship_angle -= 0.1
if keys[pygame.K_UP]: if keys[pygame.K_UP] or keys[pygame.K_w]:
ship_speed = min(ship_speed + 0.1, 5) ship_speed = min(ship_speed + 0.1, 5)
elif keys[pygame.K_s]:
ship_speed = max(ship_speed - 0.15, 0)
else: else:
ship_speed = max(ship_speed - 0.05, 0) ship_speed = max(ship_speed - 0.05, 0)
@@ -89,8 +127,15 @@ while True:
ship_pos[1] -= math.sin(ship_angle) * ship_speed ship_pos[1] -= math.sin(ship_angle) * ship_speed
# Wrap ship around screen # Wrap ship around screen
ship_pos[0] %= width if ship_pos[0] < 0:
ship_pos[1] %= height ship_pos[0] += width
elif ship_pos[0] > width:
ship_pos[0] -= width
if ship_pos[1] < 0:
ship_pos[1] += height
elif ship_pos[1] > height:
ship_pos[1] -= height
# Update bullets # Update bullets
for bullet in bullets[:]: for bullet in bullets[:]:
@@ -99,24 +144,44 @@ while True:
if bullet[0] < 0 or bullet[0] > width or bullet[1] < 0 or bullet[1] > height: if bullet[0] < 0 or bullet[0] > width or bullet[1] < 0 or bullet[1] > height:
bullets.remove(bullet) bullets.remove(bullet)
# Update particles
for particle in particles[:]:
particle["pos"][0] += particle["vel"][0]
particle["pos"][1] += particle["vel"][1]
particle["lifetime"] -= 1
if particle["lifetime"] <= 0:
particles.remove(particle)
# Create thrust particles
create_thrust_particles()
# Update asteroids # Update asteroids
for asteroid in asteroids[:]: for asteroid in asteroids[:]:
asteroid["pos"][0] += math.cos(asteroid["angle"]) * asteroid["speed"] asteroid["pos"][0] += math.cos(asteroid["angle"]) * asteroid["speed"]
asteroid["pos"][1] += math.sin(asteroid["angle"]) * asteroid["speed"] asteroid["pos"][1] += math.sin(asteroid["angle"]) * asteroid["speed"]
# Wrap asteroids around screen # Wrap asteroids around screen
asteroid["pos"][0] %= width if asteroid["pos"][0] < 0:
asteroid["pos"][1] %= height asteroid["pos"][0] += width
elif asteroid["pos"][0] > width:
asteroid["pos"][0] -= width
if asteroid["pos"][1] < 0:
asteroid["pos"][1] += height
elif asteroid["pos"][1] > height:
asteroid["pos"][1] -= height
# Check collision with ship # Check collision with ship
if (abs(asteroid["pos"][0] - ship_pos[0]) < asteroid["size"] and if (abs(asteroid["pos"][0] - ship_pos[0]) < asteroid["size"] and
abs(asteroid["pos"][1] - ship_pos[1]) < asteroid["size"]): abs(asteroid["pos"][1] - ship_pos[1]) < asteroid["size"]):
create_explosion(ship_pos[0], ship_pos[1], (255, 0, 0))
game_over = True game_over = True
# Check collision with bullets # Check collision with bullets
for bullet in bullets[:]: for bullet in bullets[:]:
if (abs(asteroid["pos"][0] - bullet[0]) < asteroid["size"] and if (abs(asteroid["pos"][0] - bullet[0]) < asteroid["size"] and
abs(asteroid["pos"][1] - bullet[1]) < asteroid["size"]): abs(asteroid["pos"][1] - bullet[1]) < asteroid["size"]):
create_explosion(asteroid["pos"][0], asteroid["pos"][1])
asteroids.remove(asteroid) asteroids.remove(asteroid)
bullets.remove(bullet) bullets.remove(bullet)
score += 1 score += 1
@@ -127,21 +192,47 @@ while True:
screen.fill(BLACK) screen.fill(BLACK)
if not game_over: if not game_over:
# Draw ship # Draw ship with better design
# Main body
points = [ points = [
(ship_pos[0] + math.cos(ship_angle) * ship_size, (ship_pos[0] + math.cos(ship_angle) * ship_size,
ship_pos[1] - math.sin(ship_angle) * ship_size), ship_pos[1] - math.sin(ship_angle) * ship_size),
(ship_pos[0] + math.cos(ship_angle + 2.6) * ship_size, (ship_pos[0] + math.cos(ship_angle + 2.5) * ship_size * 0.7,
ship_pos[1] - math.sin(ship_angle + 2.6) * ship_size), ship_pos[1] - math.sin(ship_angle + 2.5) * ship_size * 0.7),
(ship_pos[0] + math.cos(ship_angle - 2.6) * ship_size, (ship_pos[0] + math.cos(ship_angle + 3.14) * ship_size * 0.3,
ship_pos[1] - math.sin(ship_angle - 2.6) * ship_size), ship_pos[1] - math.sin(ship_angle + 3.14) * ship_size * 0.3),
(ship_pos[0] + math.cos(ship_angle - 2.5) * ship_size * 0.7,
ship_pos[1] - math.sin(ship_angle - 2.5) * ship_size * 0.7),
] ]
pygame.draw.polygon(screen, WHITE, points, 2) pygame.draw.polygon(screen, WHITE, points, 2)
# Cockpit
cockpit_pos = (
ship_pos[0] + math.cos(ship_angle) * ship_size * 0.3,
ship_pos[1] - math.sin(ship_angle) * ship_size * 0.3
)
pygame.draw.circle(screen, WHITE, (int(cockpit_pos[0]), int(cockpit_pos[1])), 3)
# Engine glow when thrusting
if ship_speed > 0:
engine_pos = (
ship_pos[0] - math.cos(ship_angle) * ship_size * 0.8,
ship_pos[1] + math.sin(ship_angle) * ship_size * 0.8
)
pygame.draw.circle(screen, (255, 165, 0), (int(engine_pos[0]), int(engine_pos[1])), 4)
# Draw bullets # Draw bullets
for bullet in bullets: for bullet in bullets:
pygame.draw.circle(screen, WHITE, (int(bullet[0]), int(bullet[1])), 2) pygame.draw.circle(screen, WHITE, (int(bullet[0]), int(bullet[1])), 2)
# Draw particles
for particle in particles:
alpha = particle["lifetime"] / particle["max_lifetime"]
color = tuple(max(0, min(255, int(c * alpha))) for c in particle["color"])
pygame.draw.circle(screen, color,
(int(particle["pos"][0]), int(particle["pos"][1])),
particle["size"])
# Draw asteroids # Draw asteroids
for asteroid in asteroids: for asteroid in asteroids:
draw_polygon(screen, WHITE, asteroid["pos"], asteroid["size"], asteroid["sides"]) draw_polygon(screen, WHITE, asteroid["pos"], asteroid["size"], asteroid["sides"])