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(
 26            '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        )
 39        self.inputnode = ba.newnode(
 40            'timedisplay', attrs={'timemin': 0, '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(
 51            'time', self.inputnode, 'time2'
 52        )
 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(
 59        self,
 60        endtime: int | float | None = None,
 61        timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS,
 62    ) -> None:
 63        """End the timer.
 64
 65        If 'endtime' is not None, it is used when calculating
 66        the final display time; otherwise the current time is used.
 67
 68        'timeformat' applies to endtime and can be SECONDS or MILLISECONDS
 69        """
 70        if endtime is None:
 71            endtime = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
 72            timeformat = ba.TimeFormat.MILLISECONDS
 73
 74        if self._starttime_ms is None:
 75            print('Warning: OnScreenTimer.stop() called without start() first')
 76        else:
 77            endtime_ms: int
 78            if timeformat is ba.TimeFormat.SECONDS:
 79                endtime_ms = int(endtime * 1000)
 80            elif timeformat is ba.TimeFormat.MILLISECONDS:
 81                assert isinstance(endtime, int)
 82                endtime_ms = endtime
 83            else:
 84                raise ValueError(f'invalid timeformat: {timeformat}')
 85
 86            self.inputnode.timemax = endtime_ms - self._starttime_ms
 87
 88    # Overloads so type checker knows our exact return type based in args.
 89    @overload
 90    def getstarttime(
 91        self, timeformat: Literal[ba.TimeFormat.SECONDS] = ba.TimeFormat.SECONDS
 92    ) -> float:
 93        ...
 94
 95    @overload
 96    def getstarttime(
 97        self, timeformat: Literal[ba.TimeFormat.MILLISECONDS]
 98    ) -> int:
 99        ...
100
101    def getstarttime(
102        self, timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS
103    ) -> int | float:
104        """Return the sim-time when start() was called.
105
106        Time will be returned in seconds if timeformat is SECONDS or
107        milliseconds if it is MILLISECONDS.
108        """
109        val_ms: Any
110        if self._starttime_ms is None:
111            print('WARNING: getstarttime() called on un-started timer')
112            val_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
113        else:
114            val_ms = self._starttime_ms
115        assert isinstance(val_ms, int)
116        if timeformat is ba.TimeFormat.SECONDS:
117            return 0.001 * val_ms
118        if timeformat is ba.TimeFormat.MILLISECONDS:
119            return val_ms
120        raise ValueError(f'invalid timeformat: {timeformat}')
121
122    @property
123    def starttime(self) -> float:
124        """Shortcut for start time in seconds."""
125        return self.getstarttime()
126
127    def handlemessage(self, msg: Any) -> Any:
128        # if we're asked to die, just kill our node/timer
129        if isinstance(msg, ba.DieMessage):
130            if self.node:
131                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(
 27            'text',
 28            attrs={
 29                'v_attach': 'top',
 30                'h_attach': 'center',
 31                'h_align': 'center',
 32                'color': (1, 1, 0.5, 1),
 33                'flatness': 0.5,
 34                'shadow': 0.5,
 35                'position': (0, -70),
 36                'scale': 1.4,
 37                'text': '',
 38            },
 39        )
 40        self.inputnode = ba.newnode(
 41            'timedisplay', attrs={'timemin': 0, '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(
 52            'time', self.inputnode, 'time2'
 53        )
 54
 55    def has_started(self) -> bool:
 56        """Return whether this timer has started yet."""
 57        return self._starttime_ms is not None
 58
 59    def stop(
 60        self,
 61        endtime: int | float | None = None,
 62        timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS,
 63    ) -> None:
 64        """End the timer.
 65
 66        If 'endtime' is not None, it is used when calculating
 67        the final display time; otherwise the current time is used.
 68
 69        'timeformat' applies to endtime and can be SECONDS or MILLISECONDS
 70        """
 71        if endtime is None:
 72            endtime = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
 73            timeformat = ba.TimeFormat.MILLISECONDS
 74
 75        if self._starttime_ms is None:
 76            print('Warning: OnScreenTimer.stop() called without start() first')
 77        else:
 78            endtime_ms: int
 79            if timeformat is ba.TimeFormat.SECONDS:
 80                endtime_ms = int(endtime * 1000)
 81            elif timeformat is ba.TimeFormat.MILLISECONDS:
 82                assert isinstance(endtime, int)
 83                endtime_ms = endtime
 84            else:
 85                raise ValueError(f'invalid timeformat: {timeformat}')
 86
 87            self.inputnode.timemax = endtime_ms - self._starttime_ms
 88
 89    # Overloads so type checker knows our exact return type based in args.
 90    @overload
 91    def getstarttime(
 92        self, timeformat: Literal[ba.TimeFormat.SECONDS] = ba.TimeFormat.SECONDS
 93    ) -> float:
 94        ...
 95
 96    @overload
 97    def getstarttime(
 98        self, timeformat: Literal[ba.TimeFormat.MILLISECONDS]
 99    ) -> int:
100        ...
101
102    def getstarttime(
103        self, timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS
104    ) -> int | float:
105        """Return the sim-time when start() was called.
106
107        Time will be returned in seconds if timeformat is SECONDS or
108        milliseconds if it is MILLISECONDS.
109        """
110        val_ms: Any
111        if self._starttime_ms is None:
112            print('WARNING: getstarttime() called on un-started timer')
113            val_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
114        else:
115            val_ms = self._starttime_ms
116        assert isinstance(val_ms, int)
117        if timeformat is ba.TimeFormat.SECONDS:
118            return 0.001 * val_ms
119        if timeformat is ba.TimeFormat.MILLISECONDS:
120            return val_ms
121        raise ValueError(f'invalid timeformat: {timeformat}')
122
123    @property
124    def starttime(self) -> float:
125        """Shortcut for start time in seconds."""
126        return self.getstarttime()
127
128    def handlemessage(self, msg: Any) -> Any:
129        # if we're asked to die, just kill our node/timer
130        if isinstance(msg, ba.DieMessage):
131            if self.node:
132                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(
27            'text',
28            attrs={
29                'v_attach': 'top',
30                'h_attach': 'center',
31                'h_align': 'center',
32                'color': (1, 1, 0.5, 1),
33                'flatness': 0.5,
34                'shadow': 0.5,
35                'position': (0, -70),
36                'scale': 1.4,
37                'text': '',
38            },
39        )
40        self.inputnode = ba.newnode(
41            'timedisplay', attrs={'timemin': 0, '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(
52            'time', self.inputnode, 'time2'
53        )

Start the timer.

def has_started(self) -> bool:
55    def has_started(self) -> bool:
56        """Return whether this timer has started yet."""
57        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:
59    def stop(
60        self,
61        endtime: int | float | None = None,
62        timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS,
63    ) -> None:
64        """End the timer.
65
66        If 'endtime' is not None, it is used when calculating
67        the final display time; otherwise the current time is used.
68
69        'timeformat' applies to endtime and can be SECONDS or MILLISECONDS
70        """
71        if endtime is None:
72            endtime = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
73            timeformat = ba.TimeFormat.MILLISECONDS
74
75        if self._starttime_ms is None:
76            print('Warning: OnScreenTimer.stop() called without start() first')
77        else:
78            endtime_ms: int
79            if timeformat is ba.TimeFormat.SECONDS:
80                endtime_ms = int(endtime * 1000)
81            elif timeformat is ba.TimeFormat.MILLISECONDS:
82                assert isinstance(endtime, int)
83                endtime_ms = endtime
84            else:
85                raise ValueError(f'invalid timeformat: {timeformat}')
86
87            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:
102    def getstarttime(
103        self, timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS
104    ) -> int | float:
105        """Return the sim-time when start() was called.
106
107        Time will be returned in seconds if timeformat is SECONDS or
108        milliseconds if it is MILLISECONDS.
109        """
110        val_ms: Any
111        if self._starttime_ms is None:
112            print('WARNING: getstarttime() called on un-started timer')
113            val_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
114        else:
115            val_ms = self._starttime_ms
116        assert isinstance(val_ms, int)
117        if timeformat is ba.TimeFormat.SECONDS:
118            return 0.001 * val_ms
119        if timeformat is ba.TimeFormat.MILLISECONDS:
120            return val_ms
121        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:
128    def handlemessage(self, msg: Any) -> Any:
129        # if we're asked to die, just kill our node/timer
130        if isinstance(msg, ba.DieMessage):
131            if self.node:
132                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