bastd.actor.onscreencountdown
Defines Actor Type(s).
1# Released under the MIT License. See LICENSE for details. 2# 3"""Defines Actor Type(s).""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9import ba 10 11if TYPE_CHECKING: 12 from typing import Any, Callable 13 14 15class OnScreenCountdown(ba.Actor): 16 """A Handy On-Screen Timer. 17 18 category: Gameplay Classes 19 20 Useful for time-based games that count down to zero. 21 """ 22 23 def __init__(self, duration: int, endcall: Callable[[], Any] | None = None): 24 """Duration is provided in seconds.""" 25 super().__init__() 26 self._timeremaining = duration 27 self._ended = False 28 self._endcall = endcall 29 self.node = ba.newnode( 30 'text', 31 attrs={ 32 'v_attach': 'top', 33 'h_attach': 'center', 34 'h_align': 'center', 35 'color': (1, 1, 0.5, 1), 36 'flatness': 0.5, 37 'shadow': 0.5, 38 'position': (0, -70), 39 'scale': 1.4, 40 'text': '', 41 }, 42 ) 43 self.inputnode = ba.newnode( 44 'timedisplay', 45 attrs={ 46 'time2': duration * 1000, 47 'timemax': duration * 1000, 48 'timemin': 0, 49 }, 50 ) 51 self.inputnode.connectattr('output', self.node, 'text') 52 self._countdownsounds = { 53 10: ba.getsound('announceTen'), 54 9: ba.getsound('announceNine'), 55 8: ba.getsound('announceEight'), 56 7: ba.getsound('announceSeven'), 57 6: ba.getsound('announceSix'), 58 5: ba.getsound('announceFive'), 59 4: ba.getsound('announceFour'), 60 3: ba.getsound('announceThree'), 61 2: ba.getsound('announceTwo'), 62 1: ba.getsound('announceOne'), 63 } 64 self._timer: ba.Timer | None = None 65 66 def start(self) -> None: 67 """Start the timer.""" 68 globalsnode = ba.getactivity().globalsnode 69 globalsnode.connectattr('time', self.inputnode, 'time1') 70 self.inputnode.time2 = ( 71 globalsnode.time + (self._timeremaining + 1) * 1000 72 ) 73 self._timer = ba.Timer(1.0, self._update, repeat=True) 74 75 def on_expire(self) -> None: 76 super().on_expire() 77 78 # Release callbacks/refs. 79 self._endcall = None 80 81 def _update(self, forcevalue: int | None = None) -> None: 82 if forcevalue is not None: 83 tval = forcevalue 84 else: 85 self._timeremaining = max(0, self._timeremaining - 1) 86 tval = self._timeremaining 87 88 # if there's a countdown sound for this time that we 89 # haven't played yet, play it 90 if tval == 10: 91 assert self.node 92 assert isinstance(self.node.scale, float) 93 self.node.scale *= 1.2 94 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 4}) 95 cmb.connectattr('output', self.node, 'color') 96 ba.animate(cmb, 'input0', {0: 1.0, 0.15: 1.0}, loop=True) 97 ba.animate(cmb, 'input1', {0: 1.0, 0.15: 0.5}, loop=True) 98 ba.animate(cmb, 'input2', {0: 0.1, 0.15: 0.0}, loop=True) 99 cmb.input3 = 1.0 100 if tval <= 10 and not self._ended: 101 ba.playsound(ba.getsound('tick')) 102 if tval in self._countdownsounds: 103 ba.playsound(self._countdownsounds[tval]) 104 if tval <= 0 and not self._ended: 105 self._ended = True 106 if self._endcall is not None: 107 self._endcall()
class
OnScreenCountdown(ba._actor.Actor):
16class OnScreenCountdown(ba.Actor): 17 """A Handy On-Screen Timer. 18 19 category: Gameplay Classes 20 21 Useful for time-based games that count down to zero. 22 """ 23 24 def __init__(self, duration: int, endcall: Callable[[], Any] | None = None): 25 """Duration is provided in seconds.""" 26 super().__init__() 27 self._timeremaining = duration 28 self._ended = False 29 self._endcall = endcall 30 self.node = ba.newnode( 31 'text', 32 attrs={ 33 'v_attach': 'top', 34 'h_attach': 'center', 35 'h_align': 'center', 36 'color': (1, 1, 0.5, 1), 37 'flatness': 0.5, 38 'shadow': 0.5, 39 'position': (0, -70), 40 'scale': 1.4, 41 'text': '', 42 }, 43 ) 44 self.inputnode = ba.newnode( 45 'timedisplay', 46 attrs={ 47 'time2': duration * 1000, 48 'timemax': duration * 1000, 49 'timemin': 0, 50 }, 51 ) 52 self.inputnode.connectattr('output', self.node, 'text') 53 self._countdownsounds = { 54 10: ba.getsound('announceTen'), 55 9: ba.getsound('announceNine'), 56 8: ba.getsound('announceEight'), 57 7: ba.getsound('announceSeven'), 58 6: ba.getsound('announceSix'), 59 5: ba.getsound('announceFive'), 60 4: ba.getsound('announceFour'), 61 3: ba.getsound('announceThree'), 62 2: ba.getsound('announceTwo'), 63 1: ba.getsound('announceOne'), 64 } 65 self._timer: ba.Timer | None = None 66 67 def start(self) -> None: 68 """Start the timer.""" 69 globalsnode = ba.getactivity().globalsnode 70 globalsnode.connectattr('time', self.inputnode, 'time1') 71 self.inputnode.time2 = ( 72 globalsnode.time + (self._timeremaining + 1) * 1000 73 ) 74 self._timer = ba.Timer(1.0, self._update, repeat=True) 75 76 def on_expire(self) -> None: 77 super().on_expire() 78 79 # Release callbacks/refs. 80 self._endcall = None 81 82 def _update(self, forcevalue: int | None = None) -> None: 83 if forcevalue is not None: 84 tval = forcevalue 85 else: 86 self._timeremaining = max(0, self._timeremaining - 1) 87 tval = self._timeremaining 88 89 # if there's a countdown sound for this time that we 90 # haven't played yet, play it 91 if tval == 10: 92 assert self.node 93 assert isinstance(self.node.scale, float) 94 self.node.scale *= 1.2 95 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 4}) 96 cmb.connectattr('output', self.node, 'color') 97 ba.animate(cmb, 'input0', {0: 1.0, 0.15: 1.0}, loop=True) 98 ba.animate(cmb, 'input1', {0: 1.0, 0.15: 0.5}, loop=True) 99 ba.animate(cmb, 'input2', {0: 0.1, 0.15: 0.0}, loop=True) 100 cmb.input3 = 1.0 101 if tval <= 10 and not self._ended: 102 ba.playsound(ba.getsound('tick')) 103 if tval in self._countdownsounds: 104 ba.playsound(self._countdownsounds[tval]) 105 if tval <= 0 and not self._ended: 106 self._ended = True 107 if self._endcall is not None: 108 self._endcall()
A Handy On-Screen Timer.
category: Gameplay Classes
Useful for time-based games that count down to zero.
OnScreenCountdown(duration: int, endcall: Optional[Callable[[], Any]] = None)
24 def __init__(self, duration: int, endcall: Callable[[], Any] | None = None): 25 """Duration is provided in seconds.""" 26 super().__init__() 27 self._timeremaining = duration 28 self._ended = False 29 self._endcall = endcall 30 self.node = ba.newnode( 31 'text', 32 attrs={ 33 'v_attach': 'top', 34 'h_attach': 'center', 35 'h_align': 'center', 36 'color': (1, 1, 0.5, 1), 37 'flatness': 0.5, 38 'shadow': 0.5, 39 'position': (0, -70), 40 'scale': 1.4, 41 'text': '', 42 }, 43 ) 44 self.inputnode = ba.newnode( 45 'timedisplay', 46 attrs={ 47 'time2': duration * 1000, 48 'timemax': duration * 1000, 49 'timemin': 0, 50 }, 51 ) 52 self.inputnode.connectattr('output', self.node, 'text') 53 self._countdownsounds = { 54 10: ba.getsound('announceTen'), 55 9: ba.getsound('announceNine'), 56 8: ba.getsound('announceEight'), 57 7: ba.getsound('announceSeven'), 58 6: ba.getsound('announceSix'), 59 5: ba.getsound('announceFive'), 60 4: ba.getsound('announceFour'), 61 3: ba.getsound('announceThree'), 62 2: ba.getsound('announceTwo'), 63 1: ba.getsound('announceOne'), 64 } 65 self._timer: ba.Timer | None = None
Duration is provided in seconds.
def
start(self) -> None:
67 def start(self) -> None: 68 """Start the timer.""" 69 globalsnode = ba.getactivity().globalsnode 70 globalsnode.connectattr('time', self.inputnode, 'time1') 71 self.inputnode.time2 = ( 72 globalsnode.time + (self._timeremaining + 1) * 1000 73 ) 74 self._timer = ba.Timer(1.0, self._update, repeat=True)
Start the timer.
def
on_expire(self) -> None:
76 def on_expire(self) -> None: 77 super().on_expire() 78 79 # Release callbacks/refs. 80 self._endcall = None
Called for remaining ba.Actor
s when their ba.Activity shuts down.
Actors can use this opportunity to clear callbacks or other references which have the potential of keeping the ba.Activity alive inadvertently (Activities can not exit cleanly while any Python references to them remain.)
Once an actor is expired (see ba.Actor.is_expired()) it should no longer perform any game-affecting operations (creating, modifying, or deleting nodes, media, timers, etc.) Attempts to do so will likely result in errors.
Inherited Members
- ba._actor.Actor
- handlemessage
- autoretain
- expired
- exists
- is_alive
- activity
- getactivity