Enhance Asteroids game with resizable window, WASD controls, particle effects, and improved ship graphics
This commit is contained in:
121
asteroids.py
121
asteroids.py
@@ -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,20 +192,46 @@ 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:
|
||||||
|
|||||||
Reference in New Issue
Block a user