0% found this document useful (0 votes)
19 views21 pages

Pygame Millennium Mission Game Code

The document is a Python script for a game developed using Pygame, featuring various game elements such as sound generation, player controls, and visual effects. It includes configurations for graphics, audio, game states, and helper classes for objects like bullets, coins, and explosions. The game aims to provide an engaging experience with rich visuals and sound effects while managing game mechanics like scoring and player health.

Uploaded by

Kannan s
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views21 pages

Pygame Millennium Mission Game Code

The document is a Python script for a game developed using Pygame, featuring various game elements such as sound generation, player controls, and visual effects. It includes configurations for graphics, audio, game states, and helper classes for objects like bullets, coins, and explosions. The game aims to provide an engaging experience with rich visuals and sound effects while managing game mechanics like scoring and player health.

Uploaded by

Kannan s
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

import pygame

import random
import math
import array
from collections import deque

# --- CONFIGURATION & CONSTANTS ---


[Link]()
try:
# Initialize audio mixer
[Link](frequency=44100, size=-16, channels=1, buffer=512)
except:
print("Audio init failed.")

WIDTH, HEIGHT = 480, 640


screen = [Link].set_mode((WIDTH, HEIGHT))
[Link].set_caption('Millennium Mission - Ultimate Mouse Control')

# Expanded Palette (Richer colors for a visual boost)


C_BLACK = (5, 5, 15) # Very Dark Background
C_WHITE = (255, 255, 255)
C_RED = (255, 70, 70) # HP color
C_GREEN = (100, 255, 100) # Enemy color
C_BLUE = (100, 180, 255) # Player color
C_YELLOW = (255, 255, 50) # Warning/Ace
C_ORANGE = (255, 150, 0)
C_PURPLE = (200, 100, 255) # Shield Color
C_MAGENTA = (255, 50, 200) # Auto-Aim/Nuke
C_GOLD = (255, 215, 50) # Money/Coin
C_DARK_GREY = (20, 20, 40) # HUD background
C_LIGHT_GREY = (80, 80, 95)
C_HUD_BORDER = (150, 150, 180)

# Game Settings
CLOCK = [Link]()
FPS = 60
MAX_LIFE = 3.0
SHIELD_DURATION = FPS * 5 # 5 seconds shield
NUKE_SCORE_GAIN = 10

# States
STATE_MENU = 0
STATE_PLAYING = 1
STATE_PAUSE = 2 # New Pause State
STATE_SHOP = 3
STATE_GAMEOVER = 4
STATE_NO_AMMO = 5

# Firing Settings
AUTO_FIRE_DELAY = 20 # Frames to wait before auto-fire starts
RAPID_FIRE_INTERVAL = 10 # 6 bullets per second (60/10)
DOUBLE_CLICK_TIME = 300 # milliseconds

# Fonts
try:
font_sm = [Link]('Inter', 18)
font_md = [Link]('Inter', 24, bold=True)
font_lg = [Link]('Inter', 40, bold=True)
font_xl = [Link]('Inter', 60, bold=True)
except:
font_sm = [Link](None, 24)
font_md = [Link](None, 32)
font_lg = [Link](None, 50)
font_xl = [Link](None, 70)

# --- PROCEDURAL SOUND GENERATOR ---


class SoundGenerator:
def __init__(self):
[Link] = {}
try:
self.create_sounds()
[Link] = True
except:
print("Sound generation failed.")
[Link] = False

def create_square_wave(self, frequency, duration, volume=0.5):


n_samples = int(duration * 44100)
buf = [Link]('h', [0] * n_samples)
if frequency == 0: return [Link](buffer=buf)
period = 44100 // frequency
for i in range(n_samples):
value = 32767 if (i // period) % 2 == 0 else -32768
decay = 1.0 - (i / n_samples)
buf[i] = int(value * volume * decay)
return [Link](buffer=buf)

def create_noise(self, duration, volume=0.5):


n_samples = int(duration * 44100)
buf = [Link]('h', [0] * n_samples)
for i in range(n_samples):
value = [Link](-32768, 32767)
decay = 1.0 - (i / n_samples)
buf[i] = int(value * volume * decay)
return [Link](buffer=buf)

def create_sounds(self):
[Link]['shoot'] = self.create_square_wave(880, 0.05, 0.2)
[Link]['explosion'] = self.create_noise(0.2, 0.3)
[Link]['coin'] = self.create_square_wave(1500, 0.05, 0.15)
[Link]['powerup'] = self.create_square_wave(600, 0.1, 0.2)
[Link]['hit'] = self.create_square_wave(200, 0.05, 0.3)

def play(self, name):


if [Link] and name in [Link]:
[Link][name].play()

SOUNDS = SoundGenerator()

# --- GLOBAL VARIABLES ---


game_state = STATE_MENU
stage = 1
score = 0
money = 0
bullets_left = 100
score_goal = 50
high_score = 0
life_float = MAX_LIFE
last_rewards = {"ammo_gained": 0, "health_bonus": 0}
last_click_time = 0 # For double click detection

# Lists
ship = None
bullets = []
enemies = []
explosions = []
coins = []
floating_texts = []
powerups = []
particles = []
starfield_layers = [] # For parallax effect

spawn_timer = 0

# --- HELPER CLASSES (Star, Particle, FloatingText, Button, Explosion, GameObject,


Coin, Bullet, Enemy, PowerUp) ---

