"""Sprite loading with graceful placeholders. Every drawable in the game asks the AssetStore for a surface by name. If a PNG named ``.png`` exists in the assets directory it is loaded and scaled to the requested size; otherwise a labeled colored rectangle is drawn instead, so the game is fully playable before any art exists. """ import os import pygame from . import settings class AssetStore: def __init__(self, assets_dir): self.assets_dir = assets_dir self._raw = {} # name -> original loaded Surface (or None if missing) self._cache = {} # (name, w, h) -> scaled Surface self._font = None def _font_for(self, h): # Lazily build a font sized to the tile so placeholder labels fit. size = max(10, int(h * 0.5)) return pygame.font.SysFont("consolas,menlo,monospace", size, bold=True) def _load_raw(self, name): if name in self._raw: return self._raw[name] path = os.path.join(self.assets_dir, name + ".png") surf = None if os.path.isfile(path): try: surf = pygame.image.load(path).convert_alpha() except pygame.error: surf = None self._raw[name] = surf return surf def get(self, name, w, h, angle=0): """Return a Surface of exactly (w, h) for the given sprite name, optionally rotated counter-clockwise by ``angle`` degrees first (used to point directional sprites like spikes the right way).""" w, h = int(w), int(h) angle %= 360 key = (name, w, h, angle) if key in self._cache: return self._cache[key] raw = self._load_raw(name) if raw is not None: if angle: raw = pygame.transform.rotate(raw, angle) # Nearest-neighbour keeps the pixel-art sprites crisp at any size. surf = pygame.transform.scale(raw, (w, h)) else: surf = self._make_placeholder(name, w, h) self._cache[key] = surf return surf def _make_placeholder(self, name, w, h): color, label = settings.PLACEHOLDERS.get(name, ((200, 60, 200), "?")) surf = pygame.Surface((w, h), pygame.SRCALPHA) surf.fill(color) # A subtle border helps distinguish adjacent tiles of the same color. pygame.draw.rect(surf, (0, 0, 0, 90), surf.get_rect(), max(1, w // 16)) if label: font = self._font_for(h) text = font.render(label, True, (15, 15, 20)) surf.blit(text, text.get_rect(center=(w // 2, h // 2))) return surf