Pygskin


NamePygskin JSON
Version 0.2.1 PyPI version JSON
download
home_pageNone
SummaryNone
upload_time2025-01-16 00:28:19
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), (0, 0))
```


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


## [`Timer` class](pygskin/timer.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` function.


## [`get_ecs_update_fn` function](pygskin/ecs.py)
An extremely simple ECS implementation.
```python
@filter_entities(has_velocity)
def apply_velocity(entity):
    entity.pos += entity.velocity

ecs_update = get_ecs_update_fn([apply_velocity])

@dataclass
class Entity:
    pos: Vector2
    velocity: Vector2

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


## [`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, (0, 0))
```


## [`rhash`/`unrhash` functions](pygskin/hash.py)
Simple reversible hash function for generating unique IDs.
```python
id = rhash("foo")
assert unrhash(id) == "foo"
```


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

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


## [`lazy` class](pygskin/lazy.py)
Lazy loading object proxy.
```python
image = lazy(lambda: pygame.image.load("foo.png"))
screen.blit(image, (0, 0))
```


## [`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_title: [start_level, enter_level_code],
            show_code_prompt: [start_level, return_to_titles],
            play_level: [end_level],
            show_game_over: [return_to_titles],
        }
    )

def show_main_menu(surface, events, exit):
    surface.blit(assets.main_menu, (0, 0))
    for event in events:
        if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
            exit("start_level")
        if event.type == pygame.KEYDOWN and event.key == pygame.K_c:
            exit("enter_code")

def start_level(input):
    return play_level if input == "start_level" else None

def enter_level_code(input):
    return show_code_prompt if input == "enter_code" else None
```


## [`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), (0, 0))
walk_frames = [get_sprite(0, i) for i in range(4)]
walk_anim = animate(walk_frames, timer.quotient)
```


## [`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` and `snakecase_to_capwords` functions](pygskin/text.py)
Convert between snake_case and CapWords.


## [`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/8a/9d/922be33de3387f42cecb499f55d383ccd67a03d7d1f0fd0101f28ad14048/pygskin-0.2.1.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), (0, 0))\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, (0, 0))\nassets.player_spawn_sfx.play()\n```\n\n\n## [`Timer` class](pygskin/timer.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` function.\n\n\n## [`get_ecs_update_fn` function](pygskin/ecs.py)\nAn extremely simple ECS implementation.\n```python\n@filter_entities(has_velocity)\ndef apply_velocity(entity):\n    entity.pos += entity.velocity\n\necs_update = get_ecs_update_fn([apply_velocity])\n\n@dataclass\nclass Entity:\n    pos: Vector2\n    velocity: Vector2\n\necs_update([Entity(pos=Vector2(0, 0), velocity=Vector2(1, 1)])\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, (0, 0))\n```\n\n\n## [`rhash`/`unrhash` functions](pygskin/hash.py)\nSimple reversible hash function for generating unique IDs.\n```python\nid = rhash(\"foo\")\nassert unrhash(id) == \"foo\"\n```\n\n\n## [`imgui` module](pygskin/imgui.py)\nImmediate mode GUI.\n```python\ngui = imgui.IMGUI()\n\ndef main_loop(screen, events, quit):\n    with imgui.render(gui, screen) as render:\n        if render(imgui.button(\"Quit\"), center=(100, 200)):\n            break\n```\n\n\n## [`lazy` class](pygskin/lazy.py)\nLazy loading object proxy.\n```python\nimage = lazy(lambda: pygame.image.load(\"foo.png\"))\nscreen.blit(image, (0, 0))\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        {\n            show_title: [start_level, enter_level_code],\n            show_code_prompt: [start_level, return_to_titles],\n            play_level: [end_level],\n            show_game_over: [return_to_titles],\n        }\n    )\n\ndef show_main_menu(surface, events, exit):\n    surface.blit(assets.main_menu, (0, 0))\n    for event in events:\n        if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:\n            exit(\"start_level\")\n        if event.type == pygame.KEYDOWN and event.key == pygame.K_c:\n            exit(\"enter_code\")\n\ndef start_level(input):\n    return play_level if input == \"start_level\" else None\n\ndef enter_level_code(input):\n    return show_code_prompt if input == \"enter_code\" else None\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), (0, 0))\nwalk_frames = [get_sprite(0, i) for i in range(4)]\nwalk_anim = animate(walk_frames, timer.quotient)\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` and `snakecase_to_capwords` functions](pygskin/text.py)\nConvert between snake_case and CapWords.\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.2.1",
    "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": "",
            "digests": {
                "blake2b_256": "e9520ac393b37e64730bf27e0906c12fa4e3e52641c3d1c6506bad122826e1e5",
                "md5": "71759134866a43d2bd4e48fa9f2ff0e1",
                "sha256": "bdbfea6ec81385f56b2606c46c0ff2077e262480fb13397662dd9229e8484b3c"
            },
            "downloads": -1,
            "filename": "pygskin-0.2.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "71759134866a43d2bd4e48fa9f2ff0e1",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 23913,
            "upload_time": "2025-01-16T00:28:16",
            "upload_time_iso_8601": "2025-01-16T00:28:16.925442Z",
            "url": "https://files.pythonhosted.org/packages/e9/52/0ac393b37e64730bf27e0906c12fa4e3e52641c3d1c6506bad122826e1e5/pygskin-0.2.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8a9d922be33de3387f42cecb499f55d383ccd67a03d7d1f0fd0101f28ad14048",
                "md5": "7ef3f8ace473b13bd5ea9416525ed2fd",
                "sha256": "8c6015f003e6abc81325fa9a663b3d2b7300aa36abf1509baf9091760b02598d"
            },
            "downloads": -1,
            "filename": "pygskin-0.2.1.tar.gz",
            "has_sig": false,
            "md5_digest": "7ef3f8ace473b13bd5ea9416525ed2fd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 18504,
            "upload_time": "2025-01-16T00:28:19",
            "upload_time_iso_8601": "2025-01-16T00:28:19.675474Z",
            "url": "https://files.pythonhosted.org/packages/8a/9d/922be33de3387f42cecb499f55d383ccd67a03d7d1f0fd0101f28ad14048/pygskin-0.2.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-01-16 00:28:19",
    "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: 0.42344s