Skip to content

Commit f44233c

Browse files
authored
Merge pull request #2344 from pythonarcade/sub-clock
Add a SubClock class to `arcade.future`
2 parents 8c17aed + 2c4161f commit f44233c

File tree

2 files changed

+92
-15
lines changed

2 files changed

+92
-15
lines changed

arcade/clock.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ class Clock:
1919
only certain elements rather than everything.
2020
2121
Args:
22-
initial_elapsed (float, optional): The amount of time the clock should assume has
22+
initial_elapsed: The amount of time the clock should assume has
2323
already occurred. Defaults to 0.0
24-
initial_tick (int, optional): The number of ticks the clock should assume has already
24+
initial_tick: The number of ticks the clock should assume has already
2525
occurred. Defaults to 0.
26-
tick_speed (float, optional): A multiplier on how the 'speed' of time.
26+
tick_speed: A multiplier on how the 'speed' of time.
2727
i.e. a value of 0.5 means time elapsed half as fast for this clock. Defaults to 1.0.
2828
"""
2929

@@ -40,7 +40,7 @@ def tick(self, delta_time: float):
4040
Update the clock with the time that has passed since the last tick.
4141
4242
Args:
43-
delta_time (float): The amount of time that has passed since the last tick.
43+
delta_time: The amount of time that has passed since the last tick.
4444
"""
4545
self._tick_delta_time = delta_time * self._tick_speed
4646
self._elapsed_time += self._tick_delta_time
@@ -51,7 +51,7 @@ def set_tick_speed(self, new_tick_speed: float):
5151
Set the speed of time for this clock.
5252
5353
Args:
54-
new_tick_speed (float): A multiplier on the 'speed' of time.
54+
new_tick_speed: A multiplier on the 'speed' of time.
5555
i.e. a value of 0.5 means time elapsed half as fast for this clock.
5656
"""
5757
self._tick_speed = new_tick_speed
@@ -61,7 +61,7 @@ def time_since(self, time: float) -> float:
6161
Calculate the amount of time that has passed since the given time.
6262
6363
Args:
64-
time (float): The time to compare against.
64+
time: The time to compare against.
6565
"""
6666
return self._elapsed_time - time
6767

@@ -70,7 +70,7 @@ def ticks_since(self, tick: int) -> int:
7070
Calculate the number of ticks that have occurred since the given tick.
7171
7272
Args:
73-
tick (int): The tick to compare against.
73+
tick: The tick to compare against.
7474
"""
7575
return self._tick - tick
7676

@@ -123,8 +123,8 @@ class FixedClock(Clock):
123123
Arcade provides a global fixed clock which is automatically ticked every update
124124
125125
Args:
126-
sibling (Clock): The unfixed clock which this clock will sync with.
127-
fixed_tick_rate (float, optional): The fixed number of seconds that pass
126+
sibling: The unfixed clock which this clock will sync with.
127+
fixed_tick_rate: The fixed number of seconds that pass
128128
for this clock every tick. Defaults to ``1.0 / 60.0``.
129129
"""
130130

