Skip to content

Commit

Permalink
Merge pull request #2344 from pythonarcade/sub-clock
Browse files Browse the repository at this point in the history
Add a SubClock class to `arcade.future`
  • Loading branch information
DragonMoffon authored Aug 8, 2024
2 parents 8c17aed + 2c4161f commit f44233c
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 15 deletions.
30 changes: 15 additions & 15 deletions arcade/clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ class Clock:
only certain elements rather than everything.
Args:
initial_elapsed (float, optional): The amount of time the clock should assume has
initial_elapsed: The amount of time the clock should assume has
already occurred. Defaults to 0.0
initial_tick (int, optional): The number of ticks the clock should assume has already
initial_tick: The number of ticks the clock should assume has already
occurred. Defaults to 0.
tick_speed (float, optional): A multiplier on how the 'speed' of time.
tick_speed: A multiplier on how the 'speed' of time.
i.e. a value of 0.5 means time elapsed half as fast for this clock. Defaults to 1.0.
"""

Expand All @@ -40,7 +40,7 @@ def tick(self, delta_time: float):
Update the clock with the time that has passed since the last tick.
Args:
delta_time (float): The amount of time that has passed since the last tick.
delta_time: The amount of time that has passed since the last tick.
"""
self._tick_delta_time = delta_time * self._tick_speed
self._elapsed_time += self._tick_delta_time
Expand All @@ -51,7 +51,7 @@ def set_tick_speed(self, new_tick_speed: float):
Set the speed of time for this clock.
Args:
new_tick_speed (float): A multiplier on the 'speed' of time.
new_tick_speed: A multiplier on the 'speed' of time.
i.e. a value of 0.5 means time elapsed half as fast for this clock.
"""
self._tick_speed = new_tick_speed
Expand All @@ -61,7 +61,7 @@ def time_since(self, time: float) -> float:
Calculate the amount of time that has passed since the given time.
Args:
time (float): The time to compare against.
time: The time to compare against.
"""
return self._elapsed_time - time

Expand All @@ -70,7 +70,7 @@ def ticks_since(self, tick: int) -> int:
Calculate the number of ticks that have occurred since the given tick.
Args:
tick (int): The tick to compare against.
tick: The tick to compare against.
"""
return self._tick - tick

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

Expand All @@ -138,7 +138,7 @@ def set_tick_speed(self, new_tick_speed: float):
Set the speed of time for this clock.
Args:
new_tick_speed (float): A multiplier on the 'speed' of time.
new_tick_speed: A multiplier on the 'speed' of time.
i.e. a value of 0.5 means time elapsed half as fast for this clock
"""
raise ValueError(
Expand All @@ -150,7 +150,7 @@ def tick(self, delta_time: float):
Update the clock with the time that has passed since the last tick.
Args:
delta_time (float): The amount of time that has passed since the last tick.
delta_time: The amount of time that has passed since the last tick.
"""
if delta_time != self._fixed_rate:
raise ValueError(
Expand Down Expand Up @@ -184,11 +184,11 @@ def _setup_clock(initial_elapsed: float = 0.0, initial_tick: int = 0, tick_speed
Private method used by the arcade window to setup the global clock post initialization.
Args:
initial_elapsed (float, optional): The amount of time the clock should assume
initial_elapsed: The amount of time the clock should assume
has already occurred. Defaults to 0.0
initial_tick (int, optional): The number of ticks the clock should assume has
initial_tick: The number of ticks the clock should assume has
already occurred. Defaults to 0.
tick_speed (float, optional): A multiplier on the 'speed' of time.
tick_speed: A multiplier on the 'speed' of time.
i.e. a value of 0.5 means time elapsed half as fast for this clock.
Defaults to 1.0.
"""
Expand All @@ -203,7 +203,7 @@ def _setup_fixed_clock(fixed_tick_rate: float = 1.0 / 60.0):
post initialization.
Args:
fixed_tick_rate (float, optional): The fixed number of seconds that pass
fixed_tick_rate: The fixed number of seconds that pass
for this clock every tick. Defaults to 1.0 / 60.0
"""
GLOBAL_FIXED_CLOCK._elapsed_time = GLOBAL_CLOCK.time # noqa: SLF001
Expand Down
77 changes: 77 additions & 0 deletions arcade/future/sub_clock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from __future__ import annotations

from typing import Optional, Union

from arcade.clock import GLOBAL_CLOCK, Clock


def boot_strap_clock(clock: Optional[Clock] = None) -> Clock:
"""
Because the sub_clock is not a fully featured part of arcade we have to
manipulate the clocks before the can be used with sub_clocks.
This step will no longer be required when SubClocks become part of the main
library.
calling it will boostrap the global clock.
DO NOT CALL MORE THAN ONCE PER CLOCK.
Args:
clock: a clcok that has yet to be setup. Defaults to arcade.clock.GLOBAL_CLOCK.
"""
clock = clock or GLOBAL_CLOCK

if hasattr(clock, "children"):
raise ValueError(f"The clock {clock} has already been bootstrapped.")

# No type check will ever like this, but we do what we must.
clock.children = [] # type: ignore

def recursive_tick(delta_time: float) -> None:
clock.tick(delta_time)
for child in clock.children: # type: ignore
child.tick(clock._tick_delta_time)

# Hey we did a decorator manually! what a time to be alive.
clock.tick = recursive_tick # type: ignore

def add_child(child: SubClock) -> None:
clock.children.append(child) # type: ignore

clock.add_child = add_child # type: ignore

return clock


class SubClock(Clock):
"""
A SubClock which gets ticked by a parent clock and can have its flow
of time altered independantly of its parent or siblings.
Args:
parent: The clock which will tick the SubClock.
could be the GLOBAL_CLOCK or another SubClock
tick_speed: A multiplier on how the 'speed' of time.
i.e. a value of 0.5 means time elapsed half as fast for this clock. Defaults to 1.0.
"""

def __init__(self, parent: Union[Clock, SubClock, None] = None, tick_speed: float = 1) -> None:
parent = parent or GLOBAL_CLOCK
super().__init__(parent._elapsed_time, parent._tick, tick_speed)
self.children: list[SubClock] = []
try:
parent.add_child(self) # type: ignore
except AttributeError:
raise AttributeError(
f"The clock {parent} has not been bootstrapped properly"
f"call boot_strap_clock({parent}) before adding children"
)

def add_child(self, child: SubClock) -> None:
self.children.append(child)

def tick(self, delta_time: float) -> None:
super().tick(delta_time)

for child in self.children:
child.tick(self.delta_time)

0 comments on commit f44233c

Please sign in to comment.