from dataclasses import dataclass, field from typing import cast from pyglet.shapes import Circle, Line from libs.ecs.world import World from components import ( Color, PlanetMarker, Position, Radius, SpaceShipMarker, Destination, ) from random import choice, randint, sample from settings import ( MIN_PLANET_RADIUS, MAX_PLANET_RADIUS, PLANET_COLORS, SCREEN_WIDTH, SCREEN_HEIGHT, SPACESHIP_COLOR, SPACESHIP_PATH_COLOR, SPACESHIP_RADIUS, ) from libs.ecs.state import BaseGameState @dataclass class GameState(BaseGameState): selected_planet: int | None = None routes: dict[tuple[int, int], "Line"] = field(default_factory=dict) def create_planet( world: World, x: float, y: float, radius: int, color: tuple[int, int, int, int], ) -> int: return world.spawn( PlanetMarker(), Position(x=x, y=y), Color(value=color), Circle(x=x, y=y, radius=radius, color=color), Radius(radius), ) def create_spaceship( world: World, src_x: float, src_y: float, dest_x: float, dest_y: float, approach_radius: int, ): return world.spawn( SpaceShipMarker(), Position(x=src_x, y=src_y), Destination(x=dest_x, y=dest_y), Radius(approach_radius), Circle( x=src_x, y=src_y, radius=SPACESHIP_RADIUS, color=SPACESHIP_COLOR, ), ) def generate_random_planet(world: World) -> int: radius: int = randint(MIN_PLANET_RADIUS, MAX_PLANET_RADIUS) x: float = float(randint(radius, SCREEN_WIDTH - radius)) y: float = float(randint(radius, SCREEN_HEIGHT - radius)) # color = (randint(0, 255), randint(0, 255), randint(0, 255), 255) color = choice(PLANET_COLORS) + (255,) return create_planet(world, x, y, radius, color) def create_travelling_spaceship( world: World, src_planet: int, dest_planet: int, ): src_planet_cs = world.get_components(src_planet) if src_planet_cs is None: raise Exception("invalid_planet") dest_planet_cs = world.get_components(dest_planet) if dest_planet_cs is None: raise Exception("invalid_planet") source_pos = src_planet_cs[Position] dest_pos = dest_planet_cs[Position] approach_radius = dest_planet_cs[Radius].value return create_spaceship( world, src_x=source_pos.x, src_y=source_pos.y, dest_x=dest_pos.x, dest_y=dest_pos.y, approach_radius=approach_radius, ) def generate_random_spaceship(world: World) -> int: planets = [entity for entity, _ in world.query(PlanetMarker)] _planet_sample = sample(planets, 2) return create_travelling_spaceship(world, *_planet_sample) def load_items(path: str) -> list[str]: with open(path) as f: data = [l.rstrip("\n") for l in f.readlines()] return data def normalize_name(name: str) -> str: return name.replace("_", " ").title()