15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
This module provide a main loop for Soya, with FPS regulation. It is a simplified
21
version of the Py2Play idler ; if you want to use Py2Play in addition to Soya,
22
you should rather use the Py2Play idler.
24
The following global module attributes are noticeable:
26
- ROUND_DURATION: The duration of a round. Round is the idler's time unit. The idler calls
27
successively begin_round(), advance_time() (possibly several times) and end_round(); it
28
is granted that ALL rounds correspond to a period of duration ROUND_DURATION (though
29
the different period may not be regularly spread over time).
32
- MIN_FRAME_DURATION: minimum duration for a frame. This attribute can be used to limit
33
the maximum FPS to save CPU time; e.g. FPS higher than 30-40 is usually useless.
34
Default is 0.025, which limits FPS to 40 in theory and to about 33 in practice
35
(I don't know why there is a difference between theory and practice !).
37
- IDLER: a reference to the last created idler."""
42
ROUND_DURATION = 0.030
43
MIN_FRAME_DURATION = 0.020
19
warnings.warn("The content of this module is now in the soya module.", DeprecationWarning)
21
from soya import Idler
52
A main loop with FPS regulation.
54
Interesting attributes:
56
- next_round_tasks: a list of callable (taking no arg) that will be called once, just
57
after the beginning of the next round.
59
- scene: the scene associated to this idler."""
61
def __init__(self, scene = None):
62
"""Idler(scene) -> Idler
64
Creates a new idler for scene SCENE."""
65
self.next_round_tasks = []
76
Starts idling with a new thread."""
78
thread.start_new_thread(self.idle, ())
83
Stops idling. The stopping may not occur immediately, but at the end of the next iteration."""
89
Starts idling with the current thread. This method doesn't finish, until you call Idler.stop()."""
91
self.time = last_fps_computation_time = time.time()
92
self.time_since_last_round = 0.0
97
while self.state >= PLAYING:
99
while (self.state >= PLAYING) and (nb_frame < 80):
100
nb_frame = nb_frame + 1
102
while 1: # Sleep until at least MIN_FRAME_DURATION second has passed since the last frame
103
current = time.time()
104
delta = current - self.time
106
if delta > MIN_FRAME_DURATION: break
107
time.sleep(MIN_FRAME_DURATION - delta)
111
while self.time_since_last_round + delta > ROUND_DURATION: # Start a new frame
112
spent_time = ROUND_DURATION - self.time_since_last_round
114
self.advance_time(spent_time / ROUND_DURATION) # Complete the previous round
115
self.end_round() # Ends the previous round
117
self.begin_round() # Prepare the following round
119
if self.next_round_tasks:
120
for task in self.next_round_tasks: task()
121
self.next_round_tasks = []
123
delta = delta - spent_time
124
self.time_since_last_round = 0
126
self.advance_time(delta / ROUND_DURATION) # start the current round
127
self.time_since_last_round = self.time_since_last_round + delta
131
current = time.time()
132
self.fps = nb_frame / (current - last_fps_computation_time)
133
last_fps_computation_time = current
135
def begin_round(self):
136
"""Idler.begin_round()
138
Called by Idler.idle when a new round begins; default implementation delegates to Idler.scene.begin_round."""
139
if self.scene: self.scene.begin_round()
144
Called by Idler.idle when a round is finished; default implementation delegates to Idler.scene.end_round."""
145
if self.scene: self.scene.end_round()
147
def advance_time(self, proportion):
148
"""Idler.advance_time()
150
Called by Idler.idle when a piece of a round has occured; default implementation delegates to Idler.scene.advance_time.
151
PROPORTION is the proportion of the current round's time that has passed (1.0 for an entire round)."""
153
soya.advance_time(proportion) # for C coded stuff
154
self.scene.advance_time(proportion)
159
Called by Idler.idle when rendering is needed; default implementation calls soya.render."""