from typing import Any, cast, get_args, overload
import pygame.sprite
+from pygame import Vector2
class Entity:
storage: type[T]
+class SkipSystem(Exception):
+ pass
+
+
type System = Callable[["World"], None]
type Plugin = Callable[["World"], None] | tuple[Plugin, ...]
if schedule not in self._schedules:
return
for system in self._schedules[schedule]:
- system(self)
+ try:
+ system(self)
+ except SkipSystem:
+ pass
+
+ def res_s[T](self, ty: type[T]) -> T:
+ if Resource(ty) not in self:
+ raise SkipSystem()
+ return self[Resource(ty)]
def run(
self,
@dataclass
-class Vec2:
- x: float
- y: float
+class ScreenCoord2D:
+ vec: Vector2
+
+
+class ShouldRender:
+ pass
@dataclass
-class Pos:
- vec: Vec2
+class Window:
+ surface: pygame.Surface
+
+
+def init_window(world: World) -> None:
+ world[Resource(Window)] = Window(pygame.display.set_mode())
@dataclass
-class Model2D:
- sprite: pygame.Surface
+class Sprite2D:
+ surface: pygame.Surface
-class ShouldRender:
- pass
+def render_sprite2d(world: World) -> None:
+ window = world.res_s(Window)
+ sprites = [
+ (sprite.surface, coord.vec)
+ for coord, sprite, _ in world.query(
+ tuple[ScreenCoord2D, Sprite2D, ShouldRender]
+ )
+ ]
+ window.surface.blits(sprites)
+
+
+@dataclass
+class ShapeColor:
+ color: pygame.Color
+
+
+@dataclass
+class Circle:
+ radius: float
+
+
+def render_circle2d(world: World) -> None:
+ window = world.res_s(Window)
+ for circle, coord, color, _ in world.query(
+ tuple[Circle, ScreenCoord2D, ShapeColor, ShouldRender]
+ ):
+ pygame.draw.circle(
+ window.surface, color.color, coord.vec, circle.radius
+ )
+
+
+@dataclass
+class Rectangle:
+ dims: Vector2
+
+
+def render_rectangle2d(world: World) -> None:
+ window = world.res_s(Window)
+ for rect, coord, color, _ in world.query(
+ tuple[Rectangle, ScreenCoord2D, ShapeColor, ShouldRender]
+ ):
+ pygame.draw.rect(window.surface, color.color, (coord.vec, rect.dims))
world = World()