Skip to content

Commit 30c36b0

Browse files
committed
LukeMS's port of the PyGame time API to sdl2
LukeMS has this added to his personal sdl2 repo on GitHub, but hasn't offered the patch upstream. Enough people seem to want it that I've decided ti offer it as a PR. I didn't take time to write unit tests for it, sorry. Closes py-sdl#168.
1 parent e5c8cba commit 30c36b0

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

sdl2/ext/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@
1919
from .pixelaccess import *
2020
from .sprite import *
2121
from .surface import *
22+
from .time import *
2223
from .window import *

sdl2/ext/time.py

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"""Track and control game time and framerate.
2+
3+
.. note::
4+
5+
This is a **MODIFIED**, pure Python implementation of time-related functions
6+
from `PyGameSDL2's time`_, in Cython, released under zlib license.
7+
8+
.. code-block:: none
9+
10+
PygameSDL2 Notice / zlib License:
11+
12+
--------------------------------------------------------------------------
13+
Original work:
14+
Copyright 2014 Tom Rothamel <[email protected]>
15+
Copyright 2014 Patrick Dawson <[email protected]>
16+
Modified work:
17+
Copyright 2017 Lucas Siqueira <[email protected]>
18+
19+
This software is provided 'as-is', without any express or implied
20+
warranty. In no event will the authors be held liable for any damages
21+
arising from the use of this software.
22+
23+
Permission is granted to anyone to use this software for any purpose,
24+
including commercial applications, and to alter it and redistribute it
25+
freely, subject to the following restrictions:
26+
27+
1. The origin of this software must not be misrepresented; you must not
28+
claim that you wrote the original software. If you use this software
29+
in a product, an acknowledgment in the product documentation would be
30+
appreciated but is not required.
31+
2. Altered source versions must be plainly marked as such, and must not
32+
be misrepresented as being the original software.
33+
3. This notice may not be removed or altered from any source
34+
distribution.
35+
--------------------------------------------------------------------------
36+
37+
.. _`PyGameSDL2's time`: https://www.github.com/renpy/pygame_sdl2/blob/\
38+
master/src/pygame_sdl2/pygame_time.pyx
39+
"""
40+
41+
import math
42+
from ..timer import SDL_Delay, SDL_GetTicks
43+
44+
45+
__all__ = ('Clock', 'wait', 'get_time', 'get_delta')
46+
47+
48+
def get_delta(t0):
49+
"""Get the time elapsed since the passed time."""
50+
return get_time - t0
51+
52+
53+
def get_time():
54+
"""Get the current time from SDL clock."""
55+
return SDL_GetTicks()
56+
57+
58+
def wait(milliseconds):
59+
"""Pause the program for an amount of time.
60+
61+
Will pause for a given number of milliseconds. This function sleeps the
62+
process to share the processor with other programs. A program that waits
63+
for even a few milliseconds will consume very little processor time.
64+
65+
Usage:
66+
wait(milliseconds)
67+
68+
Returns:
69+
int (the actual number of milliseconds used)
70+
"""
71+
start = SDL_GetTicks()
72+
SDL_Delay(int(milliseconds))
73+
return SDL_GetTicks() - start
74+
75+
76+
class Clock:
77+
"""Clock is used track and control the framerate of a game.
78+
79+
The clock can be used to limit the framerate of a game, as well as track
80+
the time used per frame.
81+
82+
Usage:
83+
clock = time.Clock()
84+
"""
85+
86+
def __init__(self):
87+
"""Initialization."""
88+
self.last = SDL_GetTicks()
89+
self.last_frames = []
90+
self.frametime = 0
91+
self.raw_frametime = 0
92+
93+
def tick(self, framerate=0):
94+
"""Update the Clock.
95+
96+
This method should be called once per frame. It will compute how many
97+
milliseconds have passed since the previous call.
98+
99+
If you pass the optional framerate argument the function will delay
100+
to keep the game running slower than the given ticks per second. This
101+
can be used to help limit the runtime speed of a game. By calling
102+
clock.tick(40) once per frame, the program will never run at more
103+
than 40 frames per second.
104+
105+
Usage:
106+
tick(framerate=0)
107+
108+
Returns:
109+
float (milliseconds)
110+
"""
111+
now = SDL_GetTicks()
112+
self.raw_frametime = now - self.last
113+
while len(self.last_frames) > 9:
114+
self.last_frames.pop(0)
115+
if framerate == 0:
116+
self.last = now
117+
self.last_frames.append(self.raw_frametime)
118+
return self.raw_frametime
119+
frame_duration = 1.0 / framerate * 1000
120+
if self.raw_frametime < frame_duration:
121+
wait(frame_duration - self.raw_frametime)
122+
now = SDL_GetTicks()
123+
self.frametime = now - self.last
124+
self.last = now
125+
self.last_frames.append(self.frametime)
126+
return self.frametime
127+
128+
def get_time(self):
129+
"""Time used in the previous tick.
130+
131+
Returns the parameter passed to the last call to Clock.tick().
132+
133+
Usage:
134+
clock.get_time()
135+
136+
Returns:
137+
int (milliseconds)
138+
"""
139+
return self.frametime
140+
141+
def get_rawtime(self):
142+
"""Actual time used in the previous tick.
143+
144+
Similar to Clock.get_time(), but this does not include any time used
145+
while clock.tick() was delaying to limit the framerate.
146+
147+
Usage:
148+
clock.get_rawtime()
149+
150+
Returns:
151+
int (milliseconds)
152+
"""
153+
return self.raw_frametime
154+
155+
def get_fps(self):
156+
"""Compute the clock framerate.
157+
158+
Compute your game's framerate (in frames per second). It is computed
159+
by averaging the last ten calls to Clock.tick().
160+
161+
Usage:
162+
get_fps()
163+
164+
Returns:
165+
float
166+
"""
167+
total_time = sum(self.last_frames)
168+
average_time = total_time / 1000.0 / len(self.last_frames)
169+
average_fps = 1.0 / average_time
170+
return 0 if math.isnan(average_fps) else average_fps

0 commit comments

Comments
 (0)