pyscrh 0.1.0__tar.gz

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.
pyscrh-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 魔丸编程
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pyscrh-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyscrh
3
+ Version: 0.1.0
4
+ Summary: A tiny Scratch-style sprite library built on pygame, for people moving from Scratch to Python.
5
+ Author-email: 魔丸编程 <17516332069@163.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 魔丸编程
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/CutePandaXJK/pyscrh
29
+ Project-URL: Repository, https://github.com/CutePandaXJK/pyscrh
30
+ Keywords: scratch,pygame,game,sprite,education,beginner
31
+ Classifier: Programming Language :: Python :: 3
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Operating System :: OS Independent
34
+ Classifier: Topic :: Games/Entertainment
35
+ Classifier: Topic :: Education
36
+ Classifier: Intended Audience :: Education
37
+ Requires-Python: >=3.8
38
+ Description-Content-Type: text/markdown
39
+ License-File: LICENSE
40
+ Requires-Dist: pygame>=2.0
41
+ Dynamic: license-file
42
+
43
+ # pyscrh
44
+
45
+ A tiny, **Scratch-style** sprite library built on [pygame](https://www.pygame.org/),
46
+ made for people moving from Scratch to Python.
47
+
48
+ Every Scratch block you know has a short Python equivalent — no game loop,
49
+ no event handling, no surface juggling to remember.
50
+
51
+ ## Install
52
+
53
+ ```bash
54
+ pip install pyscrh
55
+ ```
56
+
57
+ (Requires Python 3.8+ and pygame, which is installed automatically.)
58
+
59
+ ## Quick start
60
+
61
+ ```python
62
+ import pyscrh
63
+
64
+ apple = Sprite("apple.png") # load an image (PNG with transparency)
65
+ apple.turnway = "lr" # flip left-right when bouncing
66
+
67
+ def forever():
68
+ apple.move(5) # walk 5 steps in the current direction
69
+ apple.edgeb() # bounce off the screen edge
70
+ # stop_all() # call this anywhere to quit the game
71
+
72
+ clickGF() # start the game
73
+ ```
74
+
75
+ Just `import pyscrh` and you're done — `Sprite`, `clickGF`, `stop_all`,
76
+ `WIDTH` and `HEIGHT` are available directly, just like `import pgzrun`.
77
+
78
+ That's it. The apple walks right, bounces off the right edge, walks left,
79
+ bounces off the left edge, and repeats.
80
+
81
+ ## Scratch → Python cheat sheet
82
+
83
+ | Scratch block | pyscrh |
84
+ | --- | --- |
85
+ | move 10 steps | `sprite.move(10)` |
86
+ | turn 15° clockwise | `sprite.turnright(15)` |
87
+ | turn 15° counter-clockwise | `sprite.turnleft(15)` |
88
+ | go to x: y: | `sprite.gotoxy(x, y)` |
89
+ | go to random position | `sprite.goto("r")` |
90
+ | glide 1 sec to x: y: | `sprite.glidexy(1, x, y)` |
91
+ | point in direction 90 | `sprite.point(90)` |
92
+ | point towards mouse | `sprite.pointtow("m")` |
93
+ | if on edge, bounce | `sprite.edgeb()` |
94
+
95
+ ## How it works
96
+
97
+ You only write one required function:
98
+
99
+ - `forever()` — called once every frame, like Scratch's *forever* block.
100
+ Put `sprite.move(...)`, `edgeb()`, etc. in here. No `dt` parameter
101
+ needed; the library handles timing.
102
+
103
+ An optional `draw()` is also called every frame, *after* all sprites are
104
+ drawn, if you want extra drawing (text, backgrounds, etc.).
105
+
106
+ Call `clickGF()` to start, and `stop_all()` to close the window and quit.
107
+ pyscrh handles the window, clock, event loop and rendering for you.
108
+
109
+ ## API reference
110
+
111
+ ### `Sprite(image_path, name="")`
112
+
113
+ Create a sprite from an image file.
114
+
115
+ | Method | Description |
116
+ | --- | --- |
117
+ | `move(steps)` | Walk `steps` pixels in the current direction. |
118
+ | `turnright(deg)` / `turnleft(deg)` | Rotate by `deg` degrees. |
119
+ | `gotoxy(x, y)` | Jump to `(x, y)`. |
120
+ | `goto("r")` / `goto("m")` | Jump to a random spot / the mouse. |
121
+ | `glidexy(sec, x, y)` | Glide to `(x, y)` over `sec` seconds. |
122
+ | `glideto(sec, "r")` / `glideto(sec, "m")` | Glide to a spot / the mouse. |
123
+ | `point(deg)` | Set direction to `deg` degrees. |
124
+ | `pointtow("r")` / `pointtow("m")` | Face a random direction / the mouse. |
125
+ | `edgeb()` | Bounce off the screen edge. |
126
+
127
+ | Attribute | Description |
128
+ | --- | --- |
129
+ | `x`, `y` | Center position (read or write). |
130
+ | `angle` | Direction in degrees (0 = right, 90 = down). |
131
+ | `turnway` | `"r"` rotate-bounce, `"lr"` flip-bounce, `"n"` no bounce. |
132
+
133
+ ## License
134
+
135
+ MIT
pyscrh-0.1.0/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # pyscrh
2
+
3
+ A tiny, **Scratch-style** sprite library built on [pygame](https://www.pygame.org/),
4
+ made for people moving from Scratch to Python.
5
+
6
+ Every Scratch block you know has a short Python equivalent — no game loop,
7
+ no event handling, no surface juggling to remember.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pip install pyscrh
13
+ ```
14
+
15
+ (Requires Python 3.8+ and pygame, which is installed automatically.)
16
+
17
+ ## Quick start
18
+
19
+ ```python
20
+ import pyscrh
21
+
22
+ apple = Sprite("apple.png") # load an image (PNG with transparency)
23
+ apple.turnway = "lr" # flip left-right when bouncing
24
+
25
+ def forever():
26
+ apple.move(5) # walk 5 steps in the current direction
27
+ apple.edgeb() # bounce off the screen edge
28
+ # stop_all() # call this anywhere to quit the game
29
+
30
+ clickGF() # start the game
31
+ ```
32
+
33
+ Just `import pyscrh` and you're done — `Sprite`, `clickGF`, `stop_all`,
34
+ `WIDTH` and `HEIGHT` are available directly, just like `import pgzrun`.
35
+
36
+ That's it. The apple walks right, bounces off the right edge, walks left,
37
+ bounces off the left edge, and repeats.
38
+
39
+ ## Scratch → Python cheat sheet
40
+
41
+ | Scratch block | pyscrh |
42
+ | --- | --- |
43
+ | move 10 steps | `sprite.move(10)` |
44
+ | turn 15° clockwise | `sprite.turnright(15)` |
45
+ | turn 15° counter-clockwise | `sprite.turnleft(15)` |
46
+ | go to x: y: | `sprite.gotoxy(x, y)` |
47
+ | go to random position | `sprite.goto("r")` |
48
+ | glide 1 sec to x: y: | `sprite.glidexy(1, x, y)` |
49
+ | point in direction 90 | `sprite.point(90)` |
50
+ | point towards mouse | `sprite.pointtow("m")` |
51
+ | if on edge, bounce | `sprite.edgeb()` |
52
+
53
+ ## How it works
54
+
55
+ You only write one required function:
56
+
57
+ - `forever()` — called once every frame, like Scratch's *forever* block.
58
+ Put `sprite.move(...)`, `edgeb()`, etc. in here. No `dt` parameter
59
+ needed; the library handles timing.
60
+
61
+ An optional `draw()` is also called every frame, *after* all sprites are
62
+ drawn, if you want extra drawing (text, backgrounds, etc.).
63
+
64
+ Call `clickGF()` to start, and `stop_all()` to close the window and quit.
65
+ pyscrh handles the window, clock, event loop and rendering for you.
66
+
67
+ ## API reference
68
+
69
+ ### `Sprite(image_path, name="")`
70
+
71
+ Create a sprite from an image file.
72
+
73
+ | Method | Description |
74
+ | --- | --- |
75
+ | `move(steps)` | Walk `steps` pixels in the current direction. |
76
+ | `turnright(deg)` / `turnleft(deg)` | Rotate by `deg` degrees. |
77
+ | `gotoxy(x, y)` | Jump to `(x, y)`. |
78
+ | `goto("r")` / `goto("m")` | Jump to a random spot / the mouse. |
79
+ | `glidexy(sec, x, y)` | Glide to `(x, y)` over `sec` seconds. |
80
+ | `glideto(sec, "r")` / `glideto(sec, "m")` | Glide to a spot / the mouse. |
81
+ | `point(deg)` | Set direction to `deg` degrees. |
82
+ | `pointtow("r")` / `pointtow("m")` | Face a random direction / the mouse. |
83
+ | `edgeb()` | Bounce off the screen edge. |
84
+
85
+ | Attribute | Description |
86
+ | --- | --- |
87
+ | `x`, `y` | Center position (read or write). |
88
+ | `angle` | Direction in degrees (0 = right, 90 = down). |
89
+ | `turnway` | `"r"` rotate-bounce, `"lr"` flip-bounce, `"n"` no bounce. |
90
+
91
+ ## License
92
+
93
+ MIT
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyscrh"
7
+ version = "0.1.0"
8
+ description = "A tiny Scratch-style sprite library built on pygame, for people moving from Scratch to Python."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { file = "LICENSE" }
12
+ authors = [
13
+ { name = "魔丸编程", email = "17516332069@163.com" }
14
+ ]
15
+ keywords = ["scratch", "pygame", "game", "sprite", "education", "beginner"]
16
+ classifiers = [
17
+ "Programming Language :: Python :: 3",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Topic :: Games/Entertainment",
21
+ "Topic :: Education",
22
+ "Intended Audience :: Education",
23
+ ]
24
+ dependencies = [
25
+ "pygame>=2.0"
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/CutePandaXJK/pyscrh"
30
+ Repository = "https://github.com/CutePandaXJK/pyscrh"
@@ -0,0 +1,322 @@
1
+ """
2
+ pyscrh
3
+ ======
4
+
5
+ A tiny, **Scratch-style** sprite library built on top of pygame, made for
6
+ people moving from Scratch to Python.
7
+
8
+ Every Scratch block you know has a short Python equivalent::
9
+
10
+ from pyscrh import Sprite, clickGF
11
+
12
+ apple = Sprite("apple.png")
13
+ apple.turnway = "lr"
14
+
15
+ def forever():
16
+ apple.move(5) # move 5 steps in the current direction
17
+ apple.edgeb() # bounce off the edge
18
+
19
+ clickGF() # start the game
20
+
21
+ The public API is intentionally small: create a :class:`Sprite`, put what
22
+ should repeat forever in a ``forever()`` function, and call :func:`clickGF`
23
+ to start. You never need to touch ``dt`` or the game loop. Call
24
+ :func:`stop_all` at any point to close the window and quit.
25
+ """
26
+
27
+ import pygame
28
+ import math
29
+ import random
30
+ import inspect
31
+ import sys
32
+
33
+ __version__ = "0.1.0"
34
+
35
+ # --- pygame / window setup (runs on first import) -----------------------
36
+ pygame.init()
37
+
38
+ WIDTH = 960
39
+ HEIGHT = 720
40
+ _screen = pygame.display.set_mode((WIDTH, HEIGHT))
41
+ pygame.display.set_caption("pyscrh")
42
+ _clock = pygame.time.Clock()
43
+
44
+ # All live sprites. Internal; users never touch this.
45
+ _sprites = []
46
+
47
+
48
+ class Sprite:
49
+ """A single game character, loaded from an image file.
50
+
51
+ Parameters
52
+ ----------
53
+ image_path : str
54
+ Full path to the sprite image (PNG with transparency works best).
55
+ name : str, optional
56
+ A friendly name. Not required, but handy when you have many sprites.
57
+
58
+ Attributes
59
+ ----------
60
+ x, y : float
61
+ Center position of the sprite (read or write directly).
62
+ angle : float
63
+ Direction in degrees: ``0`` points right, ``90`` points down.
64
+ turnway : str
65
+ How the sprite behaves at the screen edge:
66
+ ``"r"`` rotates to bounce, ``"lr"`` flips left-right,
67
+ ``"n"`` does not bounce at all.
68
+ """
69
+
70
+ def __init__(self, image_path, name=""):
71
+ self.original = pygame.image.load(image_path).convert_alpha()
72
+ self.width = self.original.get_width()
73
+ self.height = self.original.get_height()
74
+
75
+ # Center position
76
+ self.x = self.width / 2
77
+ self.y = self.height / 2
78
+
79
+ # Movement state
80
+ self.angle = 0
81
+ self.direction_x = 1 # flipped by edgeb on left/right hits
82
+ self.direction_y = 1 # flipped by edgeb on top/bottom hits
83
+ self.flip_x = False # visual horizontal flip
84
+ self.flip_y = False # visual vertical flip
85
+ self.turnway = "r"
86
+ self.name = name
87
+
88
+ # Gliding state (internal, driven by glidexy / glideto)
89
+ self.glide_target_x = 0
90
+ self.glide_target_y = 0
91
+ self.glide_delta_x = 0
92
+ self.glide_delta_y = 0
93
+ self.glide_distance = 0.0
94
+ self.glide_speed = 0.0
95
+ self.gliding = False
96
+
97
+ _sprites.append(self)
98
+
99
+ # ------------------------------------------------------------------
100
+ # Movement
101
+ # ------------------------------------------------------------------
102
+ def move(self, steps):
103
+ """Walk ``steps`` pixels in the current direction.
104
+
105
+ Call this once per frame inside your ``update(dt)`` and the sprite
106
+ keeps walking. Equivalent to Scratch's *move 10 steps*.
107
+ """
108
+ rad = math.radians(self.angle)
109
+ self.x += self.direction_x * steps * math.cos(rad)
110
+ self.y += self.direction_y * steps * math.sin(rad)
111
+
112
+ def turnright(self, degrees):
113
+ """Turn right by ``degrees``."""
114
+ self.angle += degrees
115
+
116
+ def turnleft(self, degrees):
117
+ """Turn left by ``degrees``."""
118
+ self.angle -= degrees
119
+
120
+ def gotoxy(self, x, y):
121
+ """Jump instantly to position ``(x, y)``."""
122
+ self.x = x
123
+ self.y = y
124
+
125
+ def goto(self, target):
126
+ """Jump instantly to a target.
127
+
128
+ Parameters
129
+ ----------
130
+ target : str
131
+ ``"r"`` for a random spot, ``"m"`` for the mouse position.
132
+ """
133
+ if target == "r":
134
+ self.gotoxy(random.randint(0, WIDTH), random.randint(0, HEIGHT))
135
+ elif target == "m":
136
+ self.gotoxy(*pygame.mouse.get_pos())
137
+
138
+ # ------------------------------------------------------------------
139
+ # Gliding
140
+ # ------------------------------------------------------------------
141
+ def glidexy(self, seconds, x, y):
142
+ """Glide smoothly to ``(x, y)`` over ``seconds`` seconds."""
143
+ if seconds <= 0:
144
+ return
145
+ distance = math.hypot(x - self.x, y - self.y)
146
+ if distance < 1e-9:
147
+ self.gliding = False
148
+ return
149
+ self.glide_target_x = x
150
+ self.glide_target_y = y
151
+ self.glide_delta_x = x - self.x
152
+ self.glide_delta_y = y - self.y
153
+ self.glide_distance = distance
154
+ self.glide_speed = distance / seconds
155
+ self.gliding = True
156
+
157
+ def glideto(self, seconds, target):
158
+ """Glide smoothly over ``seconds`` seconds.
159
+
160
+ Parameters
161
+ ----------
162
+ seconds : float
163
+ How long the glide takes.
164
+ target : str
165
+ ``"r"`` for a random spot, ``"m"`` for the mouse position.
166
+ """
167
+ if target == "r":
168
+ self.glidexy(seconds,
169
+ random.randint(0, WIDTH),
170
+ random.randint(0, HEIGHT))
171
+ elif target == "m":
172
+ self.glidexy(seconds, *pygame.mouse.get_pos())
173
+
174
+ # ------------------------------------------------------------------
175
+ # Direction
176
+ # ------------------------------------------------------------------
177
+ def point(self, degrees):
178
+ """Set the direction to ``degrees`` (0 = right, 90 = down)."""
179
+ self.angle = degrees
180
+
181
+ def pointtow(self, target):
182
+ """Point towards something.
183
+
184
+ Parameters
185
+ ----------
186
+ target : str
187
+ ``"r"`` for a random direction, ``"m"`` to face the mouse.
188
+ """
189
+ if target == "r":
190
+ self.angle = random.randint(0, 360)
191
+ elif target == "m":
192
+ mouse_x, mouse_y = pygame.mouse.get_pos()
193
+ self.angle = math.degrees(math.atan2(
194
+ mouse_y - self.y, mouse_x - self.x))
195
+
196
+ # ------------------------------------------------------------------
197
+ # Edge bouncing
198
+ # ------------------------------------------------------------------
199
+ def edgeb(self):
200
+ """Bounce off the screen edge.
201
+
202
+ Equivalent to Scratch's *if on edge, bounce*. The horizontal /
203
+ vertical direction flips independently, and the sprite is visually
204
+ flipped according to :attr:`turnway`.
205
+ """
206
+ left = self.x - self.width / 2
207
+ right = self.x + self.width / 2
208
+ top = self.y - self.height / 2
209
+ bottom = self.y + self.height / 2
210
+
211
+ if self.turnway == "n":
212
+ return
213
+
214
+ if right > WIDTH:
215
+ self.x = WIDTH - self.width / 2
216
+ self.direction_x = -self.direction_x
217
+ self.flip_x = not self.flip_x
218
+ elif left < 0:
219
+ self.x = self.width / 2
220
+ self.direction_x = -self.direction_x
221
+ self.flip_x = not self.flip_x
222
+
223
+ if bottom > HEIGHT:
224
+ self.y = HEIGHT - self.height / 2
225
+ self.direction_y = -self.direction_y
226
+ if self.turnway == "r":
227
+ self.flip_y = not self.flip_y
228
+ elif top < 0:
229
+ self.y = self.height / 2
230
+ self.direction_y = -self.direction_y
231
+ if self.turnway == "r":
232
+ self.flip_y = not self.flip_y
233
+
234
+ # ------------------------------------------------------------------
235
+ # Internal per-frame hooks (called by clickGF, not by you)
236
+ # ------------------------------------------------------------------
237
+ def _update(self, dt):
238
+ """Advance an in-progress glide. Regular movement is done by move()."""
239
+ if not self.gliding:
240
+ return
241
+ remaining = math.hypot(self.glide_target_x - self.x,
242
+ self.glide_target_y - self.y)
243
+ step = self.glide_speed * dt
244
+ if remaining <= step:
245
+ self.x = self.glide_target_x
246
+ self.y = self.glide_target_y
247
+ self.gliding = False
248
+ else:
249
+ self.x += self.glide_delta_x / self.glide_distance * step
250
+ self.y += self.glide_delta_y / self.glide_distance * step
251
+
252
+ def _draw(self, surface):
253
+ """Render this sprite onto ``surface``."""
254
+ image = self.original
255
+ if self.turnway == "r":
256
+ image = pygame.transform.rotate(image, self.angle)
257
+ if self.flip_x:
258
+ image = pygame.transform.flip(image, True, False)
259
+ if self.flip_y:
260
+ image = pygame.transform.flip(image, False, True)
261
+ rect = image.get_rect(center=(self.x, self.y))
262
+ surface.blit(image, rect)
263
+
264
+
265
+ def clickGF():
266
+ """Start the game loop.
267
+
268
+ It automatically looks up ``forever()`` in the module that called it and
269
+ calls it once every frame, like Scratch's *forever* block. You don't
270
+ need to know about ``dt`` — the library handles timing internally.
271
+
272
+ An optional ``draw()`` is also called every frame, *after* all sprites
273
+ are drawn, if you want extra drawing. Close the window to quit, or call
274
+ :func:`stop_all` to quit from code.
275
+ """
276
+ frame = inspect.currentframe()
277
+ caller_globals = frame.f_back.f_globals
278
+ del frame
279
+ user_forever = caller_globals.get("forever")
280
+ user_draw = caller_globals.get("draw")
281
+
282
+ running = True
283
+ while running:
284
+ dt = _clock.tick(60) / 1000 # seconds since last frame (internal use)
285
+
286
+ for event in pygame.event.get():
287
+ if event.type == pygame.QUIT:
288
+ running = False
289
+
290
+ if user_forever is not None:
291
+ user_forever()
292
+ for sprite in _sprites:
293
+ sprite._update(dt)
294
+
295
+ _screen.fill((0, 0, 0))
296
+ for sprite in _sprites:
297
+ sprite._draw(_screen)
298
+ if user_draw is not None:
299
+ user_draw()
300
+ pygame.display.flip()
301
+
302
+ pygame.quit()
303
+
304
+
305
+ def stop_all():
306
+ """Close the window and stop the program.
307
+
308
+ Equivalent to Scratch's *stop all* block. Call it from anywhere, e.g.
309
+ inside ``forever()`` when your game logic says the program should end.
310
+ """
311
+ pygame.quit()
312
+ sys.exit()
313
+
314
+
315
+ # 魔法:让用户只写 "import pyscrh" 就能直接用 Sprite / clickGF / stop_all,
316
+ # 不用再写 "from pyscrh import *"(和 pgzrun 的体验一致)。
317
+ import __main__
318
+ __main__.Sprite = Sprite
319
+ __main__.clickGF = clickGF
320
+ __main__.stop_all = stop_all
321
+ __main__.WIDTH = WIDTH
322
+ __main__.HEIGHT = HEIGHT
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyscrh
3
+ Version: 0.1.0
4
+ Summary: A tiny Scratch-style sprite library built on pygame, for people moving from Scratch to Python.
5
+ Author-email: 魔丸编程 <17516332069@163.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 魔丸编程
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/CutePandaXJK/pyscrh
29
+ Project-URL: Repository, https://github.com/CutePandaXJK/pyscrh
30
+ Keywords: scratch,pygame,game,sprite,education,beginner
31
+ Classifier: Programming Language :: Python :: 3
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Operating System :: OS Independent
34
+ Classifier: Topic :: Games/Entertainment
35
+ Classifier: Topic :: Education
36
+ Classifier: Intended Audience :: Education
37
+ Requires-Python: >=3.8
38
+ Description-Content-Type: text/markdown
39
+ License-File: LICENSE
40
+ Requires-Dist: pygame>=2.0
41
+ Dynamic: license-file
42
+
43
+ # pyscrh
44
+
45
+ A tiny, **Scratch-style** sprite library built on [pygame](https://www.pygame.org/),
46
+ made for people moving from Scratch to Python.
47
+
48
+ Every Scratch block you know has a short Python equivalent — no game loop,
49
+ no event handling, no surface juggling to remember.
50
+
51
+ ## Install
52
+
53
+ ```bash
54
+ pip install pyscrh
55
+ ```
56
+
57
+ (Requires Python 3.8+ and pygame, which is installed automatically.)
58
+
59
+ ## Quick start
60
+
61
+ ```python
62
+ import pyscrh
63
+
64
+ apple = Sprite("apple.png") # load an image (PNG with transparency)
65
+ apple.turnway = "lr" # flip left-right when bouncing
66
+
67
+ def forever():
68
+ apple.move(5) # walk 5 steps in the current direction
69
+ apple.edgeb() # bounce off the screen edge
70
+ # stop_all() # call this anywhere to quit the game
71
+
72
+ clickGF() # start the game
73
+ ```
74
+
75
+ Just `import pyscrh` and you're done — `Sprite`, `clickGF`, `stop_all`,
76
+ `WIDTH` and `HEIGHT` are available directly, just like `import pgzrun`.
77
+
78
+ That's it. The apple walks right, bounces off the right edge, walks left,
79
+ bounces off the left edge, and repeats.
80
+
81
+ ## Scratch → Python cheat sheet
82
+
83
+ | Scratch block | pyscrh |
84
+ | --- | --- |
85
+ | move 10 steps | `sprite.move(10)` |
86
+ | turn 15° clockwise | `sprite.turnright(15)` |
87
+ | turn 15° counter-clockwise | `sprite.turnleft(15)` |
88
+ | go to x: y: | `sprite.gotoxy(x, y)` |
89
+ | go to random position | `sprite.goto("r")` |
90
+ | glide 1 sec to x: y: | `sprite.glidexy(1, x, y)` |
91
+ | point in direction 90 | `sprite.point(90)` |
92
+ | point towards mouse | `sprite.pointtow("m")` |
93
+ | if on edge, bounce | `sprite.edgeb()` |
94
+
95
+ ## How it works
96
+
97
+ You only write one required function:
98
+
99
+ - `forever()` — called once every frame, like Scratch's *forever* block.
100
+ Put `sprite.move(...)`, `edgeb()`, etc. in here. No `dt` parameter
101
+ needed; the library handles timing.
102
+
103
+ An optional `draw()` is also called every frame, *after* all sprites are
104
+ drawn, if you want extra drawing (text, backgrounds, etc.).
105
+
106
+ Call `clickGF()` to start, and `stop_all()` to close the window and quit.
107
+ pyscrh handles the window, clock, event loop and rendering for you.
108
+
109
+ ## API reference
110
+
111
+ ### `Sprite(image_path, name="")`
112
+
113
+ Create a sprite from an image file.
114
+
115
+ | Method | Description |
116
+ | --- | --- |
117
+ | `move(steps)` | Walk `steps` pixels in the current direction. |
118
+ | `turnright(deg)` / `turnleft(deg)` | Rotate by `deg` degrees. |
119
+ | `gotoxy(x, y)` | Jump to `(x, y)`. |
120
+ | `goto("r")` / `goto("m")` | Jump to a random spot / the mouse. |
121
+ | `glidexy(sec, x, y)` | Glide to `(x, y)` over `sec` seconds. |
122
+ | `glideto(sec, "r")` / `glideto(sec, "m")` | Glide to a spot / the mouse. |
123
+ | `point(deg)` | Set direction to `deg` degrees. |
124
+ | `pointtow("r")` / `pointtow("m")` | Face a random direction / the mouse. |
125
+ | `edgeb()` | Bounce off the screen edge. |
126
+
127
+ | Attribute | Description |
128
+ | --- | --- |
129
+ | `x`, `y` | Center position (read or write). |
130
+ | `angle` | Direction in degrees (0 = right, 90 = down). |
131
+ | `turnway` | `"r"` rotate-bounce, `"lr"` flip-bounce, `"n"` no bounce. |
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,9 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ pyscrh/__init__.py
5
+ pyscrh.egg-info/PKG-INFO
6
+ pyscrh.egg-info/SOURCES.txt
7
+ pyscrh.egg-info/dependency_links.txt
8
+ pyscrh.egg-info/requires.txt
9
+ pyscrh.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ pygame>=2.0
@@ -0,0 +1 @@
1
+ pyscrh
pyscrh-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+