Exemple #1
0
def append_wobbly_star_shape(group: displayio.Group, color):
    # Make a wobbly star.  The returned function wobbles its points a little.
    wobbly_star_points = [
        (8, 50),
        (33, 0),
        (58, 50),
        (0, 20),
        (66, 20),
    ]
    star_center_x = 170 - 25
    star_center_y = 120 - 33
    wobbly_star_polygon = vectorio.Polygon(points=wobbly_star_points)
    wobbly_star_shape = vectorio.VectorShape(shape=wobbly_star_polygon,
                                             pixel_shader=monochrome(color),
                                             x=star_center_x,
                                             y=star_center_y)
    group.append(wobbly_star_shape)

    def make_star_wobble():
        tremble = 4
        shake = 3
        trembling_points = [(random.randrange(x - tremble, x + tremble),
                             random.randrange(y - tremble, y + tremble))
                            for x, y in wobbly_star_points]
        wobbly_star_polygon.points = trembling_points
        wobbly_star_shape.x = random.randrange(star_center_x - shake,
                                               star_center_x + shake)
        wobbly_star_shape.y = random.randrange(star_center_y - shake,
                                               star_center_y + shake)

    return make_star_wobble
Exemple #2
0
def show_image(path):
    with open(path, 'rb') as f:
        bitmap = OnDiskBitmap(f)
        pixel_shader = ColorConverter()
        sprite = TileGrid(bitmap, pixel_shader=pixel_shader)
        group = Group()
        group.append(sprite)
        board.DISPLAY.show(group)
        board.DISPLAY.wait_for_frame()
Exemple #3
0
def build(
    widget: Label,
    *,
    size: float | int,
    align: align,
    fit_to: bool | str,
) -> tuple[Group, SizeHint]:

    assert isinstance(size, int), (
        "for now, text size on circuitpython must be an " +
        f"int, found object of type {type(size).__name__} with value size={size}"
    )

    is_state = isinstance(widget._text, str)

    LabelType: Type[LabelBase] = BitmapLabel if is_state else GlyphLabel
    kwargs = {"save_text": False} if is_state else {}

    # print(
    #     widget,
    #     widget.text,
    # )
    native_label: LabelBase = LabelType(
        font=FONT,
        text=fit_to if isinstance(fit_to, str) else widget.text,
        scale=size,
        **kwargs,
    )

    native = Group()
    native.append(native_label)

    widget._impl_cache_ = (size, align)

    margin = widget._margin_

    # w, h = (
    #     native_label.bounding_box[2],
    #     native_label.bounding_box[3],
    # )

    # print(
    #     widget,
    #     w / len(widget.text),
    #     (w, h),
    # ),
    return (
        native,
        (
            int(1.15 * native_label.bounding_box[2] * size) + margin * 2,
            int(1.15 * native_label.bounding_box[3] * size) + margin * 2,
        ),
    )
Exemple #4
0
def append_randart_shape(group: displayio.Group, color):
    # Make a random polygon to sit on the left side of the screen.
    # We'll update its points every now and then with the returned function.
    random_polygon = vectorio.Polygon(points=[(random.randrange(0, 100),
                                               random.randrange(0, 240))
                                              for _ in range(40)])
    random_shape = vectorio.VectorShape(
        shape=random_polygon,
        pixel_shader=monochrome(color),
    )
    group.append(random_shape)

    def new_randart():
        random_polygon.points = [(random.randrange(0, 100),
                                  random.randrange(0, 240)) for _ in range(40)]

    return new_randart
