Initial commit

This commit is contained in:
James Campbell
2026-07-21 19:36:02 -04:00
commit d84e4627c3
39 changed files with 4386 additions and 0 deletions

72
game/assets.py Normal file
View File

@@ -0,0 +1,72 @@
"""Sprite loading with graceful placeholders.
Every drawable in the game asks the AssetStore for a surface by name. If a PNG
named ``<name>.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