Antoni09's picture
Upload game files
c02cd3b verified
Raw
History Blame Contribute Delete
5.62 kB
from __future__ import annotations
import random
from dataclasses import dataclass
from typing import Dict, List, Tuple
import pygame
from config import constants
ItemType = str
@dataclass
class ItemSpec:
color: Tuple[int, int, int]
label: str
ITEM_SPECS: Dict[ItemType, ItemSpec] = {
# Metals (asteroids)
"steel_scrap": ItemSpec((160, 160, 160), "Stl"),
"aluminum_sheet": ItemSpec((180, 200, 220), "Al"),
"copper_wire": ItemSpec((200, 140, 90), "Cu"),
# Enemy drops
"lithium_battery": ItemSpec((140, 200, 255), "Li"),
"circuit_board": ItemSpec((90, 200, 120), "PCB"),
"rare_earth_element": ItemSpec((200, 160, 255), "REE"),
"pet_plastic": ItemSpec((200, 200, 220), "PET"),
"carbon_fiber": ItemSpec((80, 80, 90), "CF"),
"titanium_alloy": ItemSpec((170, 170, 190), "Ti"),
"power_core": ItemSpec((255, 100, 80), "Core"),
"crystal_capacitor": ItemSpec((180, 220, 255), "Cap"),
"exotic_isotope": ItemSpec((255, 180, 80), "Iso"),
# Health
"repair_nanites": ItemSpec((90, 240, 140), "Heal"),
"bio_gel": ItemSpec((90, 200, 90), "Gel"),
# Power-ups (enemy drops)
"powerup_magnet": ItemSpec((90, 200, 255), "Mag"),
"powerup_super_magnet": ItemSpec((110, 220, 255), "SMag"),
"powerup_weapon_missile": ItemSpec((255, 190, 80), "MSL"),
"powerup_weapon_plasma": ItemSpec((120, 200, 255), "PLS"),
"powerup_weapon_ray": ItemSpec((255, 120, 200), "RAY"),
"powerup_shieldgen": ItemSpec((140, 220, 255), "SHD"),
"powerup_rapidfire": ItemSpec((255, 220, 90), "RF"),
"powerup_damage": ItemSpec((255, 120, 120), "Dmg"),
"powerup_shield": ItemSpec((120, 180, 255), "Shd"),
"powerup_regen": ItemSpec((90, 240, 140), "Regen"),
"powerup_slow": ItemSpec((120, 180, 255), "Slow"),
"powerup_multishot": ItemSpec((255, 160, 255), "2x"),
}
def random_metal_drop() -> ItemType:
r = random.random()
cumulative = 0.0
table = constants.ASTEROID_METAL_DROP_TABLE
for name, prob in table:
cumulative += prob
if r <= cumulative:
return name
return table[-1][0]
def random_enemy_drop() -> ItemType:
table = constants.ENEMY_DROP_TABLE
total = sum(weight for _, weight in table)
r = random.uniform(0, total)
cumulative = 0.0
for name, weight in table:
cumulative += weight
if r <= cumulative:
return name
return table[-1][0]
def random_powerup_drop() -> ItemType:
table = constants.POWERUP_DROP_TABLE
total = sum(weight for _, weight in table)
r = random.uniform(0, total)
cumulative = 0.0
for name, weight in table:
cumulative += weight
if r <= cumulative:
return name
return table[-1][0]
class Item(pygame.sprite.Sprite):
"""Collectible item dropped from asteroids or enemies."""
ICONS: Dict[str, pygame.Surface] = {}
def __init__(self, item_type: ItemType, pos: Tuple[float, float]):
super().__init__()
spec = ITEM_SPECS.get(item_type, ItemSpec((200, 200, 200), item_type))
self.item_type = item_type
icon = self.ICONS.get(item_type)
if icon:
self.image = pygame.transform.scale(icon, (18, 18))
else:
self.image = pygame.Surface((14, 14), pygame.SRCALPHA)
self.image.fill(spec.color)
font = pygame.font.Font(None, 12)
text = font.render(spec.label, True, (0, 0, 0))
text_rect = text.get_rect(center=(7, 7))
self.image.blit(text, text_rect)
self.rect = self.image.get_rect(center=pos)
self.pos = pygame.Vector2(pos)
self.vel = pygame.Vector2(-80, random.uniform(-20, 20)) # drift left with slight variation
def update(self, dt: float):
self.pos += self.vel * dt
self.rect.center = (int(self.pos.x), int(self.pos.y))
class Inventory:
"""Simple inventory with capacity counting total items."""
def __init__(self, capacity: int = constants.INVENTORY_LIMIT):
self.capacity = capacity
self.counts: Dict[ItemType, int] = {}
self.weapons: Dict[str, int] = {}
self.upgrades: Dict[str, int] = {}
self.owned_ships = {"salvager_one"}
self.current_ship = "salvager_one"
@property
def total(self) -> int:
return sum(self.counts.values())
def can_pick(self, amount: int = 1) -> bool:
return True # unlimited inventory
def add(self, item_type: ItemType, amount: int = 1) -> bool:
if not self.can_pick(amount):
return False
self.counts[item_type] = self.counts.get(item_type, 0) + amount
return True
def get(self, item_type: ItemType) -> int:
# Allow checking crafted weapons using snake_case keys for recipes
weapon_key_map = {
"laser_cannon": "Laser Cannon",
"missile_launcher": "Missile Launcher",
"shield_generator": "Shield Generator",
"plasma_weapon": "Plasma Weapon",
"destruction_ray": "Destruction Ray",
}
if item_type in weapon_key_map:
return self.weapons.get(weapon_key_map[item_type], 0)
return self.counts.get(item_type, 0)
def add_weapon(self, weapon_name: str):
self.weapons[weapon_name] = self.weapons.get(weapon_name, 0) + 1
def remove_weapon(self, weapon_name: str):
if weapon_name not in self.weapons:
return
self.weapons[weapon_name] = max(0, self.weapons.get(weapon_name, 0) - 1)
if self.weapons[weapon_name] <= 0:
del self.weapons[weapon_name]