pgzero-plus 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pgzero-plus might be problematic. Click here for more details.

pgzero/animation.py ADDED
@@ -0,0 +1,244 @@
1
+ # Easing Functions ported from the Clutter Project via http://kivy.org/
2
+ # http://www.clutter-project.org/docs/clutter/stable/ClutterAlpha.html
3
+
4
+
5
+ from math import sin, pow, pi
6
+
7
+ from .clock import each_tick, unschedule
8
+ from .spellcheck import suggest
9
+
10
+ TWEEN_FUNCTIONS = {}
11
+
12
+
13
+ def tweener(f):
14
+ TWEEN_FUNCTIONS[f.__name__] = f
15
+ return f
16
+
17
+
18
+ @tweener
19
+ def linear(n):
20
+ return n
21
+
22
+
23
+ @tweener
24
+ def accelerate(n):
25
+ return n * n
26
+
27
+
28
+ @tweener
29
+ def decelerate(n):
30
+ return -1.0 * n * (n - 2.0)
31
+
32
+
33
+ @tweener
34
+ def accel_decel(n):
35
+ p = n * 2
36
+ if p < 1:
37
+ return 0.5 * p * p
38
+ p -= 1.0
39
+ return -0.5 * (p * (p - 2.0) - 1.0)
40
+
41
+
42
+ @tweener
43
+ def in_elastic(n):
44
+ p = .3
45
+ s = p / 4.0
46
+ q = n
47
+ if q == 1:
48
+ return 1.0
49
+ q -= 1.0
50
+ return -(pow(2, 10 * q) * sin((q - s) * (2 * pi) / p))
51
+
52
+
53
+ @tweener
54
+ def out_elastic(n):
55
+ p = .3
56
+ s = p / 4.0
57
+ q = n
58
+ if q == 1:
59
+ return 1.0
60
+ return pow(2, -10 * q) * sin((q - s) * (2 * pi) / p) + 1.0
61
+
62
+
63
+ @tweener
64
+ def in_out_elastic(n):
65
+ p = .3 * 1.5
66
+ s = p / 4.0
67
+ q = n * 2
68
+ if q == 2:
69
+ return 1.0
70
+ if q < 1:
71
+ q -= 1.0
72
+ return -.5 * (pow(2, 10 * q) * sin((q - s) * (2.0 * pi) / p))
73
+ else:
74
+ q -= 1.0
75
+ return pow(2, -10 * q) * sin((q - s) * (2.0 * pi) / p) * .5 + 1.0
76
+
77
+
78
+ def _out_bounce_internal(t, d):
79
+ p = t / d
80
+ if p < (1.0 / 2.75):
81
+ return 7.5625 * p * p
82
+ elif p < (2.0 / 2.75):
83
+ p -= (1.5 / 2.75)
84
+ return 7.5625 * p * p + .75
85
+ elif p < (2.5 / 2.75):
86
+ p -= (2.25 / 2.75)
87
+ return 7.5625 * p * p + .9375
88
+ else:
89
+ p -= (2.625 / 2.75)
90
+ return 7.5625 * p * p + .984375
91
+
92
+
93
+ def _in_bounce_internal(t, d):
94
+ return 1.0 - _out_bounce_internal(d - t, d)
95
+
96
+
97
+ @tweener
98
+ def bounce_end(n):
99
+ return _out_bounce_internal(n, 1.)
100
+
101
+
102
+ @tweener
103
+ def bounce_start(n):
104
+ return _in_bounce_internal(n, 1.)
105
+
106
+
107
+ @tweener
108
+ def bounce_start_end(n):
109
+ p = n * 2.
110
+ if p < 1.:
111
+ return _in_bounce_internal(p, 1.) * .5
112
+ return _out_bounce_internal(p - 1., 1.) * .5 + .5
113
+
114
+
115
+ def tween(n, start, end):
116
+ return start + (end - start) * n
117
+
118
+
119
+ def tween_attr(n, start, end):
120
+ if isinstance(start, tuple):
121
+ return tuple(tween(n, a, b) for a, b in zip(start, end))
122
+ elif isinstance(start, list):
123
+ return [tween(n, a, b) for a, b in zip(start, end)]
124
+ else:
125
+ return tween(n, start, end)
126
+
127
+
128
+ class Animation:
129
+ """An animation manager for object attribute animations.
130
+
131
+ Each keyword argument given to the Animation on creation (except
132
+ "type" and "duration") will be *tweened* from their current value
133
+ on the object to the target value specified.
134
+
135
+ If the value is a list or tuple, then each value inside that will
136
+ be tweened.
137
+
138
+ The update() method is automatically scheduled with the clock for
139
+ the duration of the animation.
140
+
141
+ """
142
+ animations = [] # Stores strong references to objects being animated.
143
+
144
+ # Animations are stored in _animation_dict under (object id, target
145
+ # attribute) keys. Objects may not be hashable, so the id, rather than
146
+ # the object itself, is needed.
147
+ # Animations with multiple targets will appear here multiple times.
148
+ # Newly scheduled animations will overwrite new ones. Once an animation
149
+ # ends, it is removed from this dict.
150
+ # Note that Animation keeps a reference to "its" object, so the id in the
151
+ # key will be valid as long as the animation lives.
152
+ _animation_dict = {}
153
+
154
+ def __init__(self, object, tween='linear', duration=1, on_finished=None,
155
+ **targets):
156
+ self.targets = targets
157
+ try:
158
+ self.function = TWEEN_FUNCTIONS[tween]
159
+ except KeyError:
160
+ suggested_tween = suggest(tween, TWEEN_FUNCTIONS.keys())
161
+ if len(suggested_tween) > 0:
162
+ raise KeyError(
163
+ 'No tween called %s found, did you mean %s?'
164
+ % (tween, suggested_tween[0])
165
+ )
166
+ else:
167
+ raise KeyError('No tween called %s found.' % tween)
168
+ self.duration = duration
169
+ self.on_finished = on_finished
170
+ self.t = 0
171
+ self.object = object
172
+ self.initial = {}
173
+ self._running = True
174
+ for k in self.targets:
175
+ try:
176
+ a = getattr(object, k)
177
+ except AttributeError:
178
+ raise ValueError(
179
+ 'object %r has no attribute %s to animate' % (object, k)
180
+ )
181
+ self.initial[k] = a
182
+ key = id(object), k
183
+ previous_animation = self._animation_dict.get(key)
184
+ if previous_animation is not None:
185
+ previous_animation._remove_target(k)
186
+ self._animation_dict[key] = self
187
+ each_tick(self.update)
188
+ self.animations.append(self)
189
+
190
+ @property
191
+ def running(self):
192
+ """Running state of the animation.
193
+
194
+ True if the animation is running.
195
+ False if the duration has elapsed or the stop() method was called.
196
+ """
197
+ return self._running
198
+
199
+ def update(self, dt):
200
+ self.t += dt
201
+ n = self.t / self.duration
202
+ if n > 1:
203
+ n = 1
204
+ self.stop(complete=True)
205
+ if self.on_finished is not None:
206
+ self.on_finished()
207
+ return
208
+ n = self.function(n)
209
+ for k in self.targets:
210
+ v = tween_attr(n, self.initial[k], self.targets[k])
211
+ setattr(self.object, k, v)
212
+
213
+ def stop(self, complete=False):
214
+ """Stop the animation, optionally completing the transition to the final
215
+ property values.
216
+
217
+ :param complete: If True, the object will have its targets
218
+ set to their final values for the animation. If not, the
219
+ targets will be set to some value between the start and
220
+ end values.
221
+ """
222
+ if not self._running:
223
+ # Don't do anything if already stopped.
224
+ return
225
+
226
+ self._running = False
227
+ if complete:
228
+ for k in self.targets:
229
+ setattr(self.object, k, self.targets[k])
230
+ for k in list(self.targets):
231
+ self._remove_target(k, stop=False)
232
+ unschedule(self.update)
233
+ self.animations.remove(self)
234
+
235
+ def _remove_target(self, target, stop=True):
236
+ del self.targets[target]
237
+ del self._animation_dict[id(self.object), target]
238
+ if not self.targets and stop:
239
+ self.stop()
240
+
241
+
242
+ def animate(object, tween='linear', duration=1, on_finished=None, **targets):
243
+ return Animation(object, tween, duration, on_finished=on_finished,
244
+ **targets)
pgzero/builtins.py ADDED
@@ -0,0 +1,45 @@
1
+ # Expose clock API as a builtin
2
+ from . import clock
3
+ from . import music
4
+ from . import tone
5
+ from .actor import Actor
6
+ from .sprites import Sprite, SpriteActor
7
+ from .storage import storage
8
+ from .keyboard import keyboard
9
+ from .animation import animate
10
+ from .rect import Rect, ZRect
11
+ from .loaders import images, sounds
12
+ from .constants import mouse, keys, keymods
13
+ from .game import Game, exit
14
+ from .tilemaps import load_tile_map_actors
15
+
16
+ # The actual screen will be installed here
17
+ from .screen import screen_instance as screen
18
+
19
+ # Global game state object. The runner replaces this with a fresh Game each time a game is run.
20
+ game = Game()
21
+
22
+
23
+ __all__ = [
24
+ "screen", # graphics output
25
+ "Actor",
26
+ "images",
27
+ "Sprite",
28
+ "SpriteActor", # graphics
29
+ "sounds",
30
+ "music",
31
+ "tone", # sound
32
+ "clock",
33
+ "animate", # timing
34
+ "Rect",
35
+ "ZRect", # geometry
36
+ "keyboard",
37
+ "mouse",
38
+ "keys",
39
+ "keymods", # input
40
+ "storage", # persistence
41
+ "Game",
42
+ "game",
43
+ "exit",
44
+ "load_tile_map_actors",
45
+ ]
pgzero/clock.py ADDED
@@ -0,0 +1,200 @@
1
+ """Clock/event scheduler.
2
+
3
+ This is a Pygame implementation of a scheduler inspired by the clock
4
+ classes in Pyglet.
5
+
6
+ """
7
+
8
+ import heapq
9
+ from weakref import ref
10
+ from functools import total_ordering
11
+ from types import MethodType
12
+
13
+ __all__ = ["Clock", "schedule", "schedule_interval", "unschedule", "clear"]
14
+
15
+ # This type can't be weakreffed in Python 3.4
16
+ builtin_function_or_method = type(open)
17
+
18
+
19
+ def weak_method(method):
20
+ """Quick weak method ref in case users aren't using Python 3.4"""
21
+ selfref = ref(method.__self__)
22
+ funcref = ref(method.__func__)
23
+
24
+ def weakref():
25
+ self = selfref()
26
+ func = funcref()
27
+ if self is None or func is None:
28
+ return None
29
+ return func.__get__(self)
30
+
31
+ return weakref
32
+
33
+
34
+ def mkref(o):
35
+ if isinstance(o, MethodType):
36
+ return weak_method(o)
37
+ else:
38
+ try:
39
+ return ref(o)
40
+ except TypeError:
41
+ if isinstance(o, builtin_function_or_method):
42
+ return lambda: o
43
+ raise
44
+
45
+
46
+ @total_ordering
47
+ class Event:
48
+ """An event scheduled for a future time.
49
+
50
+ Events are ordered by their scheduled execution time.
51
+
52
+ """
53
+
54
+ def __init__(self, time, cb, repeat=None):
55
+ self.time = time
56
+ self.repeat = repeat
57
+ self.cb = mkref(cb)
58
+ self.name = str(cb)
59
+ self.repeat = repeat
60
+
61
+ def __lt__(self, ano):
62
+ return self.time < ano.time
63
+
64
+ def __eq__(self, ano):
65
+ return self.time == ano.time
66
+
67
+ @property
68
+ def callback(self):
69
+ return self.cb()
70
+
71
+
72
+ class Clock:
73
+ """A clock used for event scheduling.
74
+
75
+ When tick() is called, all events scheduled for before now will be called
76
+ in order.
77
+
78
+ tick() would typically be called from the game loop for the default clock.
79
+
80
+ Additional clocks could be created - for example, a game clock that could
81
+ be suspended in pause screens. Your code must take care of calling tick()
82
+ or not. You could also run the clock at a different rate if desired, by
83
+ scaling dt before passing it to tick().
84
+
85
+ """
86
+
87
+ def __init__(self):
88
+ self.t = 0
89
+ self.fired = False
90
+ self.events = []
91
+ self._each_tick = []
92
+
93
+ def clear(self):
94
+ """Remove all handlers from this clock."""
95
+ self.events.clear()
96
+ self._each_tick.clear()
97
+
98
+ def schedule(self, callback, delay):
99
+ """Schedule callback to be called once, at `delay` seconds from now.
100
+
101
+ :param callback: A parameterless callable to be called.
102
+ :param delay: The delay before the call (in clock time / seconds).
103
+
104
+ """
105
+ heapq.heappush(self.events, Event(self.t + delay, callback, None))
106
+
107
+ def schedule_unique(self, callback, delay):
108
+ """Schedule callback to be called once, at `delay` seconds from now.
109
+
110
+ If it was already scheduled, postpone its firing.
111
+
112
+ :param callback: A parameterless callable to be called.
113
+ :param delay: The delay before the call (in clock time / seconds).
114
+
115
+ """
116
+ self.unschedule(callback)
117
+ self.schedule(callback, delay)
118
+
119
+ def schedule_interval(self, callback, delay):
120
+ """Schedule callback to be called every `delay` seconds.
121
+
122
+ The first occurrence will be after `delay` seconds.
123
+
124
+ :param callback: A parameterless callable to be called.
125
+ :param delay: The interval in seconds.
126
+
127
+ """
128
+ heapq.heappush(self.events, Event(self.t + delay, callback, delay))
129
+
130
+ def unschedule(self, callback):
131
+ """Unschedule the given callback.
132
+
133
+ If scheduled multiple times all instances will be unscheduled.
134
+
135
+ """
136
+ self.events = [e for e in self.events if e.callback != callback if e.callback is not None]
137
+ heapq.heapify(self.events)
138
+ self._each_tick = [e for e in self._each_tick if e() != callback]
139
+
140
+ def each_tick(self, callback):
141
+ """Schedule a callback to be called every tick.
142
+
143
+ Unlike the standard scheduler functions, the callable is passed the
144
+ elapsed clock time since the last call (the same value passed to tick).
145
+
146
+ """
147
+ self._each_tick.append(mkref(callback))
148
+
149
+ def _fire_each_tick(self, dt):
150
+ dead = [None]
151
+ for r in self._each_tick:
152
+ cb = r()
153
+ if cb is not None:
154
+ self.fired = True
155
+ try:
156
+ cb(dt)
157
+ except Exception:
158
+ import traceback
159
+
160
+ traceback.print_exc()
161
+ dead.append(cb)
162
+ self._each_tick = [e for e in self._each_tick if e() not in dead]
163
+
164
+ def tick(self, dt):
165
+ """Update the clock time and fire all scheduled events.
166
+
167
+ :param dt: The elapsed time in seconds.
168
+
169
+ """
170
+ self.fired = False
171
+ self.t += float(dt)
172
+ self._fire_each_tick(dt)
173
+ while self.events and self.events[0].time <= self.t:
174
+ ev = heapq.heappop(self.events)
175
+ cb = ev.callback
176
+ if not cb:
177
+ continue
178
+
179
+ if ev.repeat is not None:
180
+ self.schedule_interval(cb, ev.repeat)
181
+
182
+ self.fired = True
183
+ try:
184
+ cb()
185
+ except Exception:
186
+ import traceback
187
+
188
+ traceback.print_exc()
189
+ self.unschedule(cb)
190
+
191
+
192
+ # One instance of a clock is available by default, to simplify the API
193
+ clock = Clock()
194
+ tick = clock.tick
195
+ schedule = clock.schedule
196
+ schedule_interval = clock.schedule_interval
197
+ schedule_unique = clock.schedule_unique
198
+ unschedule = clock.unschedule
199
+ each_tick = clock.each_tick
200
+ clear = clock.clear
pgzero/constants.py ADDED
@@ -0,0 +1,33 @@
1
+ """Names for constants returned by Pygame."""
2
+ from enum import IntEnum
3
+ import pygame.locals
4
+
5
+
6
+ # Event type indicating the end of a music track
7
+ MUSIC_END = 99
8
+
9
+
10
+ class mouse(IntEnum):
11
+ LEFT = 1
12
+ MIDDLE = 2
13
+ RIGHT = 3
14
+ WHEEL_UP = 4
15
+ WHEEL_DOWN = 5
16
+
17
+
18
+ # Use a code generation approach to copy Pygame's key constants out into
19
+ # a Python 3.4 IntEnum, stripping prefixes where possible
20
+ srclines = ["class keys(IntEnum):"]
21
+ for k, v in vars(pygame.locals).items():
22
+ if k.startswith('K_'):
23
+ if k[2].isalpha():
24
+ k = k[2:]
25
+ srclines.append(" %s = %d" % (k.upper(), v))
26
+
27
+ srclines.append("class keymods(IntEnum):")
28
+ for k, v in vars(pygame.locals).items():
29
+ if k.startswith('KMOD_'):
30
+ srclines.append(" %s = %d" % (k[5:].upper(), v))
31
+
32
+ exec('\n'.join(srclines), globals())
33
+ del srclines
pgzero/data/icon.png ADDED
Binary file
pgzero/data/joypad.png ADDED
Binary file