Source code for ppb.assets

import sdl2.ext
from sdl2 import (
    SDL_Point,  # https://wiki.libsdl.org/SDL_Point
    SDL_CreateRGBSurface,  # https://wiki.libsdl.org/SDL_CreateRGBSurface
    SDL_FreeSurface,  # https://wiki.libsdl.org/SDL_FreeSurface
    SDL_SetColorKey,  # https://wiki.libsdl.org/SDL_SetColorKey
    SDL_CreateSoftwareRenderer,  # https://wiki.libsdl.org/SDL_CreateSoftwareRenderer
    SDL_DestroyRenderer,  # https://wiki.libsdl.org/SDL_DestroyRenderer
    SDL_SetRenderDrawColor,  # https://wiki.libsdl.org/SDL_SetRenderDrawColor
    SDL_RenderFillRect,  # https://wiki.libsdl.org/SDL_RenderFillRect
)

from sdl2.sdlgfx import (
    filledTrigonRGBA,  # https://www.ferzkopp.net/Software/SDL2_gfx/Docs/html/_s_d_l2__gfx_primitives_8h.html#a273cf4a88abf6c6a5e019b2c58ee2423
    filledCircleRGBA,  # https://www.ferzkopp.net/Software/SDL2_gfx/Docs/html/_s_d_l2__gfx_primitives_8h.html#a666bd764e2fe962656e5829d0aad5ba6
)

from ppb.assetlib import BackgroundMixin, FreeingMixin, AbstractAsset
from ppb.systems.sdl_utils import sdl_call

__all__ = (
    "Square",
    "Triangle",
    "Circle",
)

BLACK = 0, 0, 0
MAGENTA = 255, 71, 182
DEFAULT_SPRITE_SIZE = 64


def _create_surface(color):
    """
    Creates a surface for assets and sets the color key.
    """
    surface = sdl_call(
        SDL_CreateRGBSurface, 0, DEFAULT_SPRITE_SIZE, DEFAULT_SPRITE_SIZE, 32, 0, 0, 0, 0,
        _check_error=lambda rv: not rv
    )
    color_key = BLACK if color != BLACK else MAGENTA
    color = sdl2.ext.Color(*color_key)
    sdl_call(
        SDL_SetColorKey, surface, True, sdl2.ext.prepare_color(color, surface.contents),
        _check_error=lambda rv: rv < 0
    )
    sdl2.ext.fill(surface.contents, color)
    return surface


class Shape(BackgroundMixin, FreeingMixin, AbstractAsset):
    """Shapes are drawing primitives that are good for rapid prototyping."""
    def __init__(self, red: int, green: int, blue: int):
        self.color = red, green, blue
        self._start()

    def _background(self):
        surface = _create_surface(self.color)

        renderer = sdl_call(
            SDL_CreateSoftwareRenderer, surface,
            _check_error=lambda rv: not rv
        )
        try:
            self._draw_shape(renderer, rgb=self.color)
        finally:
            sdl_call(SDL_DestroyRenderer, renderer)

        return surface

    def free(self, surface, _SDL_FreeSurface=SDL_FreeSurface):
        SDL_FreeSurface(surface)

    def _draw_shape(self, renderer, **_) -> None:
        """
        Modify the raw asset to match the intended shape.
        """


[docs]class Square(Shape): """ A square image of a single color. """ def _draw_shape(self, renderer, rgb, **_): sdl_call( SDL_SetRenderDrawColor, renderer, *rgb, 255, _check_error=lambda rv: rv < 0 ) sdl_call( SDL_RenderFillRect, renderer, None, _check_error=lambda rv: rv < 0 )
[docs]class Triangle(Shape): """ A triangle image of a single color. """ def _draw_shape(self, renderer, rgb, **_): sdl_call( filledTrigonRGBA, renderer, 0, DEFAULT_SPRITE_SIZE, int(DEFAULT_SPRITE_SIZE / 2), 0, DEFAULT_SPRITE_SIZE, DEFAULT_SPRITE_SIZE, *rgb, 255, _check_error=lambda rv: rv < 0 )
[docs]class Circle(Shape): """ A circle image of a single color. """ def _draw_shape(self, renderer, rgb, **_): half = int(DEFAULT_SPRITE_SIZE / 2) sdl_call( filledCircleRGBA, renderer, half, half, # Center half, # Radius *rgb, 255, _check_error=lambda rv: rv < 0 )