bastd.actor.onscreentimer
Defines Actor(s).
1# Released under the MIT License. See LICENSE for details. 2# 3"""Defines Actor(s).""" 4from __future__ import annotations 5 6from typing import TYPE_CHECKING, overload 7 8import ba 9 10if TYPE_CHECKING: 11 from typing import Any, Literal 12 13 14class OnScreenTimer(ba.Actor): 15 """A handy on-screen timer. 16 17 category: Gameplay Classes 18 19 Useful for time-based games where time increases. 20 """ 21 22 def __init__(self) -> None: 23 super().__init__() 24 self._starttime_ms: int | None = None 25 self.node = ba.newnode('text', 26 attrs={ 27 'v_attach': 'top', 28 'h_attach': 'center', 29 'h_align': 'center', 30 'color': (1, 1, 0.5, 1), 31 'flatness': 0.5, 32 'shadow': 0.5, 33 'position': (0, -70), 34 'scale': 1.4, 35 'text': '' 36 }) 37 self.inputnode = ba.newnode('timedisplay', 38 attrs={ 39 'timemin': 0, 40 'showsubseconds': True 41 }) 42 self.inputnode.connectattr('output', self.node, 'text') 43 44 def start(self) -> None: 45 """Start the timer.""" 46 tval = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 47 assert isinstance(tval, int) 48 self._starttime_ms = tval 49 self.inputnode.time1 = self._starttime_ms 50 ba.getactivity().globalsnode.connectattr('time', self.inputnode, 51 'time2') 52 53 def has_started(self) -> bool: 54 """Return whether this timer has started yet.""" 55 return self._starttime_ms is not None 56 57 def stop(self, 58 endtime: int | float | None = None, 59 timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> None: 60 """End the timer. 61 62 If 'endtime' is not None, it is used when calculating 63 the final display time; otherwise the current time is used. 64 65 'timeformat' applies to endtime and can be SECONDS or MILLISECONDS 66 """ 67 if endtime is None: 68 endtime = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 69 timeformat = ba.TimeFormat.MILLISECONDS 70 71 if self._starttime_ms is None: 72 print('Warning: OnScreenTimer.stop() called without start() first') 73 else: 74 endtime_ms: int 75 if timeformat is ba.TimeFormat.SECONDS: 76 endtime_ms = int(endtime * 1000) 77 elif timeformat is ba.TimeFormat.MILLISECONDS: 78 assert isinstance(endtime, int) 79 endtime_ms = endtime 80 else: 81 raise ValueError(f'invalid timeformat: {timeformat}') 82 83 self.inputnode.timemax = endtime_ms - self._starttime_ms 84 85 # Overloads so type checker knows our exact return type based in args. 86 @overload 87 def getstarttime( 88 self, 89 timeformat: Literal[ba.TimeFormat.SECONDS] = ba.TimeFormat.SECONDS 90 ) -> float: 91 ... 92 93 @overload 94 def getstarttime(self, 95 timeformat: Literal[ba.TimeFormat.MILLISECONDS]) -> int: 96 ... 97 98 def getstarttime( 99 self, 100 timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> int | float: 101 """Return the sim-time when start() was called. 102 103 Time will be returned in seconds if timeformat is SECONDS or 104 milliseconds if it is MILLISECONDS. 105 """ 106 val_ms: Any 107 if self._starttime_ms is None: 108 print('WARNING: getstarttime() called on un-started timer') 109 val_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 110 else: 111 val_ms = self._starttime_ms 112 assert isinstance(val_ms, int) 113 if timeformat is ba.TimeFormat.SECONDS: 114 return 0.001 * val_ms 115 if timeformat is ba.TimeFormat.MILLISECONDS: 116 return val_ms 117 raise ValueError(f'invalid timeformat: {timeformat}') 118 119 @property 120 def starttime(self) -> float: 121 """Shortcut for start time in seconds.""" 122 return self.getstarttime() 123 124 def handlemessage(self, msg: Any) -> Any: 125 # if we're asked to die, just kill our node/timer 126 if isinstance(msg, ba.DieMessage): 127 if self.node: 128 self.node.delete()
class
OnScreenTimer(ba._actor.Actor):
15class OnScreenTimer(ba.Actor): 16 """A handy on-screen timer. 17 18 category: Gameplay Classes 19 20 Useful for time-based games where time increases. 21 """ 22 23 def __init__(self) -> None: 24 super().__init__() 25 self._starttime_ms: int | None = None 26 self.node = ba.newnode('text', 27 attrs={ 28 'v_attach': 'top', 29 'h_attach': 'center', 30 'h_align': 'center', 31 'color': (1, 1, 0.5, 1), 32 'flatness': 0.5, 33 'shadow': 0.5, 34 'position': (0, -70), 35 'scale': 1.4, 36 'text': '' 37 }) 38 self.inputnode = ba.newnode('timedisplay', 39 attrs={ 40 'timemin': 0, 41 'showsubseconds': True 42 }) 43 self.inputnode.connectattr('output', self.node, 'text') 44 45 def start(self) -> None: 46 """Start the timer.""" 47 tval = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 48 assert isinstance(tval, int) 49 self._starttime_ms = tval 50 self.inputnode.time1 = self._starttime_ms 51 ba.getactivity().globalsnode.connectattr('time', self.inputnode, 52 'time2') 53 54 def has_started(self) -> bool: 55 """Return whether this timer has started yet.""" 56 return self._starttime_ms is not None 57 58 def stop(self, 59 endtime: int | float | None = None, 60 timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> None: 61 """End the timer. 62 63 If 'endtime' is not None, it is used when calculating 64 the final display time; otherwise the current time is used. 65 66 'timeformat' applies to endtime and can be SECONDS or MILLISECONDS 67 """ 68 if endtime is None: 69 endtime = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 70 timeformat = ba.TimeFormat.MILLISECONDS 71 72 if self._starttime_ms is None: 73 print('Warning: OnScreenTimer.stop() called without start() first') 74 else: 75 endtime_ms: int 76 if timeformat is ba.TimeFormat.SECONDS: 77 endtime_ms = int(endtime * 1000) 78 elif timeformat is ba.TimeFormat.MILLISECONDS: 79 assert isinstance(endtime, int) 80 endtime_ms = endtime 81 else: 82 raise ValueError(f'invalid timeformat: {timeformat}') 83 84 self.inputnode.timemax = endtime_ms - self._starttime_ms 85 86 # Overloads so type checker knows our exact return type based in args. 87 @overload 88 def getstarttime( 89 self, 90 timeformat: Literal[ba.TimeFormat.SECONDS] = ba.TimeFormat.SECONDS 91 ) -> float: 92 ... 93 94 @overload 95 def getstarttime(self, 96 timeformat: Literal[ba.TimeFormat.MILLISECONDS]) -> int: 97 ... 98 99 def getstarttime( 100 self, 101 timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> int | float: 102 """Return the sim-time when start() was called. 103 104 Time will be returned in seconds if timeformat is SECONDS or 105 milliseconds if it is MILLISECONDS. 106 """ 107 val_ms: Any 108 if self._starttime_ms is None: 109 print('WARNING: getstarttime() called on un-started timer') 110 val_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 111 else: 112 val_ms = self._starttime_ms 113 assert isinstance(val_ms, int) 114 if timeformat is ba.TimeFormat.SECONDS: 115 return 0.001 * val_ms 116 if timeformat is ba.TimeFormat.MILLISECONDS: 117 return val_ms 118 raise ValueError(f'invalid timeformat: {timeformat}') 119 120 @property 121 def starttime(self) -> float: 122 """Shortcut for start time in seconds.""" 123 return self.getstarttime() 124 125 def handlemessage(self, msg: Any) -> Any: 126 # if we're asked to die, just kill our node/timer 127 if isinstance(msg, ba.DieMessage): 128 if self.node: 129 self.node.delete()
A handy on-screen timer.
category: Gameplay Classes
Useful for time-based games where time increases.
OnScreenTimer()
23 def __init__(self) -> None: 24 super().__init__() 25 self._starttime_ms: int | None = None 26 self.node = ba.newnode('text', 27 attrs={ 28 'v_attach': 'top', 29 'h_attach': 'center', 30 'h_align': 'center', 31 'color': (1, 1, 0.5, 1), 32 'flatness': 0.5, 33 'shadow': 0.5, 34 'position': (0, -70), 35 'scale': 1.4, 36 'text': '' 37 }) 38 self.inputnode = ba.newnode('timedisplay', 39 attrs={ 40 'timemin': 0, 41 'showsubseconds': True 42 }) 43 self.inputnode.connectattr('output', self.node, 'text')
Instantiates an Actor in the current ba.Activity.
def
start(self) -> None:
45 def start(self) -> None: 46 """Start the timer.""" 47 tval = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 48 assert isinstance(tval, int) 49 self._starttime_ms = tval 50 self.inputnode.time1 = self._starttime_ms 51 ba.getactivity().globalsnode.connectattr('time', self.inputnode, 52 'time2')
Start the timer.
def
has_started(self) -> bool:
54 def has_started(self) -> bool: 55 """Return whether this timer has started yet.""" 56 return self._starttime_ms is not None
Return whether this timer has started yet.
def
stop( self, endtime: int | float | None = None, timeformat: ba._generated.enums.TimeFormat = <TimeFormat.SECONDS: 0>) -> None:
58 def stop(self, 59 endtime: int | float | None = None, 60 timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> None: 61 """End the timer. 62 63 If 'endtime' is not None, it is used when calculating 64 the final display time; otherwise the current time is used. 65 66 'timeformat' applies to endtime and can be SECONDS or MILLISECONDS 67 """ 68 if endtime is None: 69 endtime = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 70 timeformat = ba.TimeFormat.MILLISECONDS 71 72 if self._starttime_ms is None: 73 print('Warning: OnScreenTimer.stop() called without start() first') 74 else: 75 endtime_ms: int 76 if timeformat is ba.TimeFormat.SECONDS: 77 endtime_ms = int(endtime * 1000) 78 elif timeformat is ba.TimeFormat.MILLISECONDS: 79 assert isinstance(endtime, int) 80 endtime_ms = endtime 81 else: 82 raise ValueError(f'invalid timeformat: {timeformat}') 83 84 self.inputnode.timemax = endtime_ms - self._starttime_ms
End the timer.
If 'endtime' is not None, it is used when calculating the final display time; otherwise the current time is used.
'timeformat' applies to endtime and can be SECONDS or MILLISECONDS
def
getstarttime( self, timeformat: ba._generated.enums.TimeFormat = <TimeFormat.SECONDS: 0>) -> int | float:
99 def getstarttime( 100 self, 101 timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> int | float: 102 """Return the sim-time when start() was called. 103 104 Time will be returned in seconds if timeformat is SECONDS or 105 milliseconds if it is MILLISECONDS. 106 """ 107 val_ms: Any 108 if self._starttime_ms is None: 109 print('WARNING: getstarttime() called on un-started timer') 110 val_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS) 111 else: 112 val_ms = self._starttime_ms 113 assert isinstance(val_ms, int) 114 if timeformat is ba.TimeFormat.SECONDS: 115 return 0.001 * val_ms 116 if timeformat is ba.TimeFormat.MILLISECONDS: 117 return val_ms 118 raise ValueError(f'invalid timeformat: {timeformat}')
Return the sim-time when start() was called.
Time will be returned in seconds if timeformat is SECONDS or milliseconds if it is MILLISECONDS.
def
handlemessage(self, msg: Any) -> Any:
125 def handlemessage(self, msg: Any) -> Any: 126 # if we're asked to die, just kill our node/timer 127 if isinstance(msg, ba.DieMessage): 128 if self.node: 129 self.node.delete()
General message handling; can be passed any message object.
Inherited Members
- ba._actor.Actor
- autoretain
- on_expire
- expired
- exists
- is_alive
- activity
- getactivity