From: = <=> Date: Mon, 28 Sep 2026 11:26:08 +0000 (+0200) Subject: Assets X-Git-Url: https://git.uwuaxy.net/Project%20Management.png?a=commitdiff_plain;h=f15239140fb658183fab73de166cd1ca11f1d3a4;p=axy%2Fft%2Fpacman.git Assets --- diff --git a/src/pacman/ecs/__init__.py b/src/pacman/ecs/__init__.py index df086dd..6b3c0e2 100644 --- a/src/pacman/ecs/__init__.py +++ b/src/pacman/ecs/__init__.py @@ -1,9 +1,11 @@ from dataclasses import dataclass from pathlib import Path +from typing import override import pygame from pygame import Vector3 +from pacman.ecs.assets import Asset, Assets from pacman.ecs.hierarchy import ( ChildOf, Hierarchy, @@ -114,9 +116,15 @@ def init_window(world: World) -> None: @dataclass -class Sprite2D(Component): +class Sprite2D(Component, Asset): surface: pygame.Surface + @override + @classmethod + def load(cls, ty: type, path: str) -> "Sprite2D": + del ty + return Sprite2D(pygame.image.load(path)) + def poll_events(events: WindowEvents) -> None: events.events = pygame.event.get() @@ -178,17 +186,8 @@ def move_root(root: Query[Coord2D, WiggleRoot]) -> None: coord.x = 30.0 + math.cos(tick) * 30.0 -if __name__ == "__main__": - world = ( - World() - .with_plugins(minimal_plugins, graphics_plugins) - .with_systems( - UpdateSchedule, - move_sprites, - move_root, - ) - ) - assets = list(Path("./asset").rglob("*.png")) +def setup_world(world: World, assets: Assets[Sprite2D]) -> None: + asset_paths = list(Path("./asset").rglob("*.png")) root = world.spawn( tuple[Coord2D, CoordAbs2D, WiggleRoot], ( @@ -209,19 +208,32 @@ if __name__ == "__main__": [ ( Coord2D( - 30.0 * (n := (i + j) % len(assets)), + 30.0 * (n := (i + j) % len(asset_paths)), 500.0 + 10.0, 1.0 * n + j, ), CoordAbs2D(), - Sprite2D(pygame.image.load(asset)), + assets.load(asset_path.as_posix()), ShouldRender(), WiggleSprite(), ChildOf(root), ) for j in range(3) - for i, asset in enumerate(assets) + for i, asset_path in enumerate(asset_paths) ], ) + pass + +if __name__ == "__main__": + world = ( + World() + .with_plugins(minimal_plugins, graphics_plugins) + .with_systems(StartupSchedule, setup_world) + .with_systems( + UpdateSchedule, + move_sprites, + move_root, + ) + ) world.run_main() diff --git a/src/pacman/ecs/assets.py b/src/pacman/ecs/assets.py new file mode 100644 index 0000000..0b80925 --- /dev/null +++ b/src/pacman/ecs/assets.py @@ -0,0 +1,38 @@ +from abc import ABC, abstractmethod +from collections.abc import Callable +from os import PathLike +from os.path import abspath +from typing import Self, cast, get_args, override + +from pacman.ecs.world import Resource, World +from pacman.utils.type_resolve import resolve_type_aliases + + +class Asset(ABC): + @classmethod + @abstractmethod + def load(cls, ty: type, path: str) -> Self: ... + + +class Assets[T: Asset](Resource): + def __init__(self, ty: type) -> None: + self._lookup: dict[str, T] = {} + self._asset_ty: type[T] = get_args(resolve_type_aliases(ty))[0] + + def load(self, s: str | PathLike[str]) -> T: + s = abspath(s) + if s not in self._lookup: + self._lookup[s] = self._asset_ty.load(self._asset_ty, s) + return self._lookup[s] + + @override + @classmethod + def extract_from_world( + cls, ty: type, world: World + ) -> Callable[[], Self | None]: + inner = cast( + Callable[[], Self | None], Resource.extract_from_world(ty, world) + ) + return lambda: cast( + Self, (res if (res := inner()) is not None else Assets(ty)) + )