import random from collections.abc import Callable import pygame from asteroid import Asteroid from constants import * Edge = tuple[pygame.Vector2, Callable[[float], pygame.Vector2]] class AsteroidField(pygame.sprite.Sprite): containers: pygame.sprite.Group edges: list[Edge] = [ ( pygame.Vector2(1, 0), lambda y: pygame.Vector2(-ASTEROID_MAX_RADIUS, y * SCREEN_HEIGHT), ), ( pygame.Vector2(-1, 0), lambda y: pygame.Vector2( SCREEN_WIDTH + ASTEROID_MAX_RADIUS, y * SCREEN_HEIGHT ), ), ( pygame.Vector2(0, 1), lambda x: pygame.Vector2(x * SCREEN_WIDTH, -ASTEROID_MAX_RADIUS), ), ( pygame.Vector2(0, -1), lambda x: pygame.Vector2( x * SCREEN_WIDTH, SCREEN_HEIGHT + ASTEROID_MAX_RADIUS ), ), ] def __init__(self) -> None: pygame.sprite.Sprite.__init__(self, self.containers) self.spawn_timer = 0.0 def spawn( self, radius: float, position: pygame.Vector2, velocity: pygame.Vector2 ) -> None: asteroid = Asteroid(position.x, position.y, radius) asteroid.velocity = velocity def update(self, dt: float) -> None: self.spawn_timer += dt if self.spawn_timer > ASTEROID_SPAWN_RATE_SECONDS: self.spawn_timer = 0 edge = random.choice(self.edges) speed = random.randint(40, 100) velocity = edge[0] * speed velocity = velocity.rotate(random.randint(-30, 30)) position = edge[1](random.uniform(0, 1)) kind = random.randint(1, ASTEROID_KINDS) self.spawn(ASTEROID_MIN_RADIUS * kind, position, velocity)