vi.replay
1from __future__ import annotations 2 3from typing import TYPE_CHECKING 4 5import pygame as pg 6 7from .config import Window 8 9 10if TYPE_CHECKING: 11 from typing import Any 12 13 from polars import DataFrame, Series 14 15 16__all__ = [ 17 "TimeMachine", 18] 19 20 21def load_images(image_paths: list[str]) -> list[pg.surface.Surface]: 22 return [pg.image.load(path).convert_alpha() for path in image_paths] 23 24 25class TimeMachine: 26 images: list[pg.surface.Surface] 27 window: Window 28 29 history: Series 30 index: int = 0 31 32 background: pg.surface.Surface 33 clock: pg.time.Clock 34 screen: pg.surface.Surface 35 36 running: bool = False 37 38 def __init__( 39 self, 40 history: DataFrame, 41 image_paths: list[str], 42 window: Window | None = None, 43 ) -> None: 44 pg.display.init() 45 46 # Convert multiple series (one per column) into one series of structs 47 self.history = history.to_struct("agent") 48 49 self.window = window if window is not None else Window() 50 self.screen = pg.display.set_mode(self.window.as_tuple()) 51 pg.display.set_caption("Violet") 52 53 # Load the images 54 self.images = load_images(image_paths) 55 56 # Initialise background 57 self.background = pg.surface.Surface(self.screen.get_size()).convert() 58 self.background.fill((0, 0, 0)) 59 60 # Initialise the clock. Used to cap FPS. 61 self.clock = pg.time.Clock() 62 63 def tick(self) -> None: 64 for event in pg.event.get(): 65 if event.type == pg.QUIT: 66 self.running = False 67 return 68 69 self.screen.blit(self.background, (0, 0)) 70 71 if self.index == len(self.history): 72 self.running = False 73 return 74 75 current_frame: int = self.history[self.index]["frame"] 76 77 while True: 78 if self.index == len(self.history): 79 self.running = False 80 break 81 82 data: dict[str, Any] = self.history[self.index] 83 if data["frame"] != current_frame: 84 break 85 86 image_index: int = data["image_index"] 87 image = self.images[image_index] 88 89 angle = data.get("angle") 90 if angle is not None: 91 image = pg.transform.rotate(image, angle) 92 93 rect = image.get_rect() 94 rect.center = (data["x"], data["y"]) 95 96 self.screen.blit(image, rect) 97 self.index += 1 98 99 pg.display.flip() 100 self.clock.tick(60) 101 102 def run(self) -> None: 103 self.running = True 104 while self.running: 105 self.tick() 106 107 pg.quit()
class
TimeMachine:
26class TimeMachine: 27 images: list[pg.surface.Surface] 28 window: Window 29 30 history: Series 31 index: int = 0 32 33 background: pg.surface.Surface 34 clock: pg.time.Clock 35 screen: pg.surface.Surface 36 37 running: bool = False 38 39 def __init__( 40 self, 41 history: DataFrame, 42 image_paths: list[str], 43 window: Window | None = None, 44 ) -> None: 45 pg.display.init() 46 47 # Convert multiple series (one per column) into one series of structs 48 self.history = history.to_struct("agent") 49 50 self.window = window if window is not None else Window() 51 self.screen = pg.display.set_mode(self.window.as_tuple()) 52 pg.display.set_caption("Violet") 53 54 # Load the images 55 self.images = load_images(image_paths) 56 57 # Initialise background 58 self.background = pg.surface.Surface(self.screen.get_size()).convert() 59 self.background.fill((0, 0, 0)) 60 61 # Initialise the clock. Used to cap FPS. 62 self.clock = pg.time.Clock() 63 64 def tick(self) -> None: 65 for event in pg.event.get(): 66 if event.type == pg.QUIT: 67 self.running = False 68 return 69 70 self.screen.blit(self.background, (0, 0)) 71 72 if self.index == len(self.history): 73 self.running = False 74 return 75 76 current_frame: int = self.history[self.index]["frame"] 77 78 while True: 79 if self.index == len(self.history): 80 self.running = False 81 break 82 83 data: dict[str, Any] = self.history[self.index] 84 if data["frame"] != current_frame: 85 break 86 87 image_index: int = data["image_index"] 88 image = self.images[image_index] 89 90 angle = data.get("angle") 91 if angle is not None: 92 image = pg.transform.rotate(image, angle) 93 94 rect = image.get_rect() 95 rect.center = (data["x"], data["y"]) 96 97 self.screen.blit(image, rect) 98 self.index += 1 99 100 pg.display.flip() 101 self.clock.tick(60) 102 103 def run(self) -> None: 104 self.running = True 105 while self.running: 106 self.tick() 107 108 pg.quit()
TimeMachine( history: polars.dataframe.frame.DataFrame, image_paths: list[str], window: vi.Window | None = None)
39 def __init__( 40 self, 41 history: DataFrame, 42 image_paths: list[str], 43 window: Window | None = None, 44 ) -> None: 45 pg.display.init() 46 47 # Convert multiple series (one per column) into one series of structs 48 self.history = history.to_struct("agent") 49 50 self.window = window if window is not None else Window() 51 self.screen = pg.display.set_mode(self.window.as_tuple()) 52 pg.display.set_caption("Violet") 53 54 # Load the images 55 self.images = load_images(image_paths) 56 57 # Initialise background 58 self.background = pg.surface.Surface(self.screen.get_size()).convert() 59 self.background.fill((0, 0, 0)) 60 61 # Initialise the clock. Used to cap FPS. 62 self.clock = pg.time.Clock()
window: vi.Window
def
tick(self) -> None:
64 def tick(self) -> None: 65 for event in pg.event.get(): 66 if event.type == pg.QUIT: 67 self.running = False 68 return 69 70 self.screen.blit(self.background, (0, 0)) 71 72 if self.index == len(self.history): 73 self.running = False 74 return 75 76 current_frame: int = self.history[self.index]["frame"] 77 78 while True: 79 if self.index == len(self.history): 80 self.running = False 81 break 82 83 data: dict[str, Any] = self.history[self.index] 84 if data["frame"] != current_frame: 85 break 86 87 image_index: int = data["image_index"] 88 image = self.images[image_index] 89 90 angle = data.get("angle") 91 if angle is not None: 92 image = pg.transform.rotate(image, angle) 93 94 rect = image.get_rect() 95 rect.center = (data["x"], data["y"]) 96 97 self.screen.blit(image, rect) 98 self.index += 1 99 100 pg.display.flip() 101 self.clock.tick(60)