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.

starttime: float

Shortcut for start time in seconds.

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