Exemple #5
0
def append_vectorio_shape(group: displayio.Group, color):
    # Making fonts with vector points is a pain but the memory benefits are pretty nice.
    # Also you can rotate points for spinny text if you want!
    v_polygon = vectorio.Polygon(points=[
        (0, 0),
        (10, 0),
        (18, 24),
        (26, 0),
        (36, 0),
        (22, 34),
        (10, 34),
    ])
    v_shape = vectorio.VectorShape(shape=v_polygon,
                                   pixel_shader=monochrome(color),
                                   x=160,
                                   y=16)
    group.append(v_shape)
    def showChoice(self,
                   ch_idx,
                   game_no=None,
                   round_no=None,
                   rounds_tot=None,
                   won_sf=None,
                   drew_sf=None,
                   lost_sf=None):
        """Show player's choice on NeoPixels or display.
           The display also has game and round info and win/draw summary.
           This removes all the graphical objects and re-adds them which
           causes visible flickering during an update - this could be
           improved by only replacing / updating what needs changing.
        """
        if self.disp is None:
            self.pix.fill(BLACK)
            self.pix[self.choiceToPixIdx(ch_idx)] = CHOICE_COL[ch_idx]
            return

        self.emptyGroup(self.disp_group)
        # Would be slightly better to create this Group once and re-use it
        round_choice_group = Group(max_size=3)

        if round_no is not None:
            title_dob = Label(self.font,
                              text="Game {:d}  Round {:d}/{:d}".format(
                                  game_no, round_no, rounds_tot),
                              scale=2,
                              color=TITLE_TXT_COL_FG)
            title_dob.x = round(
                (self.width - len(title_dob.text) * 2 * self.font_width) // 2)
            title_dob.y = round(self.font_height // 2)
            round_choice_group.append(title_dob)

        if won_sf is not None:
            gamesum_dob = Label(self.font,
                                text="Won {:d} Drew {:d} Lost {:d}".format(
                                    won_sf, drew_sf, lost_sf),
                                scale=2,
                                color=TITLE_TXT_COL_FG)
            gamesum_dob.x = round(
                (self.width - len(gamesum_dob.text) * 2 * self.font_width) //
                2)
            gamesum_dob.y = round(self.height - 2 * self.font_height // 2)
            round_choice_group.append(gamesum_dob)

        s_group = Group(scale=3, max_size=1)
        s_group.x = 32
        s_group.y = (self.height - 3 * self.sprite_size) // 2
        s_group.append(self.sprites[ch_idx])
        round_choice_group.append(s_group)

        self.showGroup(round_choice_group)
Exemple #7
0
def append_circle_shape(group: displayio.Group, color):
    # Make a circle that will revolve around the star while changing size
    min_circle_radius = 5
    max_circle_radius = 20
    circle_axis = 170, 120
    circle_revolution_radius = 60
    circle = vectorio.Circle(radius=max_circle_radius)
    circle_shape = vectorio.VectorShape(shape=circle,
                                        pixel_shader=monochrome(color),
                                        x=circle_axis[0],
                                        y=circle_axis[1])
    group.append(circle_shape)

    radians_in_circle = 2 * math.pi

    def revolve_circle():
        seconds_per_revolution = 8
        revolution_ratio = (time.monotonic() %
                            seconds_per_revolution) / seconds_per_revolution
        revolution_radians = revolution_ratio * radians_in_circle
        s = math.sin(revolution_radians)
        c = math.cos(revolution_radians)
        x = s * circle_revolution_radius + circle_axis[0]
        y = c * circle_revolution_radius + circle_axis[1]
        circle_shape.x = round(x)
        circle_shape.y = round(y)

    def resize_circle():
        seconds_per_size_cycle = 13
        size_ratio = abs(
            int(time.monotonic() %
                (2 * seconds_per_size_cycle) / seconds_per_size_cycle) -
            time.monotonic() % seconds_per_size_cycle / seconds_per_size_cycle)
        new_radius = min_circle_radius + size_ratio * (max_circle_radius -
                                                       min_circle_radius)
        circle.radius = int(new_radius)

    return revolve_circle, resize_circle
    def showChoice(self,
                   ch_idx,
                   game_no=None,
                   round_no=None,
                   rounds_tot=None,
                   won_sf=None,
                   drew_sf=None,
                   lost_sf=None):
        """TODO DOC"""
        if self.disp is None:
            self.pix.fill(BLACK)
            self.pix[self.choiceToPixIdx(ch_idx)] = CHOICE_COL[ch_idx]
            return

        self.emptyGroup(self.disp_group)
        ### Would be slightly better to create this Group once and re-use it
        round_choice_group = Group(max_size=3)

        if round_no is not None:
            title_dob = Label(self.font,
                              text="Game {:d}  Round {:d}/{:d}".format(
                                  game_no, round_no, rounds_tot),
                              scale=2,
                              color=TITLE_TXT_COL_FG)
            title_dob.x = round(
                (self.width - len(title_dob.text) * 2 * self.font_width) // 2)
            title_dob.y = round(self.font_height // 2)
            round_choice_group.append(title_dob)

        if won_sf is not None:
            gamesum_dob = Label(self.font,
                                text="Won {:d} Drew {:d} Lost {:d}".format(
                                    won_sf, drew_sf, lost_sf),
                                scale=2,
                                color=TITLE_TXT_COL_FG)
            gamesum_dob.x = round(
                (self.width - len(gamesum_dob.text) * 2 * self.font_width) //
                2)
            gamesum_dob.y = round(self.height - 2 * self.font_height // 2)
            round_choice_group.append(gamesum_dob)

        s_group = Group(scale=3, max_size=1)
        s_group.x = 32
        s_group.y = (self.height - 3 * self.sprite_size) // 2
        s_group.append(self.sprites[ch_idx])
        round_choice_group.append(s_group)

        self.showGroup(round_choice_group)
Exemple #9
0
def build(
    widget: Button,
    *,
    radius: int,
    size: float | int,
    fit_to_text: bool,
) -> tuple[Native, tuple[int, int]]:
    """
    Creates the native element for the std tg-gui widget based on the _fixed_style_attrs_.
    Those _fixed_style_attrs_ are passed as kwargs to this function.
    :param widget: the tg-gui widget instance to build the native for
    :param **style_attrs: the fixed style attributes that are set at build time
    :return: a tuple of the native widget and suggested size
    """
    native = Group()

    label = Label(font=FONT, x=0, y=0, text=widget.text, scale=size)
    native.append(label)

    _, _, w, h = label.bounding_box
    w *= size
    h = int(1.15 * h * size)
    r = (
        min(radius, w // 2 - 1, h // 2 - 1)
        if isinstance(radius, int)
        else min(w // 2, h // 2) - 1
    )
    padding = round(1.25 * r)

    widget._impl_cache_ = dict(radius=radius, label_width=w)
    return (
        native,
        (
            w + padding + widget._margin_ * 2,
            int(h * 1.2) + widget._margin_ * 2,
        ),
    )
    def introductionScreen(self):
        # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        """Introduction screen."""
        if self.disp is not None:
            self.emptyGroup(self.disp_group)
            intro_group = Group(max_size=7)
            welcometo_dob = Label(self.font,
                                  text="Welcome To",
                                  scale=3,
                                  color=IWELCOME_COL_FG)
            welcometo_dob.x = (self.width - 10 * 3 * self.font_width) // 2
            # Y pos on screen looks lower than I would expect
            welcometo_dob.y = 3 * self.font_height // 2
            intro_group.append(welcometo_dob)

            extra_space = 8
            spacing = 3 * self.sprite_size + extra_space
            y_adj = (-6, -2, -2)
            for idx, sprite in enumerate(self.sprites):
                s_group = Group(scale=3, max_size=1)
                s_group.x = -96
                s_group.y = round((self.height - 1.5 * self.sprite_size) / 2 +
                                  (idx - 1) * spacing) + y_adj[idx]
                s_group.append(sprite)
                intro_group.append(s_group)

            arena_dob = Label(self.font,
                              text="Arena",
                              scale=3,
                              color=IWELCOME_COL_FG)
            arena_dob.x = (self.width - 5 * 3 * self.font_width) // 2
            arena_dob.y = self.height - 3 * self.font_height // 2
            intro_group.append(arena_dob)

            self.showGroup(intro_group)

        # The color modification here is fragile as it only works
        # if the text colour is blue, i.e. data is in lsb only
        self.sample.play("welcome-to")
        while self.sample.playing():
            if self.disp is not None and intro_group[0].color < WELCOME_COL_FG:
                intro_group[0].color += 0x10
                time.sleep(0.120)

        onscreen_x_pos = 96

        # Move each sprite onto the screen while saying its name with wav file
        anims = (("rock", 10, 1, 0.050), ("paper", 11, 2, 0.050),
                 ("scissors", 7, 3, 0.050))
        for idx, (audio_name, x_shift, grp_idx, delay_s) in enumerate(anims):
            if self.disp is None:
                self.showChoice(idx)  # Use for NeoPixels
            self.sample.play(audio_name)
            # Audio needs to be long enough to finish movement
            while self.sample.playing():
                if self.disp is not None:
                    if intro_group[grp_idx].x < onscreen_x_pos:
                        intro_group[grp_idx].x += x_shift
                        time.sleep(delay_s)

        # Set NeoPixels back to black
        if self.disp is None:
            self.pix.fill(BLACK)

        self.sample.play("arena")
        while self.sample.playing():
            if self.disp is not None and intro_group[4].color < WELCOME_COL_FG:
                intro_group[4].color += 0x10
                time.sleep(0.060)

        # Button Guide for those with a display
        if self.disp is not None:
            left_dob = Label(self.font,
                             text="< Select    ",
                             scale=2,
                             color=INFO_COL_FG,
                             background_color=INFO_COL_BG)
            left_width = len(left_dob.text) * 2 * self.font_width
            left_dob.x = -left_width
            left_dob.y = self.button_y_pos
            intro_group.append(left_dob)

            right_dob = Label(self.font,
                              text=" Transmit >",
                              scale=2,
                              color=INFO_COL_FG,
                              background_color=INFO_COL_BG)
            right_width = len(right_dob.text) * 2 * self.font_width
            right_dob.x = self.width
            right_dob.y = self.button_y_pos
            intro_group.append(right_dob)

            # Move left button text onto screen, then right
            steps = 20
            for x_pos in [
                    left_dob.x + round(left_width * x / steps)
                    for x in range(1, steps + 1)
            ]:
                left_dob.x = x_pos
                time.sleep(0.06)

            for x_pos in [
                    right_dob.x - round(right_width * x / steps)
                    for x in range(1, steps + 1)
            ]:
                right_dob.x = x_pos
                time.sleep(0.06)

            time.sleep(8)  # leave on screen for further 8 seconds
Exemple #11
0
class EventTheme(BaseTheme):
    """
    A Theme for an event countdown date.

    The theme supports days, hours, and minutes labels
    at the provided positions on the provided axis, but
    can easily be extended in the future.

    Raises:
        ValueError: Provide either an x or a
            y axis for the text labels.
    """

    placeholder = "--"
    formatter = "{:>2}"
    label_positions = {"days": 0, "hours": 1, "mins": 2}

    def __init__(self, *args, pos, x_axis=None, y_axis=None, **kwargs):
        """
        Given a series of positions for the time labels and an axis
        (either an x or a y), create a new theme representing an
        event countdown.

        Args:
            pos (tuple): A tuple of (int, int, int) representing positions
                for the days, hours, and minutes labels.
            x_axis (int, optional): The x axis on which to place labels.
                Either the x_axis or y_axis is optional, but not both.
                Defaults to None.
            y_axis (int, optional): The y axis on which to place labels.
                Either the x_axis or y_axis is optional, but not both.
                Defaults to None.
        """
        super().__init__(*args, **kwargs)
        self._create_labels(x_axis, y_axis, *pos)

    def _create_labels(self, x_axis, y_axis, days_pos, hours_pos, mins_pos):
        if not (x_axis or y_axis) or (x_axis and y_axis):
            raise ValueError(
                "Must provide either an x or y axis for text labels, not both."
            )

        self.display = Group(max_size=3)

        x_positions = [x_axis] * 3 if x_axis else [days_pos, hours_pos, mins_pos]
        y_positions = [y_axis] * 3 if y_axis else [days_pos, hours_pos, mins_pos]

        for x, y in zip(x_positions, y_positions):
            label = PlaceholderLabel(
                x, y, placeholder=self.placeholder, font=self.font, color=self.color
            )
            self.display.append(label)

    def _update_label(self, label, new_value):
        pos = self.label_positions[label]
        old_value = self.display[pos].text
        if new_value != old_value:
            self.display[pos].text = new_value

    def update_time(self, days, hours, mins):
        """
        Update the time displayed.

        Args:
            days (int): Days
            hours (int): Hours
            mins (int): Minutes
        """
        self._update_label("days", self.formatter.format(days))
        self._update_label("hours", self.formatter.format(hours))
        self._update_label("mins", self.formatter.format(mins))

    @property
    def days(self):
        return self.display[self.label_positions["days"]].text

    @property
    def hours(self):
        return self.display[self.label_positions["hours"]].text

    @property
    def mins(self):
        return self.display[self.label_positions["mins"]].text
Exemple #12
0
row_spacing = FONT_HEIGHT + 2
rows_group = Group(max_size=rows)

### I have foreground and background colours I can use here

### 1234567890123456789012345678901234567890
### aa:bb:cc:dd:ee:ff -101 12345678901234567
for idx in range(rows):
    row_label = Label(
        font=terminalio.FONT,
        text="",
        max_glyphs=40,  ### maximum that will fit 240/6
        color=0xc0c000)
    row_label.y = row_y
    row_y += row_spacing
    rows_group.append(row_label)

summary_label = Label(
    font=terminalio.FONT,
    text="",
    max_glyphs=40,  ### maximum that will fit 240/6
    color=0x00c0c0)

summary_label.y = 220

screen_group = Group(max_size=2)
screen_group.append(rows_group)
screen_group.append(summary_label)

display.show(screen_group)  ### was screen_group
Exemple #13
0
                          text="----.-",
                          scale=FONT_SCALE,
                          color=0x00c0c0)
voltage_value_dob.y = 30

voltage_units_dob = Label(font=terminalio.FONT,
                          text="mV",
                          scale=FONT_SCALE,
                          color=0x00c0c0)
voltage_units_dob.y = voltage_value_dob.y
voltage_units_dob.x = len(voltage_value_dob.text) * FONT_WIDTH * FONT_SCALE

### 9 elements, 4 added immediately, 4 later, 1 spare for on-screen text
screen_group = Group(max_size=4 + 4 + 1)
if magnetometer is not None:
    screen_group.append(magnet_value_dob)
    screen_group.append(magnet_units_dob)
screen_group.append(voltage_value_dob)
screen_group.append(voltage_units_dob)

### Initialise some displayio objects and append them
### The following four variables are set by these two functions
### voltage_barneg_dob, voltage_sep_dob, voltage_barpos_dob
### magnet_circ_dob
voltage_bar_set(0)
if magnetometer is not None:
    magnet_circ_set(0)

### Start-up splash screen
display.show(screen_group)
"""
CircuitPython simple sensor data display demo using LC709203 battery monitor and TFT display
"""
import time
import board
import terminalio
from displayio import Group
from adafruit_display_text import bitmap_label
from adafruit_lc709203f import LC709203F

text_area = bitmap_label.Label(terminalio.FONT, scale=2)
text_area.anchor_point = (0.5, 0.5)
text_area.anchored_position = (board.DISPLAY.width // 2, board.DISPLAY.height // 2)

main_group = Group()

main_group.append(text_area)

print("LC709203F test")
print("Make sure LiPoly battery is plugged into the board!")

sensor = LC709203F(board.I2C())

print("IC version:", hex(sensor.ic_version))

board.DISPLAY.show(main_group)

while True:
    text_area.text = "Battery:\n{:.1f} Volts \n{}%".format(sensor.cell_voltage, sensor.cell_percent)
    time.sleep(1)
    def showGameResultScreen(self, pla, sco, rounds_tot=None):
        # pylint: disable=unused-argument,too-many-locals,too-many-statements
        """Display a high score table with a visual bubble sort
           slow enough to see the algorithm at work."""
        self.fadeUpDown("down")
        self.emptyGroup(self.disp_group)

        # Score list group + background + question mark for sorting
        gs_group = Group(max_size=4)

        # Pale grey large GAME SCORES background
        bg_scale = 6
        sbg_dob1 = Label(self.font, text="GAME", scale=bg_scale, color=GS_COL)
        sbg_dob1.x = (self.width - 4 * bg_scale * self.font_width) // 2
        sbg_dob1.y = self.height // 4
        sbg_dob2 = Label(self.font,
                         text="SCORES",
                         scale=bg_scale,
                         color=GS_COL)
        sbg_dob2.x = (self.width - 6 * bg_scale * self.font_width) // 2
        sbg_dob2.y = self.height // 4 * 3
        gs_group.append(sbg_dob1)
        gs_group.append(sbg_dob2)
        self.showGroup(gs_group)
        self.fadeUpDown("up")

        # Calculate maximum length player name
        # and see if scores happen to already be in order
        max_len = 0
        prev_score = sco[0]
        descending = True
        for idx, (name, _) in enumerate(pla):
            max_len = max(max_len, len(name))
            if sco[idx] > prev_score:
                descending = False
            prev_score = sco[idx]

        fmt = "{:" + str(max_len) + "s} {:2d}"
        x_pos = (self.width - (max_len + 3) * 2 * self.font_width) // 2
        scale = 2
        spacing = 4 if len(pla) <= 6 else 0
        top_y_pos = round((self.height - len(pla) * scale * self.font_height -
                           (len(pla) - 1) * spacing) / 2 +
                          scale * self.font_height / 2)
        scores_group = Group(max_size=len(pla))
        gs_group.append(scores_group)
        for idx, (name, _) in enumerate(pla):
            op_dob = Label(
                self.font,
                text=fmt.format(name, sco[idx]),
                scale=2,
                color=(PLAYER_NAME_COL_FG if idx == 0 else OPP_NAME_COL_FG))
            op_dob.x = x_pos
            op_dob.y = top_y_pos + idx * (scale * self.font_height + spacing)
            scores_group.append(op_dob)
            time.sleep(0.2)

        # Sort the entries if needed
        sort_scores = list(sco)  # Make an independent local copy
        if not descending:
            empty_group = Group()  # minor hack to aid swaps in scores_group
            step = 3
            qm_dob = Label(self.font, text="?", scale=2, color=QM_SORT_FG)
            qm_dob.x = round(x_pos - 1.5 * scale * self.font_width)
            gs_group.append(qm_dob)
            while True:
                swaps = 0
                for idx in range(0, len(sort_scores) - 1):
                    above_score = sort_scores[idx]
                    above_y = scores_group[idx].y
                    below_y = scores_group[idx + 1].y
                    qm_dob.y = (above_y + below_y) // 2
                    if above_score < sort_scores[idx + 1]:
                        qm_dob.text = "<"
                        qm_dob.color = QM_SORTING_FG
                        swaps += 1

                        # make list of steps
                        range_y = below_y - above_y
                        offsets = list(range(step, range_y + 1, step))
                        # Ensure this goes to the exact final position
                        if offsets[-1] != range_y:
                            offsets.append(range_y)

                        for offset in offsets:
                            scores_group[idx].y = above_y + offset
                            scores_group[idx + 1].y = below_y - offset
                            time.sleep(0.050)

                        # swap the scores around
                        sort_scores[idx] = sort_scores[idx + 1]
                        sort_scores[idx + 1] = above_score

                        # swap the graphical objects around using empty_group
                        # to avoid ValueError: Layer already in a group
                        old_above_dob = scores_group[idx]
                        old_below_dob = scores_group[idx + 1]
                        scores_group[idx + 1] = empty_group
                        scores_group[idx] = old_below_dob
                        scores_group[idx + 1] = old_above_dob

                        qm_dob.text = "?"
                        qm_dob.color = QM_SORT_FG
                        time.sleep(0.2)
                    else:
                        time.sleep(0.6)

                if swaps == 0:
                    break  # Sort complete if no values were swapped
            gs_group.remove(qm_dob)
    def showPlayerVPlayerScreen(self, me_name, op_name, my_ch_idx, op_ch_idx,
                                result, summary, win, draw, void):
        # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        """Display a win, draw, lose or error message."""
        self.fadeUpDown("down")
        self.emptyGroup(self.disp_group)

        if void:
            error_tot = 3
            error_group = Group(max_size=error_tot + 1)
            # Opponent's name helps pinpoint the error
            op_dob = Label(self.font,
                           text=op_name,
                           scale=2,
                           color=OPP_NAME_COL_FG)
            op_dob.x = 40
            op_dob.y = self.font_height
            error_group.append(op_dob)
            self.showGroup(error_group)
            self.fadeUpDown("up", duration=0.4)
            if result is not None:
                self.sample.play(result)
            font_scale = 2
            # Attempting to put the three pieces of "Error!" text on screen
            # synchronised with the sound sample repeating the word
            for idx in range(error_tot):
                error_dob = Label(self.font,
                                  text="Error!",
                                  scale=font_scale,
                                  color=ERROR_COL_FG)
                error_dob.x = 40
                error_dob.y = 60 + idx * 60
                error_group.append(error_dob)
                time.sleep(0.5)  # Small attempt to synchronise audio with text
                font_scale += 1

        else:
            # Would be slightly better to create this Group once and re-use it
            pvp_group = Group(max_size=3)

            # Add player's name and sprite just off left side of screen
            # and opponent's just off right
            player_detail = [[
                me_name, self.sprites[my_ch_idx], -16 - 3 * self.sprite_size,
                PLAYER_NAME_COL_FG, PLAYER_NAME_COL_BG
            ],
                             [
                                 op_name, self.opp_sprites[op_ch_idx],
                                 16 + self.width, OPP_NAME_COL_FG,
                                 OPP_NAME_COL_BG
                             ]]
            idx_lr = [0, 1]  # index for left and right sprite
            if win:
                player_detail.reverse()  # this player is winner so put last
                idx_lr.reverse()

            # Add some whitespace around winner's name
            player_detail[1][0] = " " + player_detail[1][0] + " "

            for (name, sprite, start_x, fg, bg) in player_detail:
                s_group = Group(scale=2,
                                max_size=2)  # Audio is choppy at scale=3
                s_group.x = start_x
                s_group.y = (self.height - 2 *
                             (self.sprite_size + self.font_height)) // 2

                s_group.append(sprite)
                p_name_dob = Label(
                    self.font,
                    text=name,
                    scale=1,  # This is scaled by the group
                    color=fg,
                    background_color=bg)
                # Centre text below sprite - values are * Group scale
                p_name_dob.x = (self.sprite_size -
                                len(name) * self.font_width) // 2
                p_name_dob.y = self.sprite_size + 4
                s_group.append(p_name_dob)

                pvp_group.append(s_group)

            if draw:
                sum_text = "Draw"
            elif win:
                sum_text = "You win"
            else:
                sum_text = "You lose"
            # Text starts invisible (BLACK) and color is later changed
            summary_dob = Label(self.font, text=sum_text, scale=3, color=BLACK)
            summary_dob.x = round(
                (self.width - 3 * self.font_width * len(sum_text)) / 2)
            summary_dob.y = round(self.height - (3 * self.font_height / 2))
            pvp_group.append(summary_dob)

            self.showGroup(pvp_group)
            self.fadeUpDown("up", duration=0.4)

            # Start audio half way through animations
            if draw:
                # Move sprites onto the screen leaving them at either side
                for idx in range(16):
                    pvp_group[idx_lr[0]].x += 6
                    pvp_group[idx_lr[1]].x -= 6
                    if idx == 8 and result is not None:
                        self.sample.play(result)
                    time.sleep(0.2)
            else:
                # Move sprites together, winning sprite overlaps and covers loser
                for idx in range(16):
                    pvp_group[idx_lr[0]].x += 10
                    pvp_group[idx_lr[1]].x -= 10
                    if idx == 8 and result is not None:
                        self.sample.play(result)
                    time.sleep(0.2)

            self.sample.wait()  # Wait for first sample to finish

            if summary is not None:
                self.sample.play(summary)

            # Flash colours for win, fad up to blue for rest
            if not draw and win:
                colours = [YELLOW_COL, ORANGE_COL, RED_COL] * 5
            else:
                colours = [DRAWLOSE_COL * sc // 15 for sc in range(1, 15 + 1)]
            for col in colours:
                summary_dob.color = col
                time.sleep(0.120)

        self.sample.wait()  # Ensure second sample has completed
Exemple #17
0
    if cam.width > width:
        continue
    if cam.height > height:
        continue
    try:
        bitmap = Bitmap(cam.width, cam.height, 65535)
        break
    except MemoryError:
        continue

print(width, height, cam.width, cam.height)
if bitmap is None:
    raise SystemExit("Could not allocate a bitmap")

g = Group(scale=1, x=(width - cam.width) // 2, y=(height - cam.height) // 2)
tg = TileGrid(
    bitmap,
    pixel_shader=ColorConverter(input_colorspace=Colorspace.RGB565_SWAPPED))
g.append(tg)
display.show(g)

t0 = time.monotonic_ns()
display.auto_refresh = False
while True:
    cam.capture(bitmap)
    bitmap.dirty()
    display.refresh(minimum_frames_per_second=0)
    t1 = time.monotonic_ns()
    print("fps", 1e9 / (t1 - t0))
    t0 = t1
Exemple #18
0
### Create the simple arrow cursors
left_col = 20
right_col = display.width // 2 + left_col
for x_pos in (left_col, right_col):
    y_pos = top_y_pos
    rps_dob_idx.append(len(screen_group))
    for label_text in choices:
        rps_dob = Label(terminalio.FONT,
                        text=label_text,
                        scale=2,
                        color=DEFAULT_TXT_COL_FG,
                        background_color=DEFAULT_TXT_COL_BG)
        rps_dob.x = x_pos
        rps_dob.y = y_pos
        y_pos += 60
        screen_group.append(rps_dob)

cursor_dob = Label(terminalio.FONT, text=">", scale=3, color=CURSOR_COL_FG)
cursor_dob.x = left_col - 20
setCursor(my_choice_idx, "mine")
cursor_dob.y = top_y_pos
screen_group.append(cursor_dob)

### Initially set to a space to not show it
opp_cursor_dob = Label(terminalio.FONT,
                       text=" ",
                       scale=3,
                       color=OPP_CURSOR_COL_FG,
                       background_color=DEFAULT_TXT_COL_BG)
opp_cursor_dob.x = right_col - 20
setCursor(my_choice_idx, "your")
Exemple #19
0
    def _update_display(self):
        self._update_display_strings()
        banner = label.Label(FONT, text=BANNER_STRING, color=COLOR)
        state = label.Label(FONT, text=self.state_str, color=COLOR)
        detector_result = label.Label(FONT,
                                      text=self.detection_result_str,
                                      color=COLOR)
        duration = label.Label(FONT, text=self.duration_str, color=COLOR)
        min_pressure_label = label.Label(FONT,
                                         text=self.min_press_str,
                                         color=COLOR)
        high_pressure_label = label.Label(FONT,
                                          text=self.high_press_str,
                                          color=COLOR)
        pressure_label = label.Label(FONT, text=self.press_str, color=COLOR)

        banner.x = 0
        banner.y = 0 + Y_OFFSET

        state.x = 10
        state.y = 10 + Y_OFFSET

        detector_result.x = 10
        detector_result.y = 20 + Y_OFFSET

        duration.x = 10
        duration.y = 30 + Y_OFFSET

        min_pressure_label.x = 0
        min_pressure_label.y = BOTTOM_ROW - 10

        pressure_label.x = DISPLAY_WIDTH - pressure_label.bounding_box[2]
        pressure_label.y = BOTTOM_ROW

        high_pressure_label.x = 0
        high_pressure_label.y = BOTTOM_ROW

        splash = Group()
        splash.append(banner)
        splash.append(state)
        splash.append(detector_result)
        splash.append(duration)
        splash.append(min_pressure_label)
        splash.append(high_pressure_label)
        splash.append(pressure_label)

        self.display.show(splash)