Edit on GitHub

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()
images: list[pygame.surface.Surface]
window: vi.Window
history: polars.series.series.Series
index: int = 0
background: pygame.surface.Surface
clock: pygame.time.Clock
screen: pygame.surface.Surface
running: bool = False
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)
def run(self) -> None:
103    def run(self) -> None:
104        self.running = True
105        while self.running:
106            self.tick()
107
108        pg.quit()