class Star:
def __init__(self, size_layer):
# Store as floats to maintain smooth movement calculations
self.x = float([Link](0, WIDTH))
self.y = float([Link](0, HEIGHT))
[Link] = size_layer
[Link] = [Link] * 0.8
[Link] = C_WHITE if [Link] == 3 else C_LIGHT_GREY

def update(self):
self.y += [Link]
if self.y > HEIGHT:
self.y = 0.0
self.x = float([Link](0, WIDTH))

def draw(self, surface):


# *** FIX: Convert coordinates to integer before drawing ***
draw_x = int(self.x)
draw_y = int(self.y)

if [Link] == 3:
[Link](surface, [Link], (draw_x, draw_y), 1)
elif [Link] == 2:
[Link](surface, [Link], (draw_x, draw_y), (draw_x, draw_y
+ 1))
else:
# set_at requires integer coordinates
surface.set_at((draw_x, draw_y), [Link])

class Particle:
def __init__(self, x, y, color, size, life, speed_y=0):
# Store positions as floats
self.x = float(x)
self.y = float(y)
[Link] = color
[Link] = size
[Link] = life
self.max_life = life
self.speed_y = float(speed_y)
self.speed_x = [Link](-0.5, 0.5)
def update(self):
self.x += self.speed_x
self.y += self.speed_y
[Link] -= 1
[Link] *= 0.95

def draw(self, surface):


if [Link] > 0 and [Link] > 0.5:
alpha = int(255 * ([Link] / self.max_life))
s = [Link]((int([Link])*2, int([Link])*2),
[Link])
[Link](s, (*[Link], alpha), (int([Link]),
int([Link])), int([Link]))
# Use int() for blitting coordinates
[Link](s, (int(self.x - [Link]), int(self.y - [Link])))

class FloatingText:
def __init__(self, x, y, text, color, duration=60):
# Store position as float for smooth scrolling
self.x = float(x)
self.y = float(y)
[Link] = text
[Link] = color
[Link] = duration

def update(self):
self.y -= 1.0 # Use float movement
[Link] -= 1

def draw(self, surface):


if [Link] > 0:
alpha = min(255, int(255 * ([Link] / 20)))
txt_surf = font_sm.render([Link], True, [Link])
txt_surf.set_alpha(alpha)
# Use int() for blitting coordinates
[Link](txt_surf, (int(self.x), int(self.y)))

class Button:
def __init__(self, x, y, w, h, text, color, text_color=C_WHITE, cost=None):
[Link] = [Link](x, y, w, h)
[Link] = text
[Link] = color
self.text_color = text_color
[Link] = cost
[Link] = True

def draw(self, surface):


col = [Link] if [Link] else C_DARK_GREY

# Draw a custom button with shadow/gradient effect


[Link](surface, (col[0]//2, col[1]//2, col[2]//2),
[Link](0, 4), border_radius=8) # Shadow
[Link](surface, col, [Link], border_radius=8)
[Link](surface, C_WHITE, [Link], 2, border_radius=8)

txt_surf = font_md.render([Link], True, self.text_color)


txt_rect = txt_surf.get_rect(center=[Link])
[Link](txt_surf, txt_rect)
if [Link] is not None:
cost_txt = f"${[Link]}"
cost_surf = font_sm.render(cost_txt, True, C_GOLD)
[Link](cost_surf, ([Link] + 10, [Link] - 10))

def is_clicked(self, pos):


return [Link] and [Link](pos)

class Explosion:
def __init__(self, pos, size=40, color=C_ORANGE):
[Link] = pos
self.max_size = size
[Link] = 5
[Link] = True
[Link] = color
[Link]('explosion')
# Create larger, more dramatic particles
for _ in range(12):
[Link](Particle(pos[0], pos[1], color, [Link](4, 8),
40, [Link](-3, 3)))

def draw(self, surface):


if [Link] < self.max_size:
# Outer white shockwave
[Link](surface, C_WHITE, [Link], [Link], 1)

# Inner core (fading)


alpha = max(0, 255 - int(255 * ([Link] / self.max_size)))
s = [Link](([Link] * 2, [Link] * 2), [Link])
[Link](s, (*[Link], alpha), ([Link], [Link]),
[Link])
[Link](s, ([Link][0] - [Link], [Link][1] - [Link]))

[Link] += 4
else:
[Link] = False

class GameObject:
def __init__(self, x, y, color):
[Link] = [Link](x, y, 0, 0)
[Link] = color

def draw_glow(self, surface, radius, color, strength=50):


"""Draws a soft, transparent glow effect."""
s = [Link]((radius*2, radius*2), [Link])
[Link](s, (*color, strength), (radius, radius), radius)
[Link](s, ([Link] - radius, [Link] - radius))

class Coin(GameObject):
def __init__(self, x, y):
super().__init__(x, y, C_GOLD)
[Link] = [Link](x, y, 15, 15)
[Link] = 0
self.exact_y = float(y) # Store vertical position as float

def update(self):
self.exact_y += 3.0
[Link].y = int(self.exact_y) # Update rect position with integer
[Link] = ([Link] + 15) % 360 # Faster spin

def draw(self, surface):


scale_factor = 1.0 + ([Link].y / HEIGHT) * 0.5
size = int(15 * scale_factor)

self.draw_glow(surface, size, C_GOLD)

# 3D Coin effect (ellipse width changes based on angle)


width = (size//2) * [Link]([Link]([Link]))
r_3d = [Link](0,0, (size//2) + abs(width), size)
r_3d.center = [Link]

[Link](surface, C_GOLD, r_3d)


[Link](surface, C_WHITE, r_3d, 1)

# Inner $ symbol
txt = font_sm.render("$", True, C_ORANGE)
[Link](txt, ([Link] - 5, [Link] - 10))

class Bullet(GameObject):
def __init__(self, x, y, is_wingman=False, target=None, is_auto_aim=False):
col = C_MAGENTA if is_auto_aim else (C_ORANGE if is_wingman else C_RED)
super().__init__(x, y, col)
[Link] = [Link](x, y, 4, 12)
[Link] = 14.0 if is_auto_aim else 12.0
self.is_auto_aim = is_auto_aim
self.exact_x = float(x)
self.exact_y = float(y)

# Tracing/Targeting Logic
if target:
tx, ty = target
dx = float(tx) - self.exact_x
dy = float(ty) - self.exact_y
dist = [Link](dx, dy)
if dist > 0:
[Link] = (dx / dist) * [Link]
[Link] = (dy / dist) * [Link]
else:
[Link] = 0.0; [Link] = -[Link]
else:
[Link] = 0.0; [Link] = -[Link]

if not is_wingman:
[Link]('shoot')

def update(self):
self.exact_x += [Link]
self.exact_y += [Link]
# Convert to integer for the rect position
[Link] = int(self.exact_x)
[Link] = int(self.exact_y)

# Add a light trail effect


[Link](Particle([Link], [Link], [Link],
1, 10))
def draw(self, surface):
self.draw_glow(surface, 8, [Link], strength=80)
[Link](surface, [Link], [Link], border_radius=2)
[Link](surface, C_WHITE, [Link](-2, -2))

class Ship(GameObject):
def __init__(self):
super().__init__(WIDTH // 2, HEIGHT - 60, C_BLUE)
[Link] = [Link](0, 0, 30, 40)
[Link] = (WIDTH // 2, HEIGHT - 60)

self.has_wingman = False
self.auto_aim_timer = 0
self.fire_held_frames = 0
self.fire_cooldown = 0
self.muzzle_flash_timer = 0

# New Shield/Nuke Properties


self.has_shield = False
self.shield_active = False
self.shield_timer = 0
self.has_nuke = False
self.nuke_count = 0

def draw(self, surface):


color = C_MAGENTA if self.auto_aim_timer > 0 else C_BLUE

# Draw Shield if active


if self.shield_active:
radius = 40 + (self.shield_timer % 10 // 5) * 2 # Pulsing effect
self.draw_glow(surface, radius + 20, C_PURPLE, strength=40)
[Link](surface, C_PURPLE, [Link], radius, 3)
[Link](surface, C_WHITE, [Link], radius // 2, 1)

dark_color = (max(0, color[0]-70), max(0, color[1]-70), max(0, color[2]-


70))

# Engine Particles (More dramatic exhaust)


for offset in [-6, 6]:
if [Link]() < 0.9:
# Use faster speed_y to simulate thrust
[Link](Particle([Link] + offset,
[Link] + 5, C_ORANGE, [Link](3,5), 15, [Link](2.5, 5)))

# Muzzle Flash
if self.muzzle_flash_timer > 0:
for offset in [-10, 10]:
[Link](surface, C_WHITE, ([Link] + offset,
[Link]), [Link](3, 6))
self.muzzle_flash_timer -= 1

# Glow Effect
self.draw_glow(surface, 40, color)

# Ship Body (Draw shaded sections for 3D feel)


# Left wing
p_l1 = ([Link], [Link])
p_l2 = ([Link] - 5, [Link] + 10)
p_l3 = ([Link], [Link] + 15)
[Link](surface, dark_color, [p_l1, p_l2, p_l3])

# Right wing
p_r1 = ([Link], [Link])
p_r2 = ([Link] + 5, [Link] + 10)
p_r3 = ([Link], [Link] + 15)
[Link](surface, color, [p_r1, p_r2, p_r3])

# Main body/cockpit
p_main = [([Link] - 5, [Link]), ([Link] + 5,
[Link]), ([Link] + 5, [Link]), ([Link] - 5,
[Link])]
[Link](surface, C_LIGHT_GREY, p_main)

# Cockpit (Glass)
[Link](surface, C_WHITE, ([Link] - 3, [Link] +
5, 6, 8), border_radius=1)

if self.has_wingman:
# Draw wingmen as smaller triangles
for offset in [-50, 50]:
wx = [Link] + offset
wy = [Link] + 5
[Link](surface, C_GREEN, [(wx, wy-8), (wx-4, wy+4),
(wx+4, wy+4)])

class Enemy(GameObject):
def __init__(self, is_boss=False):
self.is_boss = is_boss
size = 80 if is_boss else 30
col = C_RED if is_boss else C_GREEN

x_pos = WIDTH // 2 if is_boss else [Link](20, WIDTH-20)


y_pos = -80 if is_boss else -40

super().__init__(x_pos, y_pos, col)


self.base_size = size
[Link] = [Link](0, 0, size, size)
[Link] = (x_pos, y_pos)
self.exact_y = float(y_pos) # Store vertical position as float

self.can_dodge = False
if not is_boss and [Link]() < 0.08: # Increased dodge chance for
challenge
self.can_dodge = True
[Link] = C_YELLOW

if is_boss:
[Link] = 50 + (stage * 15)
self.max_hp = [Link]
[Link] = 1.0
self.move_dir = 1
else:
[Link] = 1 + (stage // 3)
self.max_hp = [Link]
[Link] = 1.0 + (stage * 0.3)

def update(self, bullets_list):


if self.is_boss:
if [Link] < 50:
self.exact_y += 2.0
[Link].y = int(self.exact_y)
else:
[Link].x += int([Link] * self.move_dir)
if [Link] > WIDTH or [Link] < 0:
self.move_dir *= -1
else:
self.exact_y += [Link]
[Link].y = int(self.exact_y)

# DODGE LOGIC
if self.can_dodge:
for b in bullets_list:
# Check if bullet is approaching and is within a narrow
horizontal band
if [Link] < [Link] and ([Link] -
[Link]) < 80:
if abs([Link] - [Link]) < 5:
dodge_dir = 3 if [Link] < [Link]
else -3
[Link].x += dodge_dir
[Link](Particle([Link],
[Link], C_YELLOW, 2, 5))

# Perspective Scaling
scale_factor = 1.0 + ([Link].y / HEIGHT) * 0.4 # Reduced scale factor
for more controlled perspective
new_size = int(self.base_size * scale_factor)
[Link] = new_size
[Link] = new_size

def draw(self, surface):


current_size = [Link]
dark_color = (max(0, [Link][0]-70), max(0, [Link][1]-70), max(0,
[Link][2]-70))

self.draw_glow(surface, current_size // 2 + 10, [Link], strength=40)

if self.is_boss:
r = [Link]
[Link](surface, dark_color, [Link](-10, -10),
border_radius=5)
[Link](surface, [Link], r, 2, border_radius=5)

# HP Bar
hp_rect = [Link]([Link], [Link] - 15, [Link], 5)
[Link](surface, C_DARK_GREY, hp_rect)
fill = ([Link] / self.max_hp) * [Link]
[Link](surface, C_RED, (hp_rect.left, hp_rect.top,
int(fill), 5))
else:
r = [Link]
# Enemy is a flying saucer/triangle
p1 = ([Link], [Link])
p2 = ([Link], [Link])
p3 = ([Link], [Link])
p4 = ([Link], [Link])
[Link](surface, dark_color, [p1, p2, p3])
[Link](surface, [Link], [p1, p3, p4])

if self.can_dodge:
[Link](surface, C_YELLOW, ([Link], [Link] - 5),
4)

class PowerUp(GameObject):
def __init__(self, x, y):
# Slightly adjusted weights for powerups
roll = [Link](1, 100)
if roll >= 95:
[Link] = 'FIRE_ASSIST'
col = C_MAGENTA
elif roll >= 70:
[Link] = 'LIFE'
col = C_GREEN
else:
[Link] = 'COIN_MAGNET'
col = C_BLUE # New powerup color

super().__init__(x, y, col)
[Link] = [Link](x, y, 20, 20)
self.initial_y = float(y)
self.exact_y = float(y)
self.sine_offset = [Link](0, [Link] * 2) # Random offset for wave
effect

def update(self):
# Sine wave movement for eye-catching movement
self.exact_y += 1.5
[Link].y = int(self.exact_y)
[Link].x += int([Link]([Link].get_ticks() * 0.005 +
self.sine_offset) * 0.5)

def draw(self, surface):


self.draw_glow(surface, 15, [Link])
s = [Link]([Link].get_ticks() * 0.01) * 5
r = [Link]()
r.inflate_ip(int(s), int(s)) # Ensure inflation uses integers
[Link](surface, [Link], r, border_radius=5)
[Link](surface, C_WHITE, r, 2, border_radius=5)

initial = ""
if [Link] == 'FIRE_ASSIST': initial = "A"
elif [Link] == 'LIFE': initial = "+"
elif [Link] == 'COIN_MAGNET': initial = "M"

txt = font_md.render(initial, True, C_WHITE)


[Link](txt, ([Link].x + 5, [Link].y - 2))

# --- GAME FUNCTIONS ---

def init_starfield():
"""Initializes multiple layers of stars for a parallax effect."""
global starfield_layers
starfield_layers = []
# Layer 1: Slow (far)
starfield_layers.append([Star(1) for _ in range(150)])
# Layer 2: Medium
starfield_layers.append([Star(2) for _ in range(100)])
# Layer 3: Fast (near)
starfield_layers.append([Star(3) for _ in range(50)])

def draw_starfield(surface):
"""Updates and draws the parallax starfield."""
for layer in starfield_layers:
for star in layer:
[Link]()
[Link](surface)

def init_game():
global ship, bullets, enemies, explosions, coins, powerups, score, money,
bullets_left, stage, life_float, score_goal, floating_texts, particles, high_score

if score > high_score:


high_score = score

ship = Ship()
bullets = []
enemies = []
explosions = []
coins = []
powerups = []
floating_texts = []
particles = []

init_starfield()

score = 0
money = 0
bullets_left = 100
stage = 1
life_float = MAX_LIFE
score_goal = 50

def start_stage():
global bullets, enemies, explosions, coins, powerups, spawn_timer, score_goal,
particles
bullets = []
enemies = []
explosions = []
coins = []
powerups = []
particles = []
spawn_timer = 0

if stage == 1: score_goal = 50
elif stage == 2: score_goal = 100
else: score_goal = 100 + (stage - 2) * 60 # Slightly higher goal for later
stages

[Link] = (WIDTH // 2, HEIGHT - 60)

def calculate_rewards():
global money, bullets_left, last_rewards
ammo_gain = 50
bullets_left += ammo_gain
health_bonus = int(life_float) * 20
money += health_bonus
last_rewards = {"ammo_gained": ammo_gain, "health_bonus": health_bonus}

def get_nearest_enemy():
nearest = None
min_dist = 9999
for e in enemies:
if [Link] > 0:
dist = [Link]([Link] - [Link], [Link] -
[Link])
if dist < min_dist:
min_dist = dist
nearest = e
return nearest

def trigger_fire():
global bullets_left
if bullets_left > 0:
bullets_left -= 1
ship.muzzle_flash_timer = 3

target_pos = None
is_auto = False

if ship.auto_aim_timer > 0:
target = get_nearest_enemy()
if target:
target_pos = [Link]
is_auto = True

[Link](Bullet([Link], [Link], target=target_pos,


is_auto_aim=is_auto))

if ship.has_wingman:
[Link](Bullet([Link] - 50, [Link], True,
target=target_pos, is_auto_aim=is_auto))
[Link](Bullet([Link] + 50, [Link], True,
target=target_pos, is_auto_aim=is_auto))

def trigger_nuke(pos):
"""Triggers a screen-clearing nuclear bomb."""
global enemies, bullets, explosions, coins, floating_texts, score

# Large explosion effect (size 500 fills the screen)


[Link](Explosion(pos, size=500, color=C_MAGENTA))

# Convert enemies to score and coins


for e in enemies:
score += NUKE_SCORE_GAIN
if e.is_boss: score += 50
[Link](Coin([Link], [Link]))
floating_texts.append(FloatingText([Link], [Link], "NUKE!",
C_MAGENTA, duration=90))

enemies = []
bullets = [b for b in bullets if b.is_auto_aim]
[Link]('explosion')

# Screen shake particles


for _ in range(50):
[Link](Particle([Link](0, WIDTH), [Link](0,
HEIGHT), C_WHITE, [Link](1, 3), 15, [Link](-10, 10)))

def handle_input():
"""Handles ship movement and auto-fire based on mouse input."""

# --- 1. MOVEMENT (Ship follows mouse) ---


mouse_x, mouse_y = [Link].get_pos()

# Clamp mouse_y to keep the ship below the HUD (y > 80)
clamped_y = max(80 + [Link] // 2, mouse_y)

# Move ship center to mouse position


[Link] = (mouse_x, clamped_y)

# Clamp ship to screen boundaries (respecting the adjusted Y position)


play_area = [Link](0, 80, WIDTH, HEIGHT - 80)
[Link].clamp_ip(play_area)

# --- 2. FIRING LOGIC (Left Click Hold) ---


mouse_buttons = [Link].get_pressed()

if mouse_buttons[0]: # Left Click


ship.fire_held_frames += 1
if ship.fire_cooldown > 0:
ship.fire_cooldown -= 1

# Auto Fire mode


if ship.fire_held_frames > AUTO_FIRE_DELAY:
if ship.fire_cooldown <= 0:
trigger_fire()
ship.fire_cooldown = RAPID_FIRE_INTERVAL
else:
# Reset logic when released
ship.fire_held_frames = 0
ship.fire_cooldown = 0

# --- DRAW SCREENS ---

def draw_hud(surface):
"""Draws the clean, sci-fi themed heads-up display."""

# 1. Background Bar (Top)


hud_rect = [Link](0, 0, WIDTH, 80)
[Link](surface, C_DARK_GREY, hud_rect)
[Link](surface, C_HUD_BORDER, (0, 80), (WIDTH, 80), 2)

# --- LEFT SIDE: HP & Stage ---

# HP Bar
hp_x, hp_y, hp_w, hp_h = 10, 10, 120, 15
[Link](surface, C_BLACK, (hp_x, hp_y, hp_w, hp_h), border_radius=3)
hp_fill_w = int((life_float / MAX_LIFE) * hp_w)
# Pulsing red if low health
hp_color = C_RED if life_float > 1.0 else (255, 100, 100) if
[Link].get_ticks() % 1000 < 500 else C_RED
[Link](surface, hp_color, (hp_x, hp_y, hp_fill_w, hp_h),
border_radius=3)

hp_text = font_sm.render(f"HULL: {int(life_float)} / {int(MAX_LIFE)}", True,


C_WHITE)
[Link](hp_text, (hp_x + 5, hp_y + 1))

# Stage
stage_text = font_md.render(f"SECTOR {stage}", True, C_YELLOW)
[Link](stage_text, (10, 35))

# --- CENTER: Score & Auto-Aim / Shield Status ---

# Score
score_display = font_lg.render(f"{score}", True, C_WHITE)
goal_display = font_sm.render(f"/{score_goal}", True, C_LIGHT_GREY)

score_x = WIDTH // 2 - score_display.get_width() // 2


[Link](score_display, (score_x, 5))
[Link](goal_display, (score_x + score_display.get_width() + 2, 25))

bar_w = 150
bar_h = 5
bar_x = WIDTH//2 - bar_w//2
bar_y = 55

# Auto-Aim / Shield Status Bar


if ship.auto_aim_timer > 0:
[Link](surface, C_DARK_GREY, (bar_x, bar_y, bar_w, bar_h),
border_radius=2)
fill = (ship.auto_aim_timer / (FPS * 10)) * bar_w
[Link](surface, C_MAGENTA, (bar_x, bar_y, int(fill), bar_h),
border_radius=2)
aim_txt = font_sm.render("Auto-Aim Active", True, C_MAGENTA)
[Link](aim_txt, (bar_x, bar_y + bar_h + 2))
elif ship.shield_active:
[Link](surface, C_DARK_GREY, (bar_x, bar_y, bar_w, bar_h),
border_radius=2)
fill = (ship.shield_timer / SHIELD_DURATION) * bar_w
[Link](surface, C_PURPLE, (bar_x, bar_y, int(fill), bar_h),
border_radius=2)
shield_txt = font_sm.render("Shield Active", True, C_PURPLE)
[Link](shield_txt, (bar_x, bar_y + bar_h + 2))

# --- RIGHT SIDE: Ammo, Money & Nuke ---

# Ammo
ammo_icon_x = WIDTH - 120
ammo_icon_y = 10
[Link](surface, C_BLUE, (ammo_icon_x, ammo_icon_y, 10, 15))
ammo_text = font_md.render(f"{bullets_left}", True, C_BLUE if bullets_left > 20
else C_RED)
[Link](ammo_text, (ammo_icon_x + 15, ammo_icon_y - 2))

# Money
money_icon_x = WIDTH - 120
money_icon_y = 35
[Link](surface, C_GOLD, (money_icon_x + 5, money_icon_y + 7), 6) #
Coin icon
money_text = font_md.render(f"${money}", True, C_GOLD)
[Link](money_text, (money_icon_x + 15, money_icon_y - 2))

# Nuke Counter
nuke_icon_x = WIDTH - 40
nuke_icon_y = 35
if ship.has_nuke:
[Link](surface, C_MAGENTA, (nuke_icon_x - 5, nuke_icon_y + 7),
6) # Nuke icon
nuke_text = font_md.render(f"x{ship.nuke_count}", True, C_MAGENTA)
[Link](nuke_text, (nuke_icon_x + 5, nuke_icon_y - 2))

def draw_pause_screen(surface):
"""Draws the pause overlay."""
overlay = [Link]((WIDTH, HEIGHT))
overlay.set_alpha(200)
[Link](C_BLACK)
[Link](overlay, (0,0))

txt = font_xl.render("PAUSED", True, C_YELLOW)


sub = font_md.render("Middle Click to Resume", True, C_WHITE)

[Link](txt, (WIDTH//2 - txt.get_width()//2, HEIGHT//3))


[Link](sub, (WIDTH//2 - sub.get_width()//2, HEIGHT//3 + 80))

# --- UI BUTTONS ---


btn_start = Button(WIDTH//2 - 100, HEIGHT//2 + 50, 200, 50, "START MISSION",
C_BLUE)
btn_restart = Button(WIDTH//2 - 100, HEIGHT//2 + 100, 200, 50, "RESTART", C_RED)

# Shop Buttons
btn_buy_bullets = Button(WIDTH//2 - 120, 250, 240, 40, "+20 Ammo", C_BLUE, cost=1)
btn_buy_wingman = Button(WIDTH//2 - 120, 300, 240, 40, "Wingman", C_GREEN, cost=20)

btn_buy_shield = Button(WIDTH//2 - 120, 350, 240, 40, "Permanent Shield", C_PURPLE,


cost=30)
btn_buy_nuke = Button(WIDTH//2 - 120, 400, 240, 40, "Nuke (+1 Charge)", C_MAGENTA,
cost=10)
btn_continue = Button(WIDTH//2 - 100, 480, 200, 50, "NEXT SECTOR >>", C_GREEN)

btn_emergency_buy = Button(WIDTH//2 - 120, HEIGHT//2 - 30, 240, 60, "RESUPPLY (+20


Ammo)", C_GREEN, cost=1)
btn_emergency_sac = Button(WIDTH//2 - 120, HEIGHT//2 + 80, 240, 60, "SACRIFICE 1 HP
(+30 Ammo)", C_RED)

# --- MAIN LOOP ---


running = True
init_game()

while running:
dt = [Link](FPS)
[Link](C_BLACK)

# --- EVENTS ---


for event in [Link]():
if [Link] == [Link]:
running = False
if [Link] == [Link]:
m_pos = [Link]

# --- MIDDLE CLICK (Button 2) - Pause Toggle ---


if [Link] == 2:
if game_state == STATE_PLAYING:
game_state = STATE_PAUSE
elif game_state == STATE_PAUSE:
game_state = STATE_PLAYING
# Middle click is intentionally disabled in Menu, Shop, Game Over,
and No Ammo states
# to prevent accidental skips and force necessary interaction.

# --- Other Clicks (Only process if not paused) ---


if game_state == STATE_PLAYING:
current_time = [Link].get_ticks()

# Button 1: Left Click (Fire & Nuke)


if [Link] == 1:
# Double Click Check (Nuke) - Must have Nuke unlocked AND
charges remaining
if ship.has_nuke and ship.nuke_count > 0 and current_time -
last_click_time < DOUBLE_CLICK_TIME:
trigger_nuke([Link])
ship.nuke_count -= 1
last_click_time = 0 # Reset for safety
else:
# Single click fire
if ship.fire_held_frames == 0:
trigger_fire()
last_click_time = current_time

# Button 3: Right Click (Shield) - Must have Shield unlocked


elif [Link] == 3:
if ship.has_shield and not ship.shield_active:
ship.shield_active = True
ship.shield_timer = SHIELD_DURATION
[Link]('powerup')

# --- State Button Clicks ---


if [Link] == 1:
if game_state == STATE_MENU and btn_start.is_clicked(m_pos):
init_game()
game_state = STATE_PLAYING

elif game_state == STATE_GAMEOVER and


btn_restart.is_clicked(m_pos):
init_game()
game_state = STATE_PLAYING

elif game_state == STATE_SHOP:


# Shop Logic
if btn_buy_bullets.is_clicked(m_pos) and money >=
btn_buy_bullets.cost:
money -= btn_buy_bullets.cost
bullets_left += 20
floating_texts.append(FloatingText(m_pos[0], m_pos[1], "+20
Ammo", C_BLUE))
[Link]('coin')
if btn_buy_wingman.is_clicked(m_pos) and money >=
btn_buy_wingman.cost and not ship.has_wingman:
money -= btn_buy_wingman.cost
ship.has_wingman = True
floating_texts.append(FloatingText(m_pos[0], m_pos[1],
"Wingman Equipped!", C_GREEN))
[Link]('powerup')

if btn_buy_shield.is_clicked(m_pos) and money >=


btn_buy_shield.cost and not ship.has_shield:
money -= btn_buy_shield.cost
ship.has_shield = True
floating_texts.append(FloatingText(m_pos[0], m_pos[1],
"Shield Unlocked!", C_PURPLE))
[Link]('powerup')

if btn_buy_nuke.is_clicked(m_pos) and money >=


btn_buy_nuke.cost:
money -= btn_buy_nuke.cost
ship.has_nuke = True # Ensure it's unlocked
ship.nuke_count += 1
floating_texts.append(FloatingText(m_pos[0], m_pos[1], "+1
Nuke Charge", C_MAGENTA))
[Link]('coin')

if btn_continue.is_clicked(m_pos):
stage += 1
start_stage()
game_state = STATE_PLAYING

elif game_state == STATE_NO_AMMO:


# Emergency Buy Logic
if btn_emergency_buy.is_clicked(m_pos) and money >=
btn_emergency_buy.cost:
money -= btn_emergency_buy.cost
bullets_left += 20
game_state = STATE_PLAYING

if btn_emergency_sac.is_clicked(m_pos):
if life_float > 1.0:
life_float -= 1.0
bullets_left += 30
game_state = STATE_PLAYING
else:
life_float = 0
game_state = STATE_GAMEOVER

# --- LOGIC & DRAWING ---


draw_starfield(screen) # Always draw starfield for visual appeal

if game_state == STATE_PLAYING:

handle_input()

# Shield Timer Update


if ship.shield_active:
ship.shield_timer -= 1
if ship.shield_timer <= 0:
ship.shield_active = False

# Auto-Aim Timer Update


if ship.auto_aim_timer > 0:
ship.auto_aim_timer -= 1

[Link](screen)

if bullets_left <= 0:
game_state = STATE_NO_AMMO

# Spawning
if spawn_timer <= 0:
is_boss_present = any(e.is_boss for e in enemies)
if stage % 5 == 0 and not is_boss_present and score < score_goal:
[Link](Enemy(is_boss=True))
elif len(enemies) < 10 and not is_boss_present:
[Link](Enemy())
spawn_timer = max(30, 80 - (stage * 5))
spawn_timer -= 1

# Objects update/draw loop


for p in particles[:]:
[Link]()
[Link](screen)
if [Link] <= 0: [Link](p)

for b in bullets[:]:
[Link]()
[Link](screen)
if [Link] < 0 or [Link] > WIDTH or [Link] < 0 or
[Link] > HEIGHT:
[Link](b)

for e in enemies[:]:
[Link](bullets)
[Link](screen)

# Damage Check: Collision with Enemy


if not ship.shield_active:
if [Link]([Link]):
life_float -= 1.0 if not e.is_boss else 3.0
if not e.is_boss:
if e in enemies: [Link](e)
[Link](Explosion([Link]))
floating_texts.append(FloatingText([Link],
[Link], "-1 HP", C_RED))

# Enemy missed the ship


if [Link] > HEIGHT:
[Link](e)
life_float -= 0.5
floating_texts.append(FloatingText([Link], HEIGHT-20,
"Missed!", C_ORANGE))

# Damage Check: Bullet hits Enemy


for b in bullets[:]:
if [Link]([Link]):
[Link] -= 1
if b in bullets: [Link](b)
if [Link] <= 0:
if e in enemies: [Link](e)
if e.is_boss: [Link]('hit')
else: [Link]('explosion')

[Link](Explosion([Link], 80 if e.is_boss
else 40))
score += 1 if not e.is_boss else 50
if [Link]() < 0.4: [Link](Coin([Link],
[Link]))
if [Link]() < 0.03 or e.is_boss:
[Link](PowerUp([Link], [Link]))
break

for c in coins[:]:
[Link]()
[Link](screen)
# Coin Magnet Logic (attracts coins when magnet powerup is active)
if ship.auto_aim_timer > 0:
dx = [Link] - [Link]
dy = [Link] - [Link]
dist = [Link](dx, dy)
if dist < 150 and dist > 0:
[Link] += int(dx / (dist / 5))
[Link] += int(dy / (dist / 5))

if [Link]([Link]):
money += 1
[Link](c)
floating_texts.append(FloatingText([Link], [Link],
"+$1", C_GOLD))
[Link]('coin')
elif [Link] > HEIGHT:
[Link](c)

for p in powerups[:]:
[Link]()
[Link](screen)
if [Link]([Link]):
[Link](p)
[Link]('powerup')
if [Link] == 'LIFE':
life_float = min(MAX_LIFE, life_float + 1)
floating_texts.append(FloatingText([Link],
[Link], "+1 HP", C_GREEN))
elif [Link] == 'FIRE_ASSIST':
ship.auto_aim_timer = FPS * 10
floating_texts.append(FloatingText([Link],
[Link], "OBLIVION MODE!", C_MAGENTA))
elif [Link] == 'COIN_MAGNET':
ship.auto_aim_timer = FPS * 7 # Re-use the timer for magnet
effect
floating_texts.append(FloatingText([Link],
[Link], "MAGNET ACTIVE!", C_BLUE))

for ex in explosions[:]:
[Link](screen)
if not [Link]: [Link](ex)
for ft in floating_texts[:]:
[Link]()
[Link](screen)
if [Link] <= 0: floating_texts.remove(ft)

# Draw the new HUD on top of everything


draw_hud(screen)

if life_float <= 0:
game_state = STATE_GAMEOVER
if score >= score_goal:
calculate_rewards()
game_state = STATE_SHOP

elif game_state == STATE_PAUSE:


draw_pause_screen(screen)
draw_hud(screen) # Draw HUD on top of pause screen

elif game_state == STATE_NO_AMMO:


overlay = [Link]((WIDTH, HEIGHT))
overlay.set_alpha(200)
[Link]((50, 0, 0))
[Link](overlay, (0,0))
msg = font_lg.render("OUT OF AMMO!", True, C_RED)
[Link](msg, (WIDTH//2 - msg.get_width()//2, 100))
btn_emergency_buy.draw(screen)
btn_emergency_sac.draw(screen)
info = font_sm.render("Click option to resume", True, C_WHITE)
[Link](info, (WIDTH//2 - info.get_width()//2, HEIGHT - 100))
draw_hud(screen)

elif game_state == STATE_SHOP:


overlay = [Link]((WIDTH, HEIGHT))
overlay.set_alpha(200)
[Link](C_DARK_GREY)
[Link](overlay, (0,0))

title = font_lg.render(f"SECTOR {stage} CLEARED!", True, C_GREEN)


[Link](title, (WIDTH//2 - title.get_width()//2, 50))

# Reward Report
resupply_txt = font_md.render(f"SUPPLY DROP: +{last_rewards['ammo_gained']}
Ammo", True, C_BLUE)
bonus_txt = font_md.render(f"PERFORMANCE BONUS: +$
{last_rewards['health_bonus']}", True, C_GOLD)
[Link](resupply_txt, (WIDTH//2 - resupply_txt.get_width()//2, 120))
[Link](bonus_txt, (WIDTH//2 - bonus_txt.get_width()//2, 160))

money_info = font_md.render(f"Total Funds: ${money}", True, C_WHITE)


[Link](money_info, (WIDTH//2 - money_info.get_width()//2, 210))

# Update button active states and text


btn_buy_wingman.active = (not ship.has_wingman and money >=
btn_buy_wingman.cost)
btn_buy_wingman.text = "Wingman" if not ship.has_wingman else "Wingman
(EQUIPPED)"

btn_buy_shield.active = (not ship.has_shield and money >=


btn_buy_shield.cost)
btn_buy_shield.text = "Permanent Shield" if not ship.has_shield else
"Shield (UNLOCKED)"

btn_buy_nuke.active = (money >= btn_buy_nuke.cost)


btn_buy_nuke.text = f"Nuke (+1 Charge) (x{ship.nuke_count})"

btn_buy_bullets.draw(screen)
btn_buy_wingman.draw(screen)
btn_buy_shield.draw(screen)
btn_buy_nuke.draw(screen)
btn_continue.draw(screen)
draw_hud(screen)

elif game_state == STATE_MENU:


title = font_lg.render("MILLENNIUM MISSION", True, C_YELLOW)
sub = font_md.render("ULTIMATE MOUSE EDITION", True, C_MAGENTA)
[Link](title, (WIDTH//2 - title.get_width()//2, HEIGHT//3))
[Link](sub, (WIDTH//2 - sub.get_width()//2, HEIGHT//3 + 50))

controls_line1 = font_sm.render("Controls: Mouse Movement", True,


C_LIGHT_GREY)
controls_line2 = font_sm.render("L-Click(Hold) Fire | R-Click Shield |
Double L-Click Nuke", True, C_LIGHT_GREY)
controls_line3 = font_sm.render("Middle Click to PAUSE/RESUME", True,
C_MAGENTA)

[Link](controls_line1, (WIDTH//2 - controls_line1.get_width()//2,


HEIGHT - 120))
[Link](controls_line2, (WIDTH//2 - controls_line2.get_width()//2,
HEIGHT - 95))
[Link](controls_line3, (WIDTH//2 - controls_line3.get_width()//2,
HEIGHT - 70))

btn_start.draw(screen)

elif game_state == STATE_GAMEOVER:


txt = font_lg.render("MISSION FAILED", True, C_RED)
score_t = font_md.render(f"Final Score: {score}", True, C_WHITE)
high_score_t = font_md.render(f"High Score: {high_score}", True, C_YELLOW)
[Link](txt, (WIDTH//2 - txt.get_width()//2, HEIGHT//3))
[Link](score_t, (WIDTH//2 - score_t.get_width()//2, HEIGHT//3 + 50))
[Link](high_score_t, (WIDTH//2 - high_score_t.get_width()//2,
HEIGHT//3 + 80))
btn_restart.draw(screen)

[Link]()

[Link]()

You might also like