diff --git a/testing/sprites/__main__.py b/testing/sprites/__main__.py index c1a201a..cea4ef0 100644 --- a/testing/sprites/__main__.py +++ b/testing/sprites/__main__.py @@ -1,10 +1,19 @@ +import datetime import enum import logging import pygame import random import time -from typing import List, Tuple - +from typing import Dict, List, Tuple + +from .helpers import ( + Animator, + AnimatorState, + TileGrid, + TileGridColumn, + TileGridCell, + MyTileGrid, +) from .utils import render_text @@ -15,262 +24,10 @@ SCREEN_WIDTH = 256 SCREEN_HEIGHT = 64 -# Sprites - FONT_FILENAME = "fonts/bitstream-vera.ttf" FONT_SIZE = 12 - -class CellStates(enum.Enum): - OPEN = enum.auto() - CLOSED = enum.auto() - OPENING = enum.auto() - CLOSING = enum.auto() - - -class CellCollapseStyle(enum.Enum): - HORIZONTAL = enum.auto() - VERTICAL = enum.auto() - - -class BaseSprite(pygame.sprite.Sprite): - pass - - -class CellGroup(pygame.sprite.Group): - def update(self): - super().update() - cy = 0 - for sprite in self.sprites(): - sprite.rect.y = cy - cy += sprite.rect.height - - -class CellRow(BaseSprite): - def __init__(self, x: int, y: int, width: int, height: int, cells: [BaseSprite]): - super().__init__() - self.x = x - self.y = y - self.width = width - self.height = height - self.cells = cells - self.image = pygame.Surface((self.width, self.height)) - self.rect = self.image.get_rect() - self.render() - - def update(self): - self.render() - - def render(self): - surface = pygame.Surface((self.width, self.height)) - cx = 0 - for cell in self.cells: - cell.update() - cell.render() - surface.blit(cell.image, (cx, 0)) - cx += cell.rect.width - print(([cell.evaluate() for cell in self.cells])) - self.image = pygame.Surface((cx, self.height)) - self.image.blit(surface, (0, 0)) - self.rect = self.image.get_rect() - - -class CellColumn(BaseSprite): - def __init__( - self, - x: int, - y: int, - width: int, - height: int, - cells: [BaseSprite], - border_width: int = 1, - border_color: pygame.Color = pygame.Color(255, 255, 255), - border_padding: int = 0, - ): - super().__init__() - self.x = x - self.y = y - self.width = width - self.height = height - self.cells = cells - self.border_width = border_width - self.border_color = border_color - self.border_padding = border_padding - self.image = pygame.Surface((self.width, self.height)) - self.rect = self.image.get_rect() - self.render() - - def update(self): - self.render() - - def render(self): - surface = pygame.Surface((self.width, self.height)) - surface.fill( - self.border_color, pygame.Rect(0, 0, self.border_width, self.height) - ) - cx, cy = self.border_width + self.border_padding, 0 - for cell in self.cells: - cell.update() - cell.render() - surface.blit(cell.image, (cx, cy)) - cy += cell.rect.height if cell.rect.height > 1 else 0 - self.image.blit(surface, (0, 0)) - self.rect = self.image.get_rect() - - def evaluate(self): - test = lambda cell: cell.open_state == CellStates.OPEN - logger.debug(f"CellColumn.evaluate: {[test(cell) for cell in self.cells]}") - return any([test(cell) for cell in self.cells]) - - -class Cell(BaseSprite): - def __init__( - self, - width: int, - height: int, - text: str, - font: str = FONT_FILENAME, - size: int = FONT_SIZE, - color_fg=pygame.Color(255, 255, 255), - color_bg=pygame.Color(0, 0, 0, 0), - color_outline=None, - padding: Tuple[int, int] = (0, -2), - evaluate_cb=lambda state: True, - ): - super().__init__() - self.width = width - self.height = height - self.text = text - self.font = font - self.size = size - self.color_fg = color_fg - self.color_bg = color_bg - self.color_outline = color_outline - self.padding = padding - self.evaluate_cb = evaluate_cb - self.render() - - def render(self): - self.image = pygame.Surface( - (self.width, self.height), - ) - self.image.fill(self.color_bg) - text_surface = render_text( - self.text, - font_filename=self.font, - font_size=self.size, - color_fg=self.color_fg, - color_outline=self.color_outline, - ) - self.image.blit(text_surface, (3 + self.padding[0], 0 + self.padding[1])) - - def evaluate(self): - state = dict() - return self.evaluate_cb(state) - - -class Collapsible(BaseSprite): - def __init__( - self, - x: int, - y: int, - width: int, - height: int, - sprite: BaseSprite, - width_closed: int = 0, - height_closed: int = 0, - open: bool = True, - collapse_style: CellCollapseStyle = CellCollapseStyle.HORIZONTAL, - speed: int = 1, - color_bg: pygame.Color = pygame.Color(0, 0, 0, 0), - debug: bool = False, - ): - super().__init__() - self.x = x - self.y = y - self.width_open = width - self.width_closed = width_closed - self.width = self.width_open if open else self.width_closed - self.height_open = height - self.height_closed = height_closed - self.height = self.height_open if open else self.height_closed - self.sprite = sprite - self.open_state = CellStates.OPEN if open else CellStates.CLOSED - self.collapse_style = collapse_style - self.speed = speed - self.color_bg = color_bg - self.debug = debug - self.image = pygame.Surface((self.width, self.height)) - self.rect = self.image.get_rect() - - def update(self): - if self.debug: - logger.debug(f"Cell.update: {self.open_state}") - if self.open_state in [CellStates.OPEN, CellStates.CLOSED]: - self.open_state = ( - CellStates.OPENING if self.evaluate() else CellStates.CLOSING - ) - self.handle_animation() - self.render() - - def handle_animation(self): - if self.open_state == CellStates.OPENING: - # Open Vertical - if self.collapse_style == CellCollapseStyle.VERTICAL: - self.height += self.speed - if self.height >= self.height_open: - self.height = self.height_open - if self.height == self.height_open: - self.open_state = CellStates.OPEN - # Open Horizontal - if self.collapse_style == CellCollapseStyle.HORIZONTAL: - self.width += self.speed - if self.width >= self.width_open: - self.width = self.width_open - if self.width == self.width_open: - self.open_state = CellStates.OPEN - elif self.open_state == CellStates.CLOSING: - # Close Vertical - if self.collapse_style == CellCollapseStyle.VERTICAL: - self.height -= self.speed - if self.height <= self.height_closed: - self.height = self.height_closed - if self.height == self.height_closed: - self.open_state = CellStates.CLOSED - # Close Horizontal - if self.collapse_style == CellCollapseStyle.HORIZONTAL: - self.width -= self.speed - if self.width <= self.width_closed: - self.width = self.width_closed - if self.width == self.width_closed: - self.open_state = CellStates.CLOSED - - def render(self, force_redraw: bool = False): - if force_redraw or self.open_state in [CellStates.OPENING, CellStates.CLOSING]: - self.image = pygame.Surface((self.width, self.height)) - self.image.fill(self.color_bg) - self.rect = self.image.get_rect() - if self.sprite.image is not None and self.image is not None: - self.sprite.update() - self.image.blit(self.sprite.image, (0, 0)) - self.rect = self.image.get_rect() - - def toggle(self): - if self.open_state == CellStates.OPEN or self.open_state == CellStates.OPENING: - self.open_state = CellStates.CLOSING - elif ( - self.open_state == CellStates.CLOSED - or self.open_state == CellStates.CLOSING - ): - self.open_state = CellStates.OPENING - if self.debug: - logger.debug(f"Cell.toggle: {self.open_state}") - - def evaluate(self): - return self.sprite.evaluate() - - -# Main Logic +# Sprites pygame.init() screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SCALED) @@ -279,62 +36,34 @@ def evaluate(self): FPS = 50 DEBUG = True -sprite_group: pygame.sprite.Group = pygame.sprite.Group() - -CELL_WIDTH = 64 -CELL_HEIGHT = 12 -tile_speedtest_download = Cell( - CELL_WIDTH, CELL_HEIGHT, "Download", evaluate_cb=lambda v: True -) - -column_tiles_internet = [tile_speedtest_download] -columns = [column_tiles_internet] - -cell_columns = [] -for column in columns: - column_cells = [] - for column_tile in column: - collapsible = Collapsible( - 0, - 0, - CELL_WIDTH, - CELL_HEIGHT, - column_tile, - collapse_style=CellCollapseStyle.VERTICAL, - debug=DEBUG, - ) - column_cells.append(collapsible) - cell_column = CellColumn(0, 0, CELL_WIDTH, SCREEN_HEIGHT, column_cells) - cell_column_collapsible = Collapsible( - 0, - 0, - CELL_WIDTH, - CELL_HEIGHT * len(column_cells), - cell_column, - collapse_style=CellCollapseStyle.HORIZONTAL, - debug=DEBUG, - ) - cell_columns.append(cell_column_collapsible) - -row = CellRow(0, 0, CELL_WIDTH * len(cell_columns), SCREEN_HEIGHT, cell_columns) - -sprite_group.add(row) +frame = 0 +state: Dict = dict() +running = True +sprite_group: pygame.sprite.Group = pygame.sprite.Group() +tile_grid = MyTileGrid(state) +sprite_group.add(tile_grid) -running = True while running: + now = datetime.datetime.now() for event in pygame.event.get(): if event.type == pygame.QUIT: running = False - # if event.type == pygame.KEYDOWN: - # if pygame.K_1 <= event.key <= pygame.K_8: - # numkey = event.key - pygame.K_0 - 1 - # sprites[numkey].toggle() + + if frame % 100 == 0: + state.update( + dict(download=random.randint(0, 1000), upload=random.randint(0, 1000)) + ) + print(f"State: {state}") screen.fill((0, 0, 0, 255)) sprite_group.update() sprite_group.draw(screen) pygame.display.flip() clock.tick(FPS) + if frame % 100 == 0: + logger.debug(f"Frame: {frame}, FPS: {clock.get_fps()}") + frame += 1 + pygame.quit() diff --git a/testing/sprites/scratch.py b/testing/sprites/helpers.py similarity index 63% rename from testing/sprites/scratch.py rename to testing/sprites/helpers.py index a50d779..dd21db6 100644 --- a/testing/sprites/scratch.py +++ b/testing/sprites/helpers.py @@ -1,4 +1,6 @@ import enum +import logging +import pygame import random import time from datetime import datetime @@ -26,6 +28,10 @@ # | +-------------------+ +-------------------+ | # +------------------------------------------------------+ +logger = logging.getLogger(__name__) +logger.addHandler(logging.StreamHandler()) +logger.setLevel(logging.DEBUG) + class AnimatorState(enum.Enum): OPEN = 1 @@ -77,61 +83,114 @@ def __repr__(self): # TILE GRID -class BaseSprite: +class BaseGroup(pygame.sprite.Group): pass -class BaseGroup: +class BaseSprite(pygame.sprite.Sprite): pass # should be a pygame.sprite.Sprite class TileGridCell(BaseSprite): - width: int - height: int + width: int = 64 + height: int = 12 visible: bool = True label: str = "" + def __init__(self, x=0, y=0): + super().__init__() + self.x = x + self.y = y + self.image = pygame.Surface((self.width, self.height)) + self.image.fill((0, random.randint(1, 32), 32)) + self.rect = self.image.get_rect() + + def update(self, state): + self.render(state) + + def render(self, state): + self.image = pygame.Surface((self.rect.width, self.rect.height)) + self.image.fill((0, random.randint(1, 32), 32)) + self.rect = self.image.get_rect() + def __repr__(self): return f"TileGridCell(size=({self.width}x{self.height}), visible={self.visible}, label='{self.label}')" # should be a pygame.sprite.Group -class TileGridColumn(BaseGroup): - cells: List[TileGridCell] = [] +class TileGridColumn(BaseSprite): + width: int = 64 + height: int = 1 + cells: List[TileGridCell] + + def __init__(self): + super().__init__() + self.image = pygame.Surface((self.width, self.height)) + self.rect = self.image.get_rect() def update(self, state): + self.render(state) + + def render(self, state): + ch = 0 + mh = sum([cell.image.get_height() for cell in self.cells]) + self.image = pygame.Surface((self.rect.width, mh)) + self.image.fill((0, 0, 0)) for cell in self.cells: cell.update(state) + self.image.blit(cell.image, (0, ch)) + ch += cell.image.get_height() def __repr__(self): return f"TileGridColumn(open={self.open}, cells={len(self.cells)})" # should be a pygame.sprite.Group -class TileGrid(BaseGroup): - columns: List[TileGridColumn] = [] +class TileGrid(BaseSprite): + columns: List[TileGridColumn] state: Dict = dict() - def __init__(self, state): + def __init__(self, state, x=0, y=0): + super().__init__() self.state = state + self.image = pygame.Surface((0, 0)) + self.rect = self.image.get_rect() def __repr__(self): - return f"TileGrid(columns={self.columns})" + return f"TileGrid(columns={self.groups})" def update(self): + self.render() + + def render(self): + cw = 0 + mw = sum([column.image.get_width() for column in self.columns]) + mh = max([column.image.get_width() for column in self.columns]) + self.image = pygame.Surface((mw, mh)) + self.image.fill((0, 0, 0, 255)) for column in self.columns: column.update(self.state) + self.image.blit(column.image, (cw, 0)) + cw += column.image.get_width() # CUSTOM SUBCLASSES class VerticalCollapseTileGridCell(TileGridCell): - width: int = 100 - height: int = 12 + width: int = 64 height_animator: Animator + def __init__(self): + super().__init__() + self.height_animator = Animator(range=(2.0, 12.0), open=True, speed=1.0) + + def update(self, state): + self.height_animator.update() + self.rect.height = self.height_animator.value + super().update(state) + @property def open(self): return self.height_animator.state != AnimatorState.CLOSED @@ -142,12 +201,17 @@ def __repr__(self): class HorizontalCollapseTileGridColumn(TileGridColumn): height: int = 12 - width_animator: Animator = Animator(range=(2.0, 64.0), open=True, speed=1.0) + width_animator: Animator + + def __init__(self): + super().__init__() + self.width_animator = Animator(range=(2.0, 64.0), open=True, speed=1.0) def update(self, state): - super().update(state) self.width_animator.set(self.open) self.width_animator.update() + self.rect.width = self.width_animator.value + super().update(state) @property def open(self): @@ -168,10 +232,10 @@ def __init__(self): self.height_animator = Animator(range=(2.0, 12.0), open=True, speed=1.0) def update(self, state): + super().update(state) v = int(state.get("download", 0)) - open = v < 500 + open = v > 500 self.height_animator.set(open) - self.height_animator.update() class CellSpeedTestUpload(VerticalCollapseTileGridCell): @@ -182,17 +246,21 @@ def __init__(self): self.height_animator = Animator(range=(2.0, 12.0), open=True, speed=1.0) def update(self, state): + super().update(state) v = int(state.get("upload", 0)) - open = v < 500 + open = v > 500 self.height_animator.set(open) - self.height_animator.update() # CUSTOM COLUMNS class GridColumn1(HorizontalCollapseTileGridColumn): - cells = [CellSpeedTestDownload(), CellSpeedTestUpload()] + cells = [CellSpeedTestUpload()] + + +class GridColumn2(HorizontalCollapseTileGridColumn): + cells = [CellSpeedTestDownload()] # CUSTOM GRID @@ -201,31 +269,4 @@ class GridColumn1(HorizontalCollapseTileGridColumn): class MyTileGrid(TileGrid): x = 0 y = 0 - columns = [GridColumn1()] - - -state: Dict = dict() -frame = 0 - -my_tile_grid = MyTileGrid(state) - -while True: - now = datetime.now() - - if frame % 100 == 0: - state.update( - dict(download=random.randint(0, 1000), upload=random.randint(0, 1000)) - ) - print(f"State: {state}") - time.sleep(1) - - my_tile_grid.update() - - col0 = my_tile_grid.columns[0] - cell0 = col0.cells[0] - cell1 = col0.cells[1] - - print(f"COL0: {col0}, CELLS: {cell0}, {cell1}") - - time.sleep(0.05) - frame += 1 + columns = [GridColumn1(), GridColumn2()] diff --git a/testing/sprites/rawgraphics.py b/testing/sprites/rawgraphics.py new file mode 100644 index 0000000..c1a201a --- /dev/null +++ b/testing/sprites/rawgraphics.py @@ -0,0 +1,340 @@ +import enum +import logging +import pygame +import random +import time +from typing import List, Tuple + +from .utils import render_text + + +logger = logging.getLogger(__name__) +logger.addHandler(logging.StreamHandler()) +logger.setLevel(logging.DEBUG) + +SCREEN_WIDTH = 256 +SCREEN_HEIGHT = 64 + +# Sprites + +FONT_FILENAME = "fonts/bitstream-vera.ttf" +FONT_SIZE = 12 + + +class CellStates(enum.Enum): + OPEN = enum.auto() + CLOSED = enum.auto() + OPENING = enum.auto() + CLOSING = enum.auto() + + +class CellCollapseStyle(enum.Enum): + HORIZONTAL = enum.auto() + VERTICAL = enum.auto() + + +class BaseSprite(pygame.sprite.Sprite): + pass + + +class CellGroup(pygame.sprite.Group): + def update(self): + super().update() + cy = 0 + for sprite in self.sprites(): + sprite.rect.y = cy + cy += sprite.rect.height + + +class CellRow(BaseSprite): + def __init__(self, x: int, y: int, width: int, height: int, cells: [BaseSprite]): + super().__init__() + self.x = x + self.y = y + self.width = width + self.height = height + self.cells = cells + self.image = pygame.Surface((self.width, self.height)) + self.rect = self.image.get_rect() + self.render() + + def update(self): + self.render() + + def render(self): + surface = pygame.Surface((self.width, self.height)) + cx = 0 + for cell in self.cells: + cell.update() + cell.render() + surface.blit(cell.image, (cx, 0)) + cx += cell.rect.width + print(([cell.evaluate() for cell in self.cells])) + self.image = pygame.Surface((cx, self.height)) + self.image.blit(surface, (0, 0)) + self.rect = self.image.get_rect() + + +class CellColumn(BaseSprite): + def __init__( + self, + x: int, + y: int, + width: int, + height: int, + cells: [BaseSprite], + border_width: int = 1, + border_color: pygame.Color = pygame.Color(255, 255, 255), + border_padding: int = 0, + ): + super().__init__() + self.x = x + self.y = y + self.width = width + self.height = height + self.cells = cells + self.border_width = border_width + self.border_color = border_color + self.border_padding = border_padding + self.image = pygame.Surface((self.width, self.height)) + self.rect = self.image.get_rect() + self.render() + + def update(self): + self.render() + + def render(self): + surface = pygame.Surface((self.width, self.height)) + surface.fill( + self.border_color, pygame.Rect(0, 0, self.border_width, self.height) + ) + cx, cy = self.border_width + self.border_padding, 0 + for cell in self.cells: + cell.update() + cell.render() + surface.blit(cell.image, (cx, cy)) + cy += cell.rect.height if cell.rect.height > 1 else 0 + self.image.blit(surface, (0, 0)) + self.rect = self.image.get_rect() + + def evaluate(self): + test = lambda cell: cell.open_state == CellStates.OPEN + logger.debug(f"CellColumn.evaluate: {[test(cell) for cell in self.cells]}") + return any([test(cell) for cell in self.cells]) + + +class Cell(BaseSprite): + def __init__( + self, + width: int, + height: int, + text: str, + font: str = FONT_FILENAME, + size: int = FONT_SIZE, + color_fg=pygame.Color(255, 255, 255), + color_bg=pygame.Color(0, 0, 0, 0), + color_outline=None, + padding: Tuple[int, int] = (0, -2), + evaluate_cb=lambda state: True, + ): + super().__init__() + self.width = width + self.height = height + self.text = text + self.font = font + self.size = size + self.color_fg = color_fg + self.color_bg = color_bg + self.color_outline = color_outline + self.padding = padding + self.evaluate_cb = evaluate_cb + self.render() + + def render(self): + self.image = pygame.Surface( + (self.width, self.height), + ) + self.image.fill(self.color_bg) + text_surface = render_text( + self.text, + font_filename=self.font, + font_size=self.size, + color_fg=self.color_fg, + color_outline=self.color_outline, + ) + self.image.blit(text_surface, (3 + self.padding[0], 0 + self.padding[1])) + + def evaluate(self): + state = dict() + return self.evaluate_cb(state) + + +class Collapsible(BaseSprite): + def __init__( + self, + x: int, + y: int, + width: int, + height: int, + sprite: BaseSprite, + width_closed: int = 0, + height_closed: int = 0, + open: bool = True, + collapse_style: CellCollapseStyle = CellCollapseStyle.HORIZONTAL, + speed: int = 1, + color_bg: pygame.Color = pygame.Color(0, 0, 0, 0), + debug: bool = False, + ): + super().__init__() + self.x = x + self.y = y + self.width_open = width + self.width_closed = width_closed + self.width = self.width_open if open else self.width_closed + self.height_open = height + self.height_closed = height_closed + self.height = self.height_open if open else self.height_closed + self.sprite = sprite + self.open_state = CellStates.OPEN if open else CellStates.CLOSED + self.collapse_style = collapse_style + self.speed = speed + self.color_bg = color_bg + self.debug = debug + self.image = pygame.Surface((self.width, self.height)) + self.rect = self.image.get_rect() + + def update(self): + if self.debug: + logger.debug(f"Cell.update: {self.open_state}") + if self.open_state in [CellStates.OPEN, CellStates.CLOSED]: + self.open_state = ( + CellStates.OPENING if self.evaluate() else CellStates.CLOSING + ) + self.handle_animation() + self.render() + + def handle_animation(self): + if self.open_state == CellStates.OPENING: + # Open Vertical + if self.collapse_style == CellCollapseStyle.VERTICAL: + self.height += self.speed + if self.height >= self.height_open: + self.height = self.height_open + if self.height == self.height_open: + self.open_state = CellStates.OPEN + # Open Horizontal + if self.collapse_style == CellCollapseStyle.HORIZONTAL: + self.width += self.speed + if self.width >= self.width_open: + self.width = self.width_open + if self.width == self.width_open: + self.open_state = CellStates.OPEN + elif self.open_state == CellStates.CLOSING: + # Close Vertical + if self.collapse_style == CellCollapseStyle.VERTICAL: + self.height -= self.speed + if self.height <= self.height_closed: + self.height = self.height_closed + if self.height == self.height_closed: + self.open_state = CellStates.CLOSED + # Close Horizontal + if self.collapse_style == CellCollapseStyle.HORIZONTAL: + self.width -= self.speed + if self.width <= self.width_closed: + self.width = self.width_closed + if self.width == self.width_closed: + self.open_state = CellStates.CLOSED + + def render(self, force_redraw: bool = False): + if force_redraw or self.open_state in [CellStates.OPENING, CellStates.CLOSING]: + self.image = pygame.Surface((self.width, self.height)) + self.image.fill(self.color_bg) + self.rect = self.image.get_rect() + if self.sprite.image is not None and self.image is not None: + self.sprite.update() + self.image.blit(self.sprite.image, (0, 0)) + self.rect = self.image.get_rect() + + def toggle(self): + if self.open_state == CellStates.OPEN or self.open_state == CellStates.OPENING: + self.open_state = CellStates.CLOSING + elif ( + self.open_state == CellStates.CLOSED + or self.open_state == CellStates.CLOSING + ): + self.open_state = CellStates.OPENING + if self.debug: + logger.debug(f"Cell.toggle: {self.open_state}") + + def evaluate(self): + return self.sprite.evaluate() + + +# Main Logic + +pygame.init() +screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SCALED) + +clock = pygame.time.Clock() +FPS = 50 +DEBUG = True + +sprite_group: pygame.sprite.Group = pygame.sprite.Group() + +CELL_WIDTH = 64 +CELL_HEIGHT = 12 + +tile_speedtest_download = Cell( + CELL_WIDTH, CELL_HEIGHT, "Download", evaluate_cb=lambda v: True +) + +column_tiles_internet = [tile_speedtest_download] +columns = [column_tiles_internet] + +cell_columns = [] +for column in columns: + column_cells = [] + for column_tile in column: + collapsible = Collapsible( + 0, + 0, + CELL_WIDTH, + CELL_HEIGHT, + column_tile, + collapse_style=CellCollapseStyle.VERTICAL, + debug=DEBUG, + ) + column_cells.append(collapsible) + cell_column = CellColumn(0, 0, CELL_WIDTH, SCREEN_HEIGHT, column_cells) + cell_column_collapsible = Collapsible( + 0, + 0, + CELL_WIDTH, + CELL_HEIGHT * len(column_cells), + cell_column, + collapse_style=CellCollapseStyle.HORIZONTAL, + debug=DEBUG, + ) + cell_columns.append(cell_column_collapsible) + +row = CellRow(0, 0, CELL_WIDTH * len(cell_columns), SCREEN_HEIGHT, cell_columns) + +sprite_group.add(row) + + +running = True +while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + # if event.type == pygame.KEYDOWN: + # if pygame.K_1 <= event.key <= pygame.K_8: + # numkey = event.key - pygame.K_0 - 1 + # sprites[numkey].toggle() + + screen.fill((0, 0, 0, 255)) + sprite_group.update() + sprite_group.draw(screen) + pygame.display.flip() + clock.tick(FPS) +pygame.quit()