pyrogue/game/components.py
2024-08-19 15:47:27 +02:00

77 lines
2.1 KiB
Python

"""Collection of common components."""
from __future__ import annotations
from typing import Final, Self, Callable
import attrs
import math
import tcod.ecs.callbacks
from tcod.ecs import Entity
@attrs.define(frozen=True)
class Position:
"""An entities position."""
x: int
y: int
def __add__(self, direction: tuple[int, int] | Position) -> Self:
"""Add a vector to this position."""
match direction:
case Position(x, y):
return self.__class__(self.x + x, self.y + y)
case (x, y):
return self.__class__(self.x + x, self.y + y)
raise NotImplementedError
def __sub__(self, direction: tuple[int, int] | Position) -> Self:
match direction:
case Position(x, y):
return self.__class__(self.x - x, self.y - y)
case (x, y):
return self.__class__(self.x - x, self.y - y)
raise NotImplementedError
def mod(self, other: tuple[int,int] | Position | int) -> Self:
match other:
case Position(x,y):
return self.__class__(self.x//x, self.y//y)
case int(x):
return self.__class__(self.x//x, self.y//x)
case (x, y):
return self.__class__(self.x//x, self.y//y)
raise NotImplementedError
def length(self):
return math.sqrt(self.x**2+self.y**2)
@tcod.ecs.callbacks.register_component_changed(component=Position)
def on_position_changed(entity: Entity, old: Position | None, new: Position | None) -> None:
"""Mirror position components as a tag."""
if old == new:
return
if old is not None:
entity.tags.discard(old)
if new is not None:
entity.tags.add(new)
from numpy.typing import NDArray
@attrs.define(frozen=True)
class Graphic:
"""An entities icon and color."""
ch: int = ord("!")
fg: NDArray = (255, 255, 255, 255)
bg: NDArray = (0, 0, 0, 0)
Action: Final = ("Action", Callable[[Entity], None])
"""Possible action."""
Gold: Final = ("Gold", int)
"""Amount of gold."""
HP: Final = ("Health", int)
"""How alive an entity is"""