@@ -138,7 +138,7 @@ def set_tick_speed(self, new_tick_speed: float):
138138
Set the speed of time for this clock.
139139
140140
Args:
141-
new_tick_speed (float): A multiplier on the 'speed' of time.
141+
new_tick_speed: A multiplier on the 'speed' of time.
142142
i.e. a value of 0.5 means time elapsed half as fast for this clock
143143
"""
144144
raise ValueError(
@@ -150,7 +150,7 @@ def tick(self, delta_time: float):
150150
Update the clock with the time that has passed since the last tick.
151151
152152
Args:
153-
delta_time (float): The amount of time that has passed since the last tick.
153+
delta_time: The amount of time that has passed since the last tick.
154154
"""
155155
if delta_time != self._fixed_rate:
156156
raise ValueError(
@@ -184,11 +184,11 @@ def _setup_clock(initial_elapsed: float = 0.0, initial_tick: int = 0, tick_speed
184184
Private method used by the arcade window to setup the global clock post initialization.
185185
186186
Args:
187-
initial_elapsed (float, optional): The amount of time the clock should assume
187+
initial_elapsed: The amount of time the clock should assume
188188
has already occurred. Defaults to 0.0
189-
initial_tick (int, optional): The number of ticks the clock should assume has
189+
initial_tick: The number of ticks the clock should assume has
190190
already occurred. Defaults to 0.
191-
tick_speed (float, optional): A multiplier on the 'speed' of time.
191+
tick_speed: A multiplier on the 'speed' of time.
192192
i.e. a value of 0.5 means time elapsed half as fast for this clock.
193193
Defaults to 1.0.
194194
"""
@@ -203,7 +203,7 @@ def _setup_fixed_clock(fixed_tick_rate: float = 1.0 / 60.0):
203203
post initialization.
204204
205205
Args:
206-
fixed_tick_rate (float, optional): The fixed number of seconds that pass
206+
fixed_tick_rate: The fixed number of seconds that pass
207207
for this clock every tick. Defaults to 1.0 / 60.0
208208
"""
209209
GLOBAL_FIXED_CLOCK._elapsed_time = GLOBAL_CLOCK.time # noqa: SLF001

arcade/future/sub_clock.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from __future__ import annotations
2+
3+
from typing import Optional, Union
4+
5+
from arcade.clock import GLOBAL_CLOCK, Clock
6+
7+
8+
def boot_strap_clock(clock: Optional[Clock] = None) -> Clock:
9+
"""
10+
Because the sub_clock is not a fully featured part of arcade we have to
11+
manipulate the clocks before the can be used with sub_clocks.
12+
13+
This step will no longer be required when SubClocks become part of the main
14+
library.
15+
16+
calling it will boostrap the global clock.
17+
DO NOT CALL MORE THAN ONCE PER CLOCK.
18+
19+
Args:
20+
clock: a clcok that has yet to be setup. Defaults to arcade.clock.GLOBAL_CLOCK.
21+
"""
22+
clock = clock or GLOBAL_CLOCK
23+
24+
if hasattr(clock, "children"):
25+
raise ValueError(f"The clock {clock} has already been bootstrapped.")
26+
27+
# No type check will ever like this, but we do what we must.
28+
clock.children = [] # type: ignore
29+
30+
def recursive_tick(delta_time: float) -> None:
31+
clock.tick(delta_time)
32+
for child in clock.children: # type: ignore
33+
child.tick(clock._tick_delta_time)
34+
35+
# Hey we did a decorator manually! what a time to be alive.
36+
clock.tick = recursive_tick # type: ignore
37+
38+
def add_child(child: SubClock) -> None:
39+
clock.children.append(child) # type: ignore
40+
41+
clock.add_child = add_child # type: ignore
42+
43+
return clock
44+
45+
46+
class SubClock(Clock):
47+
"""
48+
A SubClock which gets ticked by a parent clock and can have its flow
49+
of time altered independantly of its parent or siblings.
50+
51+
Args:
52+
parent: The clock which will tick the SubClock.
53+
could be the GLOBAL_CLOCK or another SubClock
54+
tick_speed: A multiplier on how the 'speed' of time.
55+
i.e. a value of 0.5 means time elapsed half as fast for this clock. Defaults to 1.0.
56+
"""
57+
58+
def __init__(self, parent: Union[Clock, SubClock, None] = None, tick_speed: float = 1) -> None:
59+
parent = parent or GLOBAL_CLOCK
60+
super().__init__(parent._elapsed_time, parent._tick, tick_speed)
61+
self.children: list[SubClock] = []
62+
try:
63+
parent.add_child(self) # type: ignore
64+
except AttributeError:
65+
raise AttributeError(
66+
f"The clock {parent} has not been bootstrapped properly"
67+
f"call boot_strap_clock({parent}) before adding children"
68+
)
69+
70+
def add_child(self, child: SubClock) -> None:
71+
self.children.append(child)
72+
73+
def tick(self, delta_time: float) -> None:
74+
super().tick(delta_time)
75+
76+
for child in self.children:
77+
child.tick(self.delta_time)

0 commit comments

Comments
 (0)