pyscratch-pysc 1.0.3__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.
- assets/bullet_hell/enemy.py +130 -0
- assets/bullet_hell/enemy_bullets.py +230 -0
- assets/bullet_hell/main.py +11 -0
- assets/bullet_hell/old_verisons/bullet_hell.py +379 -0
- assets/bullet_hell/old_verisons/enemy.py +226 -0
- assets/bullet_hell/old_verisons/game_start.py +6 -0
- assets/bullet_hell/old_verisons/main.py +50 -0
- assets/bullet_hell/old_verisons/player.py +76 -0
- assets/bullet_hell/player.py +89 -0
- assets/bullet_hell/player_bullets.py +34 -0
- assets/bullet_hell/setting.py +33 -0
- examples/animated_sprite/main.py +7 -0
- examples/animated_sprite/my_sprite.py +79 -0
- examples/bullet_hell/enemy.py +152 -0
- examples/bullet_hell/enemy_bullet.py +88 -0
- examples/bullet_hell/main.py +17 -0
- examples/bullet_hell/player.py +39 -0
- examples/bullet_hell/player_bullet.py +31 -0
- examples/doodle_jump/main.py +9 -0
- examples/doodle_jump/platforms.py +51 -0
- examples/doodle_jump/player.py +52 -0
- examples/fish/assets/bullet_hell/enemy.py +130 -0
- examples/fish/assets/bullet_hell/enemy_bullets.py +230 -0
- examples/fish/assets/bullet_hell/main.py +11 -0
- examples/fish/assets/bullet_hell/old_verisons/bullet_hell.py +379 -0
- examples/fish/assets/bullet_hell/old_verisons/enemy.py +226 -0
- examples/fish/assets/bullet_hell/old_verisons/game_start.py +6 -0
- examples/fish/assets/bullet_hell/old_verisons/main.py +50 -0
- examples/fish/assets/bullet_hell/old_verisons/player.py +76 -0
- examples/fish/assets/bullet_hell/player.py +89 -0
- examples/fish/assets/bullet_hell/player_bullets.py +34 -0
- examples/fish/assets/bullet_hell/setting.py +33 -0
- examples/fish/fish.py +67 -0
- examples/fish/main.py +4 -0
- examples/getting-started/step 1 - create a sprite/main.py +11 -0
- examples/getting-started/step 1 - create a sprite/player.py +5 -0
- examples/getting-started/step 2 - control a sprite/main.py +11 -0
- examples/getting-started/step 2 - control a sprite/player.py +42 -0
- examples/getting-started/step 3 - backdrops/main.py +17 -0
- examples/getting-started/step 3 - backdrops/player.py +33 -0
- examples/getting-started/step 4 - clone a sprite/enemy.py +53 -0
- examples/getting-started/step 4 - clone a sprite/main.py +17 -0
- examples/getting-started/step 4 - clone a sprite/player.py +32 -0
- examples/getting-started/step 4 - clone a sprite (simple)/enemy.py +42 -0
- examples/getting-started/step 4 - clone a sprite (simple)/main.py +17 -0
- examples/getting-started/step 4 - clone a sprite (simple)/player.py +32 -0
- examples/getting-started/step 5 - local variables/enemy.py +52 -0
- examples/getting-started/step 5 - local variables/main.py +17 -0
- examples/getting-started/step 5 - local variables/player.py +49 -0
- examples/getting-started/step 6 - shared variables/enemy.py +64 -0
- examples/getting-started/step 6 - shared variables/main.py +17 -0
- examples/getting-started/step 6 - shared variables/player.py +80 -0
- examples/getting-started/step 7 - Referencing other sprites/enemy.py +83 -0
- examples/getting-started/step 7 - Referencing other sprites/hearts.py +39 -0
- examples/getting-started/step 7 - Referencing other sprites/main.py +23 -0
- examples/getting-started/step 7 - Referencing other sprites/player.py +59 -0
- examples/getting-started/step 8 - sprite variables/enemy.py +98 -0
- examples/getting-started/step 8 - sprite variables/hearts.py +39 -0
- examples/getting-started/step 8 - sprite variables/main.py +22 -0
- examples/getting-started/step 8 - sprite variables/player.py +63 -0
- examples/getting-started/step 9 - messages/enemy.py +98 -0
- examples/getting-started/step 9 - messages/hearts.py +39 -0
- examples/getting-started/step 9 - messages/main.py +23 -0
- examples/getting-started/step 9 - messages/player.py +78 -0
- examples/perspective_background/main.py +14 -0
- examples/perspective_background/player.py +52 -0
- examples/perspective_background/trees.py +39 -0
- examples/simple_pong/ball.py +72 -0
- examples/simple_pong/left_paddle.py +36 -0
- examples/simple_pong/main.py +21 -0
- examples/simple_pong/right_paddle.py +37 -0
- examples/simple_pong/score_display.py +54 -0
- pyscratch/__init__.py +48 -0
- pyscratch/event.py +263 -0
- pyscratch/game_module.py +1589 -0
- pyscratch/helper.py +561 -0
- pyscratch/sprite.py +1920 -0
- pyscratch/tools/sprite_preview/left_panel/frame_preview_card.py +238 -0
- pyscratch/tools/sprite_preview/left_panel/frame_preview_panel.py +42 -0
- pyscratch/tools/sprite_preview/main.py +18 -0
- pyscratch/tools/sprite_preview/main_panel/animation_display.py +77 -0
- pyscratch/tools/sprite_preview/main_panel/frame_bin.py +33 -0
- pyscratch/tools/sprite_preview/main_panel/play_edit_ui.py +64 -0
- pyscratch/tools/sprite_preview/main_panel/set_as_sprite_folder.py +22 -0
- pyscratch/tools/sprite_preview/main_panel/sprite_edit_ui.py +174 -0
- pyscratch/tools/sprite_preview/main_panel/warning_message.py +25 -0
- pyscratch/tools/sprite_preview/right_panel/back_button.py +35 -0
- pyscratch/tools/sprite_preview/right_panel/cut_button.py +32 -0
- pyscratch/tools/sprite_preview/right_panel/cut_parameter_fitting.py +152 -0
- pyscratch/tools/sprite_preview/right_panel/cut_parameters.py +42 -0
- pyscratch/tools/sprite_preview/right_panel/file_display.py +84 -0
- pyscratch/tools/sprite_preview/right_panel/file_display_area.py +57 -0
- pyscratch/tools/sprite_preview/right_panel/spritesheet_view.py +262 -0
- pyscratch/tools/sprite_preview/right_panel/ss_select_corner.py +208 -0
- pyscratch/tools/sprite_preview/settings.py +14 -0
- pyscratch/tools/sprite_preview/utils/input_box.py +235 -0
- pyscratch/tools/sprite_preview/utils/render_wrapped_file_name.py +86 -0
- pyscratch_pysc-1.0.3.dist-info/METADATA +37 -0
- pyscratch_pysc-1.0.3.dist-info/RECORD +101 -0
- pyscratch_pysc-1.0.3.dist-info/WHEEL +5 -0
- pyscratch_pysc-1.0.3.dist-info/top_level.txt +3 -0
pyscratch/event.py
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
"""
|
2
|
+
Everything in this module is directly under the pyscratch namespace.
|
3
|
+
For example, instead of doing `pysc.event.Timer`,
|
4
|
+
you can also directly do `pysc.Timer`.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from __future__ import annotations
|
8
|
+
from typing import Any, Callable, Dict, Generator, Generic, List, ParamSpec, Set, Tuple, TypeVar, Union, override
|
9
|
+
from types import GeneratorType, NoneType
|
10
|
+
|
11
|
+
import pygame
|
12
|
+
import pymunk
|
13
|
+
import numpy as np
|
14
|
+
|
15
|
+
P = ParamSpec('P')
|
16
|
+
"""@private"""
|
17
|
+
T = TypeVar('T')
|
18
|
+
"""@private"""
|
19
|
+
|
20
|
+
|
21
|
+
def _declare_callback_type(obj: Event, func: Callable[P, Union[NoneType, Generator[float, None, None]]]) -> Event[P]:
|
22
|
+
return obj
|
23
|
+
|
24
|
+
|
25
|
+
class Event(Generic[P]):
|
26
|
+
"""
|
27
|
+
A low level Event class.
|
28
|
+
You **do not** need to create the Event object yourself.
|
29
|
+
They are instead returned by functions like `sprite.when_game_started()`
|
30
|
+
|
31
|
+
In no circumstances will you need to create your custom event. Always use the message event instead.
|
32
|
+
"""
|
33
|
+
|
34
|
+
def __init__(self):
|
35
|
+
"""@private"""
|
36
|
+
|
37
|
+
self.__triggers: List = []
|
38
|
+
self.__callbacks: List[Callable[P, Union[NoneType, Generator[float, None, None]]]] = []
|
39
|
+
self.__stay_active = True
|
40
|
+
self.__to_soft_remove = False
|
41
|
+
self.__generators: Dict[GeneratorType, float] = {}
|
42
|
+
|
43
|
+
|
44
|
+
#def add_handler(self, func: Callable[P, Union[NoneType, Generator[float, None, None]]]):
|
45
|
+
# use Any for the simplicity in the doc
|
46
|
+
def add_handler(self, func: Callable[P, Any]):
|
47
|
+
"""
|
48
|
+
Add a handler function to this event.
|
49
|
+
When the event is triggered, the handler functions are called, taking in the parameters passed on by the triggers.
|
50
|
+
"""
|
51
|
+
self.__callbacks.append(func)
|
52
|
+
return self
|
53
|
+
|
54
|
+
|
55
|
+
def remove(self):
|
56
|
+
"""Schedule this event to be removed."""
|
57
|
+
self.__stay_active = False
|
58
|
+
|
59
|
+
def soft_remove(self):
|
60
|
+
"""Schedule this event to be removed when all the generators (yield functions) finish"""
|
61
|
+
self.__to_soft_remove = True
|
62
|
+
|
63
|
+
@property
|
64
|
+
def stay_active(self) -> bool:
|
65
|
+
"""Shows whether this event is removed or scheduled to be removed."""
|
66
|
+
return self.__stay_active
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
def trigger(self, *args: P.args, **kwargs: P.kwargs):
|
71
|
+
"""
|
72
|
+
@private
|
73
|
+
Trigger the event. The parameters will be passed on to the event handlers.
|
74
|
+
|
75
|
+
You will not need to run this method ever.
|
76
|
+
"""
|
77
|
+
self.__triggers.append((args, kwargs))
|
78
|
+
|
79
|
+
def _handle_all(self, current_t_ms):
|
80
|
+
while self._handle_one(current_t_ms):
|
81
|
+
pass
|
82
|
+
|
83
|
+
def _handle_one(self, current_t_ms):
|
84
|
+
|
85
|
+
if not len(self.__triggers):
|
86
|
+
return False
|
87
|
+
|
88
|
+
args, kwargs = self.__triggers.pop(0)
|
89
|
+
|
90
|
+
for cb in self.__callbacks:
|
91
|
+
ret = cb(*args, **kwargs) # type: ignore
|
92
|
+
if isinstance(ret, GeneratorType):
|
93
|
+
|
94
|
+
# just to schedule to run immediately
|
95
|
+
# actually run when self.generators_proceed is called
|
96
|
+
self.__generators[ret] = current_t_ms
|
97
|
+
|
98
|
+
return True
|
99
|
+
|
100
|
+
def _generators_proceed(self, current_t_ms):
|
101
|
+
to_remove = []
|
102
|
+
|
103
|
+
for g, t in self.__generators.items():
|
104
|
+
next_t = t
|
105
|
+
while next_t<=current_t_ms:
|
106
|
+
try:
|
107
|
+
next_t = next_t+next(g)*1000
|
108
|
+
self.__generators[g] = next_t
|
109
|
+
except StopIteration:
|
110
|
+
next_t = np.inf
|
111
|
+
to_remove.append(g)
|
112
|
+
|
113
|
+
self.__generators = {g:t for g, t in self.__generators.items() if not g in to_remove}
|
114
|
+
if not len(self.__generators) and self.__to_soft_remove:
|
115
|
+
self.remove()
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
class _ConditionInterface:
|
121
|
+
"""
|
122
|
+
A low level Condition class.
|
123
|
+
You **do not** need to create the Condition object yourself.
|
124
|
+
"""
|
125
|
+
def _check(self):
|
126
|
+
pass
|
127
|
+
|
128
|
+
def add_handler(self, callback: Callable[[int], Any]):
|
129
|
+
"""
|
130
|
+
Add a handler function to this event.
|
131
|
+
When the event is triggered, the handler functions are called, taking in the parameters passed on by the triggers.
|
132
|
+
"""
|
133
|
+
return self
|
134
|
+
|
135
|
+
def remove(self):
|
136
|
+
"""Schedule this event to be removed."""
|
137
|
+
pass
|
138
|
+
|
139
|
+
def soft_remove(self):
|
140
|
+
"""Schedule this event to be removed when all the generators (yield functions) finish"""
|
141
|
+
pass
|
142
|
+
|
143
|
+
@property
|
144
|
+
def stay_active(self) -> bool:
|
145
|
+
"""Shows whether this event is removed or scheduled to be removed."""
|
146
|
+
return True
|
147
|
+
|
148
|
+
class Condition(_ConditionInterface):
|
149
|
+
def __init__(self, checker: Callable[[], bool] = lambda: False, repeats: Union[float, int]=1):
|
150
|
+
"""@private"""
|
151
|
+
self.trigger = Event()
|
152
|
+
self.repeat_remains = repeats
|
153
|
+
self.checker = checker
|
154
|
+
self.__stay_active = True
|
155
|
+
|
156
|
+
def add_handler(self, callback: Callable[[int], Any]):
|
157
|
+
self.trigger.add_handler(callback)
|
158
|
+
return self
|
159
|
+
|
160
|
+
def remove(self):
|
161
|
+
self.__stay_active = False
|
162
|
+
self.trigger.remove()
|
163
|
+
|
164
|
+
def soft_remove(self):
|
165
|
+
self.__stay_active = False
|
166
|
+
self.trigger.soft_remove()
|
167
|
+
|
168
|
+
@property
|
169
|
+
def stay_active(self):
|
170
|
+
return self.__stay_active
|
171
|
+
|
172
|
+
def _check(self):
|
173
|
+
if self.checker() and self.repeat_remains:
|
174
|
+
self.repeat_remains -= 1
|
175
|
+
self.trigger.trigger(self.repeat_remains)
|
176
|
+
|
177
|
+
if not self.repeat_remains:
|
178
|
+
self.soft_remove()
|
179
|
+
|
180
|
+
def change_checker(self, checker= lambda: False):
|
181
|
+
"""@private"""
|
182
|
+
self.checker = checker
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
class TimerCondition(_ConditionInterface):
|
187
|
+
def __init__(self, reset_period=np.inf, repeats=np.inf):
|
188
|
+
"""
|
189
|
+
@private
|
190
|
+
"""
|
191
|
+
self.trigger = Event()
|
192
|
+
self.repeat_remains = repeats
|
193
|
+
self.timer = Timer(reset_period=reset_period)
|
194
|
+
self.period = 0
|
195
|
+
self.__stay_active = True
|
196
|
+
|
197
|
+
def add_handler(self, callback: Callable[[int], Any]):
|
198
|
+
self.trigger.add_handler(callback)
|
199
|
+
return self
|
200
|
+
|
201
|
+
def remove(self):
|
202
|
+
self.__stay_active = False
|
203
|
+
self.trigger.remove()
|
204
|
+
|
205
|
+
def soft_remove(self):
|
206
|
+
self.__stay_active = False
|
207
|
+
self.trigger.soft_remove()
|
208
|
+
|
209
|
+
@property
|
210
|
+
def stay_active(self):
|
211
|
+
return self.__stay_active
|
212
|
+
|
213
|
+
def _check(self):
|
214
|
+
self.timer.read()
|
215
|
+
while (self.timer.n_period > self.period) and self.repeat_remains:
|
216
|
+
self.period += 1
|
217
|
+
self.repeat_remains -= 1
|
218
|
+
self.trigger.trigger(self.repeat_remains)
|
219
|
+
|
220
|
+
if not self.repeat_remains:
|
221
|
+
self.soft_remove()
|
222
|
+
|
223
|
+
|
224
|
+
|
225
|
+
class Timer:
|
226
|
+
"""
|
227
|
+
Create a timer that resets every `reset_period` seconds.
|
228
|
+
"""
|
229
|
+
def __init__(self, reset_period=np.inf):
|
230
|
+
"""
|
231
|
+
Parameters
|
232
|
+
---
|
233
|
+
reset_period: float
|
234
|
+
The reset period. Pass in np.inf for no reset
|
235
|
+
"""
|
236
|
+
self._t0 = pygame.time.get_ticks()/1000
|
237
|
+
self.reset_period = reset_period
|
238
|
+
self.n_period = 0
|
239
|
+
"""How many times the `reset_period` have passed"""
|
240
|
+
|
241
|
+
def read(self):
|
242
|
+
"""
|
243
|
+
Read the timer.
|
244
|
+
"""
|
245
|
+
dt = pygame.time.get_ticks()/1000 - self._t0
|
246
|
+
self.n_period = int(dt // self.reset_period)
|
247
|
+
return dt % self.reset_period
|
248
|
+
|
249
|
+
def full_reset(self):
|
250
|
+
"""
|
251
|
+
Reset the timer and the `n_period`.
|
252
|
+
"""
|
253
|
+
self.n_period = 0
|
254
|
+
self._t0 = pygame.time.get_ticks()/1000
|
255
|
+
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
|
263
|
+
|