Source code for bascenev1lib.actor.onscreencountdown

# Released under the MIT License. See LICENSE for details.
#
"""Defines Actor Type(s)."""

from __future__ import annotations

from typing import TYPE_CHECKING, override

import bascenev1 as bs

if TYPE_CHECKING:
    from typing import Any, Callable


[docs] class OnScreenCountdown(bs.Actor): """A Handy On-Screen Timer. category: Gameplay Classes Useful for time-based games that count down to zero. """ def __init__(self, duration: int, endcall: Callable[[], Any] | None = None): """Duration is provided in seconds.""" super().__init__() self._timeremaining = duration self._ended = False self._endcall = endcall self.node = bs.newnode( 'text', attrs={ 'v_attach': 'top', 'h_attach': 'center', 'h_align': 'center', 'color': (1, 1, 0.5, 1), 'flatness': 0.5, 'shadow': 0.5, 'position': (0, -70), 'scale': 1.4, 'text': '', }, ) self.inputnode = bs.newnode( 'timedisplay', attrs={ 'time2': duration * 1000, 'timemax': duration * 1000, 'timemin': 0, }, ) self.inputnode.connectattr('output', self.node, 'text') self._countdownsounds = { 10: bs.getsound('announceTen'), 9: bs.getsound('announceNine'), 8: bs.getsound('announceEight'), 7: bs.getsound('announceSeven'), 6: bs.getsound('announceSix'), 5: bs.getsound('announceFive'), 4: bs.getsound('announceFour'), 3: bs.getsound('announceThree'), 2: bs.getsound('announceTwo'), 1: bs.getsound('announceOne'), } self._timer: bs.Timer | None = None
[docs] def start(self) -> None: """Start the timer.""" globalsnode = bs.getactivity().globalsnode globalsnode.connectattr('time', self.inputnode, 'time1') self.inputnode.time2 = ( globalsnode.time + (self._timeremaining + 1) * 1000 ) self._timer = bs.Timer(1.0, self._update, repeat=True)
[docs] @override def on_expire(self) -> None: super().on_expire() # Release callbacks/refs. self._endcall = None
def _update(self, forcevalue: int | None = None) -> None: if forcevalue is not None: tval = forcevalue else: self._timeremaining = max(0, self._timeremaining - 1) tval = self._timeremaining # If there's a countdown sound for this time that we # haven't played yet, play it. if tval == 10: assert self.node assert isinstance(self.node.scale, float) self.node.scale *= 1.2 cmb = bs.newnode('combine', owner=self.node, attrs={'size': 4}) cmb.connectattr('output', self.node, 'color') bs.animate(cmb, 'input0', {0: 1.0, 0.15: 1.0}, loop=True) bs.animate(cmb, 'input1', {0: 1.0, 0.15: 0.5}, loop=True) bs.animate(cmb, 'input2', {0: 0.1, 0.15: 0.0}, loop=True) cmb.input3 = 1.0 if tval <= 10 and not self._ended: bs.getsound('tick').play() if tval in self._countdownsounds: self._countdownsounds[tval].play() if tval <= 0 and not self._ended: self._ended = True if self._endcall is not None: self._endcall()