Skip to content

Commit 55c88d2

Browse files
Experimental new version of the window which provides a fixed update. (#1944)
* Started working on Clock and Timer classes * Mostly finished clock and timer * Created the updated window class The fixed update implementation is created, but classes to access the clocks and other variables is still necessary. * Tired best to fix linting. Can't fix a few issues due to it being an experimental view/window. * Add __init__.py for clock in experimental * Top-level docstring and experimental.clock.clock_window.Window docstring fixes * Add fixed update None return annotations * Fix missing annotation on TextureAnimationSprite._animation * Use nasty typing tricks to make mypy pass * Fix no newline to make ruff pass --------- Co-authored-by: pushfoo <36696816+pushfoo@users.noreply.github.com>
1 parent b0790cb commit 55c88d2

File tree

5 files changed

+1487
-1
lines changed

5 files changed

+1487
-1
lines changed

arcade/experimental/clock/__init__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""Experimental fixed update support.
2+
3+
.. warning:: The classes in this module have incomplete typing!
4+
5+
Using them in your projects may make your IDE or type checker
6+
complain. Pull requests welcome.
7+
8+
See the following pull request for more information:
9+
`https://github.com/pythonarcade/arcade/pull/1944`_
10+
"""
11+
from arcade.experimental.clock.timer import Timer
12+
from arcade.experimental.clock.clock import Clock
13+
from arcade.experimental.clock.clock_window import View, Window
14+
15+
16+
__all__ = [
17+
"Timer",
18+
"Clock",
19+
"View",
20+
"Window"
21+
]

arcade/experimental/clock/clock.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
from typing import Optional, Set
2+
from arcade.experimental.clock.timer import Timer
3+
4+
5+
class Clock:
6+
"""
7+
A clock for managing elapsed time, delta time, and timers
8+
9+
A clock has a tick method that can either be called directly
10+
or is called by its parent clock. If a clock has a parent
11+
DO NOT CALL its tick method.
12+
13+
A clock can have any number of child timers or clocks.
14+
The children and timers are stored in unordered sets, therefore
15+
the properties which return them make no promises on the order.
16+
17+
The tick speed of a clock is how fast time elapses for it.
18+
19+
When a clock calls tick on its children it passes its modified delta_time
20+
21+
Arcade's clocks are synchronous. No matter how long an update takes
22+
all queries to a clock's elapsed time will be the same. This ensures
23+
that two objects who have the same lifespan and are created at the
24+
same time will die on the same frame in the future.
25+
"""
26+
27+
def __init__(self, *,
28+
tick_speed: float = 1.0,
29+
initial_elapsed_time: float = 0.0,
30+
initial_tick_count: int = 0,
31+
frozen: bool = False,
32+
parent: Optional["Clock"] = None
33+
):
34+
self.tick_speed: float = tick_speed
35+
self._frozen: bool = frozen
36+
37+
self._elapsed_time: float = initial_elapsed_time
38+
self._tick_count: int = initial_tick_count
39+
40+
self._parent: Optional[Clock] = parent
41+
42+
self._children: Set[Clock] = set()
43+
self._timers: Set[Timer] = set()
44+
45+
self._delta_time_raw: float = 0.0
46+
47+
def tick(self, delta_time: float):
48+
self._tick_count += 1
49+
if self._frozen:
50+
return
51+
self._delta_time_raw = delta_time
52+
53+
self._elapsed_time = self._delta_time_raw * self.tick_speed
54+
55+
for child in tuple(self._children):
56+
child.tick(self._delta_time_raw * self.tick_speed)
57+
58+
for timer in tuple(self._timers):
59+
if timer.complete:
60+
timer.kill()
61+
timer.check()
62+
63+
#def create_new_child(self, *,
64+
# tick_speed: float = 1.0,
65+
# inherit_elapsed: bool = False,
66+
# inherit_count: bool = False,
67+
# lifespan: float = 0.0
68+
# ) -> "Clock":
69+
# pass
70+
71+
#def create_new_timer(self, duration: float, callback: Callable,
72+
# *args,
73+
# **kwargs
74+
# ) -> Timer:
75+
# pass
76+
77+
def add_clock(self, new_child: "Clock"):
78+
pass
79+
80+
def add_timer(self, new_timer: Timer):
81+
pass
82+
83+
def free(self):
84+
if self._parent:
85+
self._parent.pop_child(self)
86+
87+
def time_since(self, start: float):
88+
return self._elapsed_time - start
89+
90+
@property
91+
def delta_time(self):
92+
return self._delta_time_raw * self._tick_speed
93+
94+
@property
95+
def delta_time_raw(self):
96+
return self._delta_time_raw
97+
98+
@property
99+
def elapsed(self):
100+
return self._elapsed_time
101+
102+
@property
103+
def frozen(self):
104+
return self._frozen
105+
106+
def freeze(self):
107+
self._frozen = True
108+
109+
def unfreeze(self):
110+
self._frozen = False
111+
112+
def toggle_frozen(self) -> bool:
113+
self._frozen = bool(1 - self._frozen)
114+
return self._frozen
115+
116+
@property
117+
def children(self):
118+
return tuple(self._children)
119+
120+
def pop_child(self, child: "Clock"):
121+
pass
122+
123+
@property
124+
def timers(self):
125+
return tuple(self._timers)
126+
127+
def pop_timer(self, timer: Timer):
128+
"""
129+
Popping a timer allows you to remove a timer from a clock without destroying the timer.
130+
"""
131+
pass
132+
133+
@property
134+
def parent(self):
135+
return self._parent
136+
137+
def transfer_parent(self, new_parent):
138+
pass
139+
140+
@property
141+
def tick_count(self):
142+
return self._tick_count

0 commit comments

Comments
 (0)