import argparse import math import random import pygame import sys def parse_args(): p = argparse.ArgumentParser() p.add_argument("--targets", type=int, default=3) p.add_argument("--speed", type=float, default=200) p.add_argument("--size", type=int, default=10) p.add_argument("--mode", choices=["bounce", "oscillate"], default="bounce") return p.parse_args() class Ball: def __init__(self, w, h, r, speed, mode): self.r = r self.mode = mode self.x = random.uniform(r, w - r) self.y = random.uniform(r, h - r) if mode == "bounce": ang = random.uniform(0, math.tau) self.vx = math.cos(ang) * speed self.vy = math.sin(ang) * speed else: self.base_x = self.x self.base_y = self.y self.phase = random.uniform(0, math.tau) self.amp = random.uniform(30, 120) self.speed = speed def update(self, dt, w, h): if self.mode == "bounce": self.x += self.vx * dt self.y += self.vy * dt if self.x < self.r or self.x > w - self.r: self.vx = -self.vx self.x = max(self.r, min(self.x, w - self.r)) if self.y < self.r or self.y > h - self.r: self.vy = -self.vy self.y = max(self.r, min(self.y, h - self.r)) else: self.phase += dt * self.speed self.x = self.base_x + math.cos(self.phase) * self.amp self.y = self.base_y + math.sin(self.phase) * self.amp def draw(self, surf): pygame.draw.circle(surf, (255, 0, 0), (int(self.x), int(self.y)), self.r) def main(): args = parse_args() pygame.init() screen = pygame.display.set_mode((800, 600), pygame.RESIZABLE) pygame.display.set_caption("spectrum tracker test") clock = pygame.time.Clock() w, h = screen.get_size() balls = [Ball(w, h, args.size, args.speed, args.mode) for _ in range(args.targets)] pygame.mouse.set_visible(False) cursor_radius = 4 cursor_surface = pygame.Surface((cursor_radius * 2, cursor_radius * 2), pygame.SRCALPHA) pygame.draw.circle(cursor_surface, (255, 255, 255, 120), (cursor_radius, cursor_radius), cursor_radius) while True: dt = clock.tick(180) / 1000.0 for e in pygame.event.get(): if e.type == pygame.QUIT: pygame.quit() sys.exit() if e.type == pygame.VIDEORESIZE: screen = pygame.display.set_mode(e.size, pygame.RESIZABLE) w, h = e.size screen.fill((0, 0, 0)) for b in balls: b.update(dt, w, h) b.draw(screen) if pygame.mouse.get_focused(): mx, my = pygame.mouse.get_pos() screen.blit(cursor_surface, (mx - cursor_radius, my - cursor_radius)) pygame.display.flip() if __name__ == "__main__": main()