import pygame import random import math pygame.init() WIDTH, HEIGHT = 900, 700 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Epic Shooter 2.0") clock = pygame.time.Clock() FPS = 60 # Colors WHITE = (255, 255, 255) BLACK = (0, 0, 0) PLAYER_COLOR = (50, 200, 255) ENEMY_COLOR = (255, 60, 60) BULLET_COLOR = (255, 220, 0) BG_COLOR = (20, 20, 40) font = pygame.font.SysFont("Arial", 28) # Game variables gravity = 0.4 player_speed = 5 bullet_speed = 12 enemy_spawn_time = 1500 # ms max_bullets = 5 # max bullets on screen at once recoil_force = 2 # amount of recoil applied # Weapon states weapon_state = "normal" # "spread", "rapid", "kaboom" last_shot = 0 rapid_fire_delay = 100 # in ms # Setup timers pygame.time.set_timer(pygame.USEREVENT, enemy_spawn_time) # Player class class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.Surface((50, 50), pygame.SRCALPHA) pygame.draw.circle(self.image, PLAYER_COLOR, (25, 25), 25) self.rect = self.image.get_rect(center=(WIDTH // 2, HEIGHT - 100)) self.vel = pygame.Vector2(0, 0) self.health = 3 def update(self): keys = pygame.key.get_pressed() self.vel.x = 0 self.vel.y = 0 if keys[pygame.K_a]: self.vel.x = -player_speed if keys[pygame.K_d]: self.vel.x = player_speed if keys[pygame.K_w]: self.vel.y = -player_speed if keys[pygame.K_s]: self.vel.y = player_speed self.rect.x += self.vel.x self.rect.y += self.vel.y # Keep inside screen self.rect.clamp_ip(screen.get_rect()) # Bullet class class Bullet(pygame.sprite.Sprite): def __init__(self, x, y, angle, speed=bullet_speed): super().__init__() self.image = pygame.Surface((10, 10), pygame.SRCALPHA) pygame.draw.circle(self.image, BULLET_COLOR, (5, 5), 5) self.rect = self.image.get_rect(center=(x, y)) self.speed = speed self.angle = angle self.vel = pygame.Vector2(math.cos(angle), math.sin(angle)) * self.speed def update(self): self.rect.x += self.vel.x self.rect.y += self.vel.y if not screen.get_rect().colliderect(self.rect): self.kill() # Enemy class class Enemy(pygame.sprite.Sprite): def __init__(self): super().__init__() size = random.randint(30, 50) self.image = pygame.Surface((size, size), pygame.SRCALPHA) pygame.draw.circle(self.image, ENEMY_COLOR, (size//2, size//2), size//2) self.rect = self.image.get_rect(center=(random.randint(0, WIDTH), -50)) self.speed = random.uniform(1, 3) self.health = 1 def update(self): self.rect.y += self.speed if self.rect.top > HEIGHT: self.kill() # Boss class class Boss(Enemy): def __init__(self): super().__init__() self.image = pygame.Surface((100, 100), pygame.SRCALPHA) pygame.draw.circle(self.image, (255, 0, 255), (50, 50), 50) self.rect = self.image.get_rect(center=(WIDTH // 2, -100)) self.speed = 0.5 self.health = 5 def update(self): self.rect.y += self.speed if self.rect.top > HEIGHT // 4: self.speed = 2 # start moving faster once it's on screen if self.rect.top > HEIGHT: self.kill() # PowerUp class class PowerUp(pygame.sprite.Sprite): def __init__(self, x, y, type): super().__init__() self.image = pygame.Surface((20, 20), pygame.SRCALPHA) self.type = type if type == "speed": pygame.draw.circle(self.image, (0, 255, 0), (10, 10), 10) elif type == "health": pygame.draw.circle(self.image, (255, 0, 0), (10, 10), 10) self.rect = self.image.get_rect(center=(x, y)) # Setup player = Player() player_group = pygame.sprite.GroupSingle(player) bullets = pygame.sprite.Group() enemies = pygame.sprite.Group() powerups = pygame.sprite.Group() score = 0 # Recoil effect def apply_recoil(player, direction): player.rect.x -= direction * recoil_force # Weapon Options: Spread, Rapid, Kaboom def shoot_weapon(player, now): global weapon_state, last_shot, rapid_fire_delay mx, my = pygame.mouse.get_pos() px, py = player.rect.center angle = math.atan2(my - py, mx - px) if weapon_state == "normal": # Normal shooting bullets.add(Bullet(px, py, angle)) elif weapon_state == "spread": # Spread shot spread = 0.25 for i in range(5): bullets.add(Bullet(px, py, angle + spread * (i - 2))) elif weapon_state == "rapid": # Rapid fire (faster shots) if now - last_shot > rapid_fire_delay: bullets.add(Bullet(px, py, angle)) last_shot = now elif weapon_state == "kaboom": # Kaboom shot (explosion) explosion = Bullet(px, py, angle, speed=bullet_speed*2) explosion.image.fill((255, 0, 0)) # Make it red for explosion bullets.add(explosion) # Draw glowing effect def draw_glow(surface, pos, color, radius): glow = pygame.Surface((radius*2, radius*2), pygame.SRCALPHA) pygame.draw.circle(glow, color, (radius, radius), radius) glow.set_alpha(80) surface.blit(glow, (pos[0] - radius, pos[1] - radius), special_flags=pygame.BLEND_ADD) # Main loop running = True while running: dt = clock.tick(FPS) now = pygame.time.get_ticks() for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.USEREVENT: if score >= 30: enemies.add(Boss()) else: enemies.add(Enemy()) if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: # Left click apply_recoil(player, 1) shoot_weapon(player, now) if event.type == pygame.KEYDOWN: if event.key == pygame.K_1: weapon_state = "normal" # Normal weapon elif event.key == pygame.K_2: weapon_state = "spread" # Spread shot elif event.key == pygame.K_3: weapon_state = "rapid" # Rapid fire # Update player_group.update() bullets.update() enemies.update() powerups.update() # Collisions for bullet in bullets: hit = pygame.sprite.spritecollideany(bullet, enemies) if hit: bullet.kill() hit.kill() score += 1 if pygame.sprite.spritecollideany(player, enemies): player.health -= 1 if player.health <= 0: running = False # Powerups collision for powerup in pygame.sprite.spritecollide(player, powerups, dokill=True): if powerup.type == "speed": player_speed += 1 elif powerup.type == "health": player.health += 1 # Draw screen.fill(BG_COLOR) # Background fake glow for e in enemies: draw_glow(screen, e.rect.center, ENEMY_COLOR, 30) for b in bullets: draw_glow(screen, b.rect.center, BULLET_COLOR, 15) draw_glow(screen, player.rect.center, PLAYER_COLOR, 40) player_group.draw(screen) bullets.draw(screen) enemies.draw(screen) powerups.draw(screen) # Display score and health text = font.render(f"Score: {score} Health: {player.health}", True, WHITE) screen.blit(text, (10, 10)) pygame.display.flip() pygame.quit()