Skip to content

Commit

Permalink
edit examples
Browse files Browse the repository at this point in the history
  • Loading branch information
gottadiveintopython committed Oct 16, 2024
1 parent 57d4e80 commit 88f0dbd
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 309 deletions.
41 changes: 22 additions & 19 deletions examples/06_full_blown_app_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import asyncpygame as apg
from asyncpygame.scene_switcher import SceneSwitcher, FadeTransition
from _uix.touch_indicator import touch_indicator
from _uix.anchor_layout import AnchorLayout
from _uix.ripple_button import RippleButton
from _uix.anchor_layout import anchor_layout
from _uix.ripple_button import ripple_button
from _uix.modal_dialog import ask_yes_no_question


Expand Down Expand Up @@ -47,17 +47,20 @@ async def title_scene(*, scene_switcher, userdata, **kwargs: Unpack[apg.CommonPa
target_rect = draw_target.get_rect()
font = userdata['font']
async with apg.open_nursery() as nursery:
AnchorLayout(
nursery,
e_start = apg.Event()
s = nursery.start
s(anchor_layout(
font.render("<Your App Title>", True, "white", userdata["bgcolor"]).convert(draw_target),
target_rect.scale_by(1.0, 0.5).move_to(y=target_rect.y),
priority=0x100, **kwargs)
start_button = RippleButton(
nursery,
priority=0x100,
**kwargs))
s(ripple_button(
button_image := font.render("Start", True, "white").convert_alpha(),
button_image.get_rect(center=target_rect.scale_by(1.0, 0.5).move_to(bottom=target_rect.bottom).center).inflate(80, 80),
priority=0x100, **kwargs)
await start_button.to_be_clicked()
on_click=e_start.fire,
priority=0x100,
**kwargs))
await e_start.wait()
scene_switcher.switch_to(menu_scene, FadeTransition())
await apg.sleep_forever()

Expand All @@ -67,20 +70,20 @@ async def menu_scene(*, scene_switcher, userdata, **kwargs: Unpack[apg.CommonPar
target_rect = draw_target.get_rect()
font = userdata['font']
async with apg.open_nursery() as nursery:
play_button = RippleButton(
nursery,
e_play = apg.Event()
e_back = apg.Event()
s = nursery.start
s(ripple_button(
button_image := font.render("Play Game", True, "white").convert_alpha(),
button_image.get_rect(center=target_rect.scale_by(1.0, 0.5).move_to(y=target_rect.y).center).inflate(80, 80),
priority=0x100, **kwargs)
back_button = RippleButton(
nursery,
on_click=e_play.fire,
priority=0x100, **kwargs))
s(ripple_button(
button_image := font.render("Back to Title", True, "white").convert_alpha(),
button_image.get_rect(center=target_rect.scale_by(1.0, 0.5).move_to(bottom=target_rect.bottom).center).inflate(80, 80),
priority=0x100, **kwargs)
tasks = await apg.wait_any(
play_button.to_be_clicked(),
back_button.to_be_clicked(),
)
on_click=e_back.fire,
priority=0x100, **kwargs))
tasks = await apg.wait_any(e_play.wait(), e_back.wait())
next_scene = title_scene if tasks[1].finished else game_scene
scene_switcher.switch_to(next_scene, FadeTransition())
await apg.sleep_forever()
Expand Down
59 changes: 12 additions & 47 deletions examples/_uix/anchor_layout.py
Original file line number Diff line number Diff line change
@@ -1,65 +1,30 @@
__all__ = ('AnchorLayout', )
__all__ = ('anchor_layout', )

from typing import Self
from functools import partial

from asyncgui import Nursery, sleep_forever
import asyncgui
from pygame import Surface, Rect


class AnchorLayout:
async def anchor_layout(
image: Surface, dest: Rect, priority, *, anchor_image="center", anchor_dest="center",
executor, draw_target, **__):
'''
.. code-block::
async with asyncpygame.open_nursery() as nursery:
image = Surface(...)
dest = Rect(...)
layout = AnchorLayout(nursery, image, dest, **common_params)
# Aligns the right edge of the image with the right edge of the layout.
layout.anchor_src = "right"
layout.anchor_dest = "right"
# Aligns the center of the image with the midtop of the layout.
layout.anchor_src = "center"
layout.anchor_dest = "midtop"
# You can change its image anytime.
layout.image = another_image
# You can move or resize the layout by updating the ``dest``.
dest.right = ...
dest.width = ...
# but you cannot assign another Rect instance to the layout.
layout.dest = another_rect # NOT ALLOWED
nursery.start(anchor_layout(image, dest, priority=..., **common_params))
'''
def __init__(self, owner: Nursery, image: Surface, dest: Rect,
*, anchor_src="center", anchor_dest="center", **common_params):
'''
:param owner: AnchorLayout cannot outlive its owner. When the owner is closed, the sprite is destroyed.
:param anchor_src: This must be any of the ``Rect``s positional attribute names. (e.g. "topleft", "bottomleft", ...)
:param anchor_dest: Same as ``anchor_src``.
'''
self._dest = dest
self.image = image
self.anchor_src = anchor_src
self.anchor_dest = anchor_dest
self._main_task = owner.start(self._main(**common_params), daemon=True)

def kill(self):
self._main_task.cancel()
with executor.register(partial(_draw, draw_target.blit, image, image.get_rect(), dest, anchor_image, anchor_dest), priority):
await asyncgui.sleep_forever()

@property
def dest(self) -> Rect:
return self._dest

async def _main(self, *, priority, draw_target, executor, **unused):
with executor.register(partial(self._draw, draw_target.blit, self._dest, self), priority=priority):
await sleep_forever()
def _draw(getattr, setattr, blit, image, src: Rect, dest: Rect, anchor_image, anchor_dest):
setattr(src, anchor_image, getattr(dest, anchor_dest))
blit(image, src)

def _draw(getattr, blit, dest, self: Self):
image = self.image
blit(image, image.get_rect(**{self.anchor_src: getattr(dest, self.anchor_dest)}))

_draw = partial(_draw, getattr)
_draw = partial(_draw, getattr, setattr)
89 changes: 49 additions & 40 deletions examples/_uix/modal_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@
from functools import partial

import asyncgui
from pygame import Rect
from pygame.colordict import THECOLORS
from pygame import Rect, Surface
from pygame.font import SysFont

from asyncpygame import CommonParams, block_input_events, Clock
from _uix.ripple_button import RippleButton
from _uix.anchor_layout import AnchorLayout
from _uix.ripple_button import ripple_button
from _uix.anchor_layout import anchor_layout


@asynccontextmanager
async def darken(*, priority, **kwargs: Unpack[CommonParams]):
interpolate = kwargs["clock"].interpolate_scalar
draw_target = kwargs["draw_target"]
overlay_surface = draw_target.copy()
overlay_surface.fill("black")
overlay_surface = Surface(draw_target.size)
set_alpha = overlay_surface.set_alpha
with kwargs["executor"].register(partial(draw_target.blit, overlay_surface), priority):
async for v in interpolate(0, 180, duration=200):
Expand All @@ -28,22 +28,22 @@ async def darken(*, priority, **kwargs: Unpack[CommonParams]):
set_alpha(v)


async def translate_rects_vertically(clock: Clock, rects, movement, duration):
async def move_rects_vertically(clock: Clock, rects, movement, duration):
org_ys = tuple(rect.y for rect in rects)
async for v in clock.interpolate_scalar(0, movement, duration=duration):
for rect, org_y in zip(rects, org_ys):
rect.y = org_y + v


async def show_messagebox(
message, *, dialog_size: Rect=None, font=None, text_ok='OK',
priority, **kwargs: Unpack[CommonParams]) -> bool:
message, priority, *, dialog_size: Rect=None, font=None, text_ok='OK',
**kwargs: Unpack[CommonParams]) -> bool:
'''
.. code-block::
await show_messagebox("Hello World", priority=0xFFFFFA00, **kwargs)
'''
bgcolor = "grey90"
bgcolor = THECOLORS["grey90"]
clock = kwargs["clock"]
draw_target = kwargs["draw_target"]
if font is None:
Expand All @@ -56,33 +56,37 @@ async def show_messagebox(
dialog_size = target_rect.inflate(-100, 0)
dialog_size.height = dialog_size.width // 2
dialog_dest = dialog_size.move_to(bottom=target_rect.top)
e_ok = asyncgui.Event()
with kwargs["executor"].register(partial(draw_target.fill, bgcolor, dialog_dest), priority=priority + 1):
label = AnchorLayout(
nursery,
s = nursery.start
s(anchor_layout(
font.render(message, True, "black", bgcolor).convert(draw_target),
dialog_dest.scale_by(1.0, 0.7).move_to(top=dialog_dest.top).inflate(-10, -10),
priority=priority + 2, **kwargs)
ok_button = RippleButton(
nursery,
label_dest := dialog_dest.scale_by(1.0, 0.7).move_to(top=dialog_dest.top).inflate(-10, -10),
priority + 2,
**kwargs), daemon=True)
s(ripple_button(
font.render(text_ok, True, "white"),
dialog_dest.scale_by(0.5, 0.3).move_to(midbottom=dialog_dest.midbottom).inflate(-20, -20),
priority=priority + 2, **kwargs)
rects = (dialog_dest, label.dest, ok_button.dest, )
button_dest := dialog_dest.scale_by(0.5, 0.3).move_to(midbottom=dialog_dest.midbottom).inflate(-20, -20),
priority + 2,
on_click=e_ok.fire,
**kwargs), daemon=True)
rects = (dialog_dest, label_dest, button_dest, )
y_movement = target_rect.centery - dialog_dest.centery
await translate_rects_vertically(clock, rects, y_movement, duration=200)
await ok_button.to_be_clicked()
await translate_rects_vertically(clock, rects, -y_movement, duration=200)
await move_rects_vertically(clock, rects, y_movement, duration=200)
await e_ok.wait()
await move_rects_vertically(clock, rects, -y_movement, duration=200)
return


async def ask_yes_no_question(
question, *, dialog_size: Rect=None, font=None, text_yes='Yes', text_no='No',
priority, **kwargs: Unpack[CommonParams]) -> bool:
question, priority, *, dialog_size: Rect=None, font=None, text_yes='Yes', text_no='No',
**kwargs: Unpack[CommonParams]) -> bool:
'''
.. code-block::
result = await ask_yes_no_question("Do you like PyGame?", priority=0xFFFFFA00, **kwargs)
'''
bgcolor = "grey90"
bgcolor = THECOLORS["grey90"]
clock = kwargs["clock"]
draw_target = kwargs["draw_target"]
if font is None:
Expand All @@ -95,25 +99,30 @@ async def ask_yes_no_question(
dialog_size = target_rect.inflate(-100, 0)
dialog_size.height = dialog_size.width // 2
dialog_dest = dialog_size.move_to(bottom=target_rect.top)
e_yes = asyncgui.Event()
e_no = asyncgui.Event()
with kwargs["executor"].register(partial(draw_target.fill, bgcolor, dialog_dest), priority=priority + 1):
label = AnchorLayout(
nursery,
s = nursery.start
s(anchor_layout(
font.render(question, True, "black", bgcolor).convert(draw_target),
dialog_dest.scale_by(1.0, 0.5).move_to(top=dialog_dest.top).inflate(-10, -10),
priority=priority + 2, **kwargs)
yes_button = RippleButton(
nursery,
label_dest := dialog_dest.scale_by(1.0, 0.5).move_to(top=dialog_dest.top).inflate(-10, -10),
priority + 2,
**kwargs), daemon=True)
s(ripple_button(
font.render(text_yes, True, "white"),
dialog_dest.scale_by(0.5, 0.5).move_to(bottomright=dialog_dest.bottomright).inflate(-20, -20),
priority=priority + 2, **kwargs)
no_button = RippleButton(
nursery,
yes_button_dest := dialog_dest.scale_by(0.5, 0.5).move_to(bottomright=dialog_dest.bottomright).inflate(-20, -20),
priority + 2,
on_click=e_yes.fire,
**kwargs), daemon=True)
s(ripple_button(
font.render(text_no, True, "white"),
dialog_dest.scale_by(0.5, 0.5).move_to(bottomleft=dialog_dest.bottomleft).inflate(-20, -20),
priority=priority + 2, **kwargs)
rects = (dialog_dest, label.dest, yes_button.dest, no_button.dest, )
no_button_dest := dialog_dest.scale_by(0.5, 0.5).move_to(bottomleft=dialog_dest.bottomleft).inflate(-20, -20),
priority + 2,
on_click=e_no.fire,
**kwargs), daemon=True)
rects = (dialog_dest, label_dest, yes_button_dest, no_button_dest, )
y_movement = target_rect.centery - dialog_dest.centery
await translate_rects_vertically(clock, rects, y_movement, duration=200)
tasks = await asyncgui.wait_any(yes_button.to_be_clicked(), no_button.to_be_clicked())
await translate_rects_vertically(clock, rects, -y_movement, duration=200)
await move_rects_vertically(clock, rects, y_movement, duration=200)
tasks = await asyncgui.wait_any(e_yes.wait(), e_no.wait())
await move_rects_vertically(clock, rects, -y_movement, duration=200)
return tasks[0].finished
2 changes: 1 addition & 1 deletion examples/_uix/progress_spinner.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def _draw(pygame_draw_arc, draw_target, color, rect, line_width, self: Self):
_draw = partial(_draw, pygame.draw.arc)


async def progress_spinner(dest: Rect, *, color="white", line_width=20, min_arc_angle=0.3, speed=1.0, priority, **kwargs):
async def progress_spinner(dest: Rect, priority, *, color="white", line_width=20, min_arc_angle=0.3, speed=1.0, **kwargs):
R1 = 0.4
R2 = math.tau - min_arc_angle * 2
next_start = itertools.accumulate(itertools.cycle((R1, R1, R1 + R2, R1, )), initial=0).__next__
Expand Down
Loading

0 comments on commit 88f0dbd

Please sign in to comment.