Pygskin


NamePygskin JSON
Version 0.3.0 PyPI version JSON
download
home_pageNone
SummaryNone
upload_time2025-02-10 23:41:32
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseMIT
keywords framework game pygame
VCS
bugtrack_url
requirements pygame-ce
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Pygskin

A collection of useful functions and classes for Pygame

## [`animate` function](pygskin/animation.py)
Animation generator function which takes a list of frames or mapping of
quotients (0.0 - 1.0) to keyframes and a function that returns a quotient, and
returns an generator that returns frames.
```python
anim = animate([image1, image2], timer.quotient)
screen.blit(next(anim))
```


## [`Assets` class](pygskin/assets.py)
Provides attribute access to asset files and batch loading
```python
assets = Assets()
screen.blit(assets.player)
assets.player_spawn_sfx.play()
```


## [`Camera` class](pygskin/camera.py)
A camera class for scrolling and zooming a surface.
```python
camera = Camera(screen.get_rect(), clamp=world_map.get_rect())
camera.view.fill("black")
sprite_group.draw(camera)
camera.zoom = 2.4
camera.draw(screen)
```

## [`Timer` class](pygskin/clock.py)
A countdown timer dataclass. Can be used with the `animate` function.
```python
timer = Timer(3000)  # 3 seconds
timer.tick()
if timer.finished:
    timer.elapsed = 0  # loop
```


## [`iter_dialogue` function](pygskin/dialogue.py)
Generator function for stepping through a dialogue script parsed from a JSON or
YAML file.
```python
context = {}
dialogue = iter_dialogue(
    assets.act1_scene1,
    context,
    speak=speak,
)

def main_loop(screen, events, quit):
    if action := next(dialogue, None):
        action()
```


## [`Direction` enum](pygskin/direction.py)
Enum for up/down/left/right directions
```python
direction = Direction.UP
if direction in Direction.VERTICAL:
    rect.move_ip(direction.vector)
```


## [`easing` module](pygskin/easing.py)
A selection of easing functions for use with interpolation. Can be used with the
`animate` and `make_color_gradient` functions.


## [`Component` class](pygskin/ecs.py)
A minimal ECS implementation.
```python
class Velocity(Component[Vector2]): ...
class Position(Component[Vector2]): ...

def apply_velocity_system() -> None:
    for id, velocity in Velocity.components.items():
        pos = Position.components[id]
        pos += velocity

@dataclass
class Entity:
    pos: Position = Position()
    velocity: Velocity = Velocity()

entities = [Entity(pos=Vector2(0, 0), velocity=Vector2(1, 1)])

apply_velocity_system()
```


## [`bind` function](pygskin/func.py)
Partial function application with one or more argument placeholders at arbitrary
positions.
```python
foos = filter(bind(isinstance, ..., Foo), items)
```


## [`run_game` function](pygskin/game.py)
Pygbag compatible game loop.
```python
def main_loop(screen, events, exit):
    screen.fill(random.choice(pygame.color.THECOLORS.values()))

    for event in events:
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            exit()


if __name__ == '__main__':
    run_game(Window("My Game", (WIDTH, HEIGHT)), main_loop)
```


## [`make_color_gradient` function](pygskin/gradient.py)
Generate a color gradient between two colors.
```python
sky_image = make_color_gradient(screen.size, "white", "blue")
screen.blit(sky_image)
```


## [`imgui` module](pygskin/imgui.py)
Immediate mode GUI.
```python
gui = imgui.IMGUI()

def main_loop(screen, events, exit):
    with imgui.render(gui, screen) as render:
        if render(imgui.button("Quit"), center=(100, 200)):
            exit()
```


## [`map_inputs_to_actions` function](pygskin/input.py)
Map input events to actions. Enables user-defined key bindings.
```python
keyboard_controls = {
    "jump": Event(pg.KEYDOWN, key=pg.K_UP),
    "duck": Event(pg.KEYDOWN, key=pg.K_DOWN),
    "quit": Event(pg.KEYDOWN, key=pg.K_ESCAPE),
}
for action in map_inputs_to_actions(
    keyboard_controls,
    pygame.event.get(),
):
    if action == "jump":
        player.jump()
    if action == "duck":
        player.duck()
    if action == "quit":
        exit()
```


## [`lazy` class](pygskin/lazy.py)
Lazy loading object proxy. Works like a partial function application for
objects.
```python
image = lazy(pygame.image.load, "foo.png"))
screen.blit(image)
```


## [`scroll_parallax_layers` function](pygskin/parallax.py)
Scroll parallax layers at different rates.
```python
background = LayeredUpdates()
background.add(assets.sky, layer=0)
background.add(assets.mountains, layer=1)
background.add(assets.trees, layer=2)

scroll_parallax_layers(
    (vx, vy),
    background.layers,
    background.get_sprites_from_layer,
    {0: 0, 1: 1.5, 2: 2.0},
)
```


## [`channel` function](pygskin/pubsub.py)
Simple pubsub implementation.
```python
foo = channel()
foo.subscribe(lambda x: print(f"subscriber 1: {x}"))
foo("bar")
```


## [`get_rect_attrs` function](pygskin/rect.py)
Filter rect attributes (eg `top`, `center`, `size`) from a dictionary. Useful
for passing kwargs to `pygame.Rect.move_to` or `pygame.Surface.get_rect`.
```python
def foo(image: Surface, **kwargs):
    image_rect = image.get_rect(**get_rect_attrs(kwargs))
```


## [`add_padding` function](pygskin/rect.py)
Add padding of varying amounts to a Rect.
```python
top, right, bottom, left = [100, 50, 10, 5]
padded, rect = add_padding(Rect(0, 0, 10, 10), [top, right, bottom, left])
assert padded.size == (120, 65)
assert rect.topleft == (5, 100)
```


## [`grid` function](pygskin/rect.py)
Divide a Rect into a specified number of rows and columns, and return a function
to access the cells by row/column index, or string aliases.
```python
get_cell = grid(
    Rect(0, 0, 100, 100),
    rows=2,
    cols=2,
    names={"nw": (0, 0), "ne": (1, 0), "sw": (0, 1), "se": (1, 1)},
)
assert get_cell("ne") == get_cell(1, 0) == Rect(50, 0, 50, 50)
```


## [`screen_manager` function](pygskin/screen.py)
Screen manager state machine.
```python
def main():
    return screen_manager(
        show_main_menu,
        play_level,
    )

def show_main_menu(surface, events, exit_screen):
    surface.blit(assets.main_menu)
    for event in events:
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                exit_screen()
            if event.key == pygame.K_RETURN:
                exit_screen(to=play_level)

def play_level(surface, events, exit_screen):
    ...
```


## [`shake` function](pygskin/shake.py)
Shake animation generator.
```python
rect = Rect(100, 100, 100, 100)
timer = Timer(3000)
shake_fn = shake()

def main_loop(screen, events, exit):
    screen.fill("black")
    timer.tick()
    pygame.draw.rect(screen, "red", rect.move(shake_fn(timer.quotient())))
```


## [`spritesheet` function](pygskin/spritesheet.py)
Provides grid cell access to a spritesheet image.
```python
get_sprite = spritesheet(pygame.image.load("foo.png"), rows=3, cols=4)
screen.blit(get_sprite(2, 1))
walk_frames = [get_sprite(0, i) for i in range(4)]
walk_anim = animate(walk_frames, timer.quotient)
```


## [`draw_sprite_stack` function](pygskin/spritestack.py)
Draw a pseudo-3d sprite using sprite-stacking.
```python
draw_sprite_stack(
    screen,
    spritesheet(assets.player, rows=1, cols=8),
    (100, 100),
    spacing=3,
)
```


## [`statemachine` function](pygskin/statemachine.py)
State machine as generator.


## [`get_styles` function](pygskin/stylesheet.py)
Simple cascading style sheet engine. Filters styles by object type, class and id
attributes. Can be used with imgui module.
```yaml
# styles.yaml
"*":
  color: black
  background_color: grey

"#error":
  background_color: red
```
```python
# cascading styles
stylesheet = partial(get_styles, assets.styles)
Foo = namedtuple("Foo", ["id"])
styles = stylesheet(Foo(id="error"))
assert styles["background_color"] == "red"

# use with imgui
with imgui.render(gui, surface, stylesheet) as render:
    render(imgui.button("Click me!"), center=(100, 100))
```


## [`make_sprite` function](pygskin/surface.py)
Create a sprite from an image.
```python
player = make_sprite(assets.player, center=player_pos)
```


## [`rotate_surface` function](pygskin/surface.py)
Rotate a surface in place or around a specified point.
```python
rotated_image = rotate_surface(image, angle, center=(0, 0))
```


## [`to_snakecase` function](pygskin/text.py)
Convert CapWords to snake_case.


## [`speech_duration` function](pygskin/text.py)
Calculate rough speech duration in seconds.


## [`tile` function](pygskin/tile.py)
Generate a blit sequence to tile an image across a surface.
```python
screen.blits(tile(screen.get_rect(), assets.grass))
```


## [`angle_between` function](pygskin/vector.py)
Calculate the angle between two points.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "Pygskin",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": "Andy Driver <andy@pagezero.net>",
    "keywords": "framework, game, pygame",
    "author": null,
    "author_email": "Andy Driver <andy@pagezero.net>",
    "download_url": "https://files.pythonhosted.org/packages/c2/a6/ae196469dd5c9f3606de7b90bdef9e79ebaa6912a48d695128abaf86d181/pygskin-0.3.0.tar.gz",
    "platform": null,
    "description": "# Pygskin\n\nA collection of useful functions and classes for Pygame\n\n## [`animate` function](pygskin/animation.py)\nAnimation generator function which takes a list of frames or mapping of\nquotients (0.0 - 1.0) to keyframes and a function that returns a quotient, and\nreturns an generator that returns frames.\n```python\nanim = animate([image1, image2], timer.quotient)\nscreen.blit(next(anim))\n```\n\n\n## [`Assets` class](pygskin/assets.py)\nProvides attribute access to asset files and batch loading\n```python\nassets = Assets()\nscreen.blit(assets.player)\nassets.player_spawn_sfx.play()\n```\n\n\n## [`Camera` class](pygskin/camera.py)\nA camera class for scrolling and zooming a surface.\n```python\ncamera = Camera(screen.get_rect(), clamp=world_map.get_rect())\ncamera.view.fill(\"black\")\nsprite_group.draw(camera)\ncamera.zoom = 2.4\ncamera.draw(screen)\n```\n\n## [`Timer` class](pygskin/clock.py)\nA countdown timer dataclass. Can be used with the `animate` function.\n```python\ntimer = Timer(3000)  # 3 seconds\ntimer.tick()\nif timer.finished:\n    timer.elapsed = 0  # loop\n```\n\n\n## [`iter_dialogue` function](pygskin/dialogue.py)\nGenerator function for stepping through a dialogue script parsed from a JSON or\nYAML file.\n```python\ncontext = {}\ndialogue = iter_dialogue(\n    assets.act1_scene1,\n    context,\n    speak=speak,\n)\n\ndef main_loop(screen, events, quit):\n    if action := next(dialogue, None):\n        action()\n```\n\n\n## [`Direction` enum](pygskin/direction.py)\nEnum for up/down/left/right directions\n```python\ndirection = Direction.UP\nif direction in Direction.VERTICAL:\n    rect.move_ip(direction.vector)\n```\n\n\n## [`easing` module](pygskin/easing.py)\nA selection of easing functions for use with interpolation. Can be used with the\n`animate` and `make_color_gradient` functions.\n\n\n## [`Component` class](pygskin/ecs.py)\nA minimal ECS implementation.\n```python\nclass Velocity(Component[Vector2]): ...\nclass Position(Component[Vector2]): ...\n\ndef apply_velocity_system() -> None:\n    for id, velocity in Velocity.components.items():\n        pos = Position.components[id]\n        pos += velocity\n\n@dataclass\nclass Entity:\n    pos: Position = Position()\n    velocity: Velocity = Velocity()\n\nentities = [Entity(pos=Vector2(0, 0), velocity=Vector2(1, 1)])\n\napply_velocity_system()\n```\n\n\n## [`bind` function](pygskin/func.py)\nPartial function application with one or more argument placeholders at arbitrary\npositions.\n```python\nfoos = filter(bind(isinstance, ..., Foo), items)\n```\n\n\n## [`run_game` function](pygskin/game.py)\nPygbag compatible game loop.\n```python\ndef main_loop(screen, events, exit):\n    screen.fill(random.choice(pygame.color.THECOLORS.values()))\n\n    for event in events:\n        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:\n            exit()\n\n\nif __name__ == '__main__':\n    run_game(Window(\"My Game\", (WIDTH, HEIGHT)), main_loop)\n```\n\n\n## [`make_color_gradient` function](pygskin/gradient.py)\nGenerate a color gradient between two colors.\n```python\nsky_image = make_color_gradient(screen.size, \"white\", \"blue\")\nscreen.blit(sky_image)\n```\n\n\n## [`imgui` module](pygskin/imgui.py)\nImmediate mode GUI.\n```python\ngui = imgui.IMGUI()\n\ndef main_loop(screen, events, exit):\n    with imgui.render(gui, screen) as render:\n        if render(imgui.button(\"Quit\"), center=(100, 200)):\n            exit()\n```\n\n\n## [`map_inputs_to_actions` function](pygskin/input.py)\nMap input events to actions. Enables user-defined key bindings.\n```python\nkeyboard_controls = {\n    \"jump\": Event(pg.KEYDOWN, key=pg.K_UP),\n    \"duck\": Event(pg.KEYDOWN, key=pg.K_DOWN),\n    \"quit\": Event(pg.KEYDOWN, key=pg.K_ESCAPE),\n}\nfor action in map_inputs_to_actions(\n    keyboard_controls,\n    pygame.event.get(),\n):\n    if action == \"jump\":\n        player.jump()\n    if action == \"duck\":\n        player.duck()\n    if action == \"quit\":\n        exit()\n```\n\n\n## [`lazy` class](pygskin/lazy.py)\nLazy loading object proxy. Works like a partial function application for\nobjects.\n```python\nimage = lazy(pygame.image.load, \"foo.png\"))\nscreen.blit(image)\n```\n\n\n## [`scroll_parallax_layers` function](pygskin/parallax.py)\nScroll parallax layers at different rates.\n```python\nbackground = LayeredUpdates()\nbackground.add(assets.sky, layer=0)\nbackground.add(assets.mountains, layer=1)\nbackground.add(assets.trees, layer=2)\n\nscroll_parallax_layers(\n    (vx, vy),\n    background.layers,\n    background.get_sprites_from_layer,\n    {0: 0, 1: 1.5, 2: 2.0},\n)\n```\n\n\n## [`channel` function](pygskin/pubsub.py)\nSimple pubsub implementation.\n```python\nfoo = channel()\nfoo.subscribe(lambda x: print(f\"subscriber 1: {x}\"))\nfoo(\"bar\")\n```\n\n\n## [`get_rect_attrs` function](pygskin/rect.py)\nFilter rect attributes (eg `top`, `center`, `size`) from a dictionary. Useful\nfor passing kwargs to `pygame.Rect.move_to` or `pygame.Surface.get_rect`.\n```python\ndef foo(image: Surface, **kwargs):\n    image_rect = image.get_rect(**get_rect_attrs(kwargs))\n```\n\n\n## [`add_padding` function](pygskin/rect.py)\nAdd padding of varying amounts to a Rect.\n```python\ntop, right, bottom, left = [100, 50, 10, 5]\npadded, rect = add_padding(Rect(0, 0, 10, 10), [top, right, bottom, left])\nassert padded.size == (120, 65)\nassert rect.topleft == (5, 100)\n```\n\n\n## [`grid` function](pygskin/rect.py)\nDivide a Rect into a specified number of rows and columns, and return a function\nto access the cells by row/column index, or string aliases.\n```python\nget_cell = grid(\n    Rect(0, 0, 100, 100),\n    rows=2,\n    cols=2,\n    names={\"nw\": (0, 0), \"ne\": (1, 0), \"sw\": (0, 1), \"se\": (1, 1)},\n)\nassert get_cell(\"ne\") == get_cell(1, 0) == Rect(50, 0, 50, 50)\n```\n\n\n## [`screen_manager` function](pygskin/screen.py)\nScreen manager state machine.\n```python\ndef main():\n    return screen_manager(\n        show_main_menu,\n        play_level,\n    )\n\ndef show_main_menu(surface, events, exit_screen):\n    surface.blit(assets.main_menu)\n    for event in events:\n        if event.type == pygame.KEYDOWN:\n            if event.key == pygame.K_ESCAPE:\n                exit_screen()\n            if event.key == pygame.K_RETURN:\n                exit_screen(to=play_level)\n\ndef play_level(surface, events, exit_screen):\n    ...\n```\n\n\n## [`shake` function](pygskin/shake.py)\nShake animation generator.\n```python\nrect = Rect(100, 100, 100, 100)\ntimer = Timer(3000)\nshake_fn = shake()\n\ndef main_loop(screen, events, exit):\n    screen.fill(\"black\")\n    timer.tick()\n    pygame.draw.rect(screen, \"red\", rect.move(shake_fn(timer.quotient())))\n```\n\n\n## [`spritesheet` function](pygskin/spritesheet.py)\nProvides grid cell access to a spritesheet image.\n```python\nget_sprite = spritesheet(pygame.image.load(\"foo.png\"), rows=3, cols=4)\nscreen.blit(get_sprite(2, 1))\nwalk_frames = [get_sprite(0, i) for i in range(4)]\nwalk_anim = animate(walk_frames, timer.quotient)\n```\n\n\n## [`draw_sprite_stack` function](pygskin/spritestack.py)\nDraw a pseudo-3d sprite using sprite-stacking.\n```python\ndraw_sprite_stack(\n    screen,\n    spritesheet(assets.player, rows=1, cols=8),\n    (100, 100),\n    spacing=3,\n)\n```\n\n\n## [`statemachine` function](pygskin/statemachine.py)\nState machine as generator.\n\n\n## [`get_styles` function](pygskin/stylesheet.py)\nSimple cascading style sheet engine. Filters styles by object type, class and id\nattributes. Can be used with imgui module.\n```yaml\n# styles.yaml\n\"*\":\n  color: black\n  background_color: grey\n\n\"#error\":\n  background_color: red\n```\n```python\n# cascading styles\nstylesheet = partial(get_styles, assets.styles)\nFoo = namedtuple(\"Foo\", [\"id\"])\nstyles = stylesheet(Foo(id=\"error\"))\nassert styles[\"background_color\"] == \"red\"\n\n# use with imgui\nwith imgui.render(gui, surface, stylesheet) as render:\n    render(imgui.button(\"Click me!\"), center=(100, 100))\n```\n\n\n## [`make_sprite` function](pygskin/surface.py)\nCreate a sprite from an image.\n```python\nplayer = make_sprite(assets.player, center=player_pos)\n```\n\n\n## [`rotate_surface` function](pygskin/surface.py)\nRotate a surface in place or around a specified point.\n```python\nrotated_image = rotate_surface(image, angle, center=(0, 0))\n```\n\n\n## [`to_snakecase` function](pygskin/text.py)\nConvert CapWords to snake_case.\n\n\n## [`speech_duration` function](pygskin/text.py)\nCalculate rough speech duration in seconds.\n\n\n## [`tile` function](pygskin/tile.py)\nGenerate a blit sequence to tile an image across a surface.\n```python\nscreen.blits(tile(screen.get_rect(), assets.grass))\n```\n\n\n## [`angle_between` function](pygskin/vector.py)\nCalculate the angle between two points.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": null,
    "version": "0.3.0",
    "project_urls": {
        "documentation": "https://github.com/andyhd/pygskin/blob/main/README.md",
        "homepage": "https://github.com/andyhd/pygskin",
        "issues": "https://github.com/andyhd/pygskin/issues",
        "repository": "https://github.com/andyhd/pygskin"
    },
    "split_keywords": [
        "framework",
        " game",
        " pygame"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d74c427bbcb061be35df2135b4ef5862e7745aca32caab66f86a90b7c128c614",
                "md5": "90af315d2e3962058ba3fb4e251eaf25",
                "sha256": "64dc2bd3cabbed89c2bb13e4293ee7a199a2a1784240a2e4b96b17294f546eaf"
            },
            "downloads": -1,
            "filename": "pygskin-0.3.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "90af315d2e3962058ba3fb4e251eaf25",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 26886,
            "upload_time": "2025-02-10T23:41:30",
            "upload_time_iso_8601": "2025-02-10T23:41:30.297555Z",
            "url": "https://files.pythonhosted.org/packages/d7/4c/427bbcb061be35df2135b4ef5862e7745aca32caab66f86a90b7c128c614/pygskin-0.3.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c2a6ae196469dd5c9f3606de7b90bdef9e79ebaa6912a48d695128abaf86d181",
                "md5": "af0cdfdddd00b2f6cdbfc3d500c37ba3",
                "sha256": "c45066b89bbc97f02e26df876cd8bed900d9a2c0a5899ea1b41eb8d3418e4182"
            },
            "downloads": -1,
            "filename": "pygskin-0.3.0.tar.gz",
            "has_sig": false,
            "md5_digest": "af0cdfdddd00b2f6cdbfc3d500c37ba3",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 29402,
            "upload_time": "2025-02-10T23:41:32",
            "upload_time_iso_8601": "2025-02-10T23:41:32.220544Z",
            "url": "https://files.pythonhosted.org/packages/c2/a6/ae196469dd5c9f3606de7b90bdef9e79ebaa6912a48d695128abaf86d181/pygskin-0.3.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-10 23:41:32",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "andyhd",
    "github_project": "pygskin",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "pygame-ce",
            "specs": []
        }
    ],
    "lcname": "pygskin"
}
        
Elapsed time: 2.05277s