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.
Files changed (101) hide show
  1. assets/bullet_hell/enemy.py +130 -0
  2. assets/bullet_hell/enemy_bullets.py +230 -0
  3. assets/bullet_hell/main.py +11 -0
  4. assets/bullet_hell/old_verisons/bullet_hell.py +379 -0
  5. assets/bullet_hell/old_verisons/enemy.py +226 -0
  6. assets/bullet_hell/old_verisons/game_start.py +6 -0
  7. assets/bullet_hell/old_verisons/main.py +50 -0
  8. assets/bullet_hell/old_verisons/player.py +76 -0
  9. assets/bullet_hell/player.py +89 -0
  10. assets/bullet_hell/player_bullets.py +34 -0
  11. assets/bullet_hell/setting.py +33 -0
  12. examples/animated_sprite/main.py +7 -0
  13. examples/animated_sprite/my_sprite.py +79 -0
  14. examples/bullet_hell/enemy.py +152 -0
  15. examples/bullet_hell/enemy_bullet.py +88 -0
  16. examples/bullet_hell/main.py +17 -0
  17. examples/bullet_hell/player.py +39 -0
  18. examples/bullet_hell/player_bullet.py +31 -0
  19. examples/doodle_jump/main.py +9 -0
  20. examples/doodle_jump/platforms.py +51 -0
  21. examples/doodle_jump/player.py +52 -0
  22. examples/fish/assets/bullet_hell/enemy.py +130 -0
  23. examples/fish/assets/bullet_hell/enemy_bullets.py +230 -0
  24. examples/fish/assets/bullet_hell/main.py +11 -0
  25. examples/fish/assets/bullet_hell/old_verisons/bullet_hell.py +379 -0
  26. examples/fish/assets/bullet_hell/old_verisons/enemy.py +226 -0
  27. examples/fish/assets/bullet_hell/old_verisons/game_start.py +6 -0
  28. examples/fish/assets/bullet_hell/old_verisons/main.py +50 -0
  29. examples/fish/assets/bullet_hell/old_verisons/player.py +76 -0
  30. examples/fish/assets/bullet_hell/player.py +89 -0
  31. examples/fish/assets/bullet_hell/player_bullets.py +34 -0
  32. examples/fish/assets/bullet_hell/setting.py +33 -0
  33. examples/fish/fish.py +67 -0
  34. examples/fish/main.py +4 -0
  35. examples/getting-started/step 1 - create a sprite/main.py +11 -0
  36. examples/getting-started/step 1 - create a sprite/player.py +5 -0
  37. examples/getting-started/step 2 - control a sprite/main.py +11 -0
  38. examples/getting-started/step 2 - control a sprite/player.py +42 -0
  39. examples/getting-started/step 3 - backdrops/main.py +17 -0
  40. examples/getting-started/step 3 - backdrops/player.py +33 -0
  41. examples/getting-started/step 4 - clone a sprite/enemy.py +53 -0
  42. examples/getting-started/step 4 - clone a sprite/main.py +17 -0
  43. examples/getting-started/step 4 - clone a sprite/player.py +32 -0
  44. examples/getting-started/step 4 - clone a sprite (simple)/enemy.py +42 -0
  45. examples/getting-started/step 4 - clone a sprite (simple)/main.py +17 -0
  46. examples/getting-started/step 4 - clone a sprite (simple)/player.py +32 -0
  47. examples/getting-started/step 5 - local variables/enemy.py +52 -0
  48. examples/getting-started/step 5 - local variables/main.py +17 -0
  49. examples/getting-started/step 5 - local variables/player.py +49 -0
  50. examples/getting-started/step 6 - shared variables/enemy.py +64 -0
  51. examples/getting-started/step 6 - shared variables/main.py +17 -0
  52. examples/getting-started/step 6 - shared variables/player.py +80 -0
  53. examples/getting-started/step 7 - Referencing other sprites/enemy.py +83 -0
  54. examples/getting-started/step 7 - Referencing other sprites/hearts.py +39 -0
  55. examples/getting-started/step 7 - Referencing other sprites/main.py +23 -0
  56. examples/getting-started/step 7 - Referencing other sprites/player.py +59 -0
  57. examples/getting-started/step 8 - sprite variables/enemy.py +98 -0
  58. examples/getting-started/step 8 - sprite variables/hearts.py +39 -0
  59. examples/getting-started/step 8 - sprite variables/main.py +22 -0
  60. examples/getting-started/step 8 - sprite variables/player.py +63 -0
  61. examples/getting-started/step 9 - messages/enemy.py +98 -0
  62. examples/getting-started/step 9 - messages/hearts.py +39 -0
  63. examples/getting-started/step 9 - messages/main.py +23 -0
  64. examples/getting-started/step 9 - messages/player.py +78 -0
  65. examples/perspective_background/main.py +14 -0
  66. examples/perspective_background/player.py +52 -0
  67. examples/perspective_background/trees.py +39 -0
  68. examples/simple_pong/ball.py +72 -0
  69. examples/simple_pong/left_paddle.py +36 -0
  70. examples/simple_pong/main.py +21 -0
  71. examples/simple_pong/right_paddle.py +37 -0
  72. examples/simple_pong/score_display.py +54 -0
  73. pyscratch/__init__.py +48 -0
  74. pyscratch/event.py +263 -0
  75. pyscratch/game_module.py +1589 -0
  76. pyscratch/helper.py +561 -0
  77. pyscratch/sprite.py +1920 -0
  78. pyscratch/tools/sprite_preview/left_panel/frame_preview_card.py +238 -0
  79. pyscratch/tools/sprite_preview/left_panel/frame_preview_panel.py +42 -0
  80. pyscratch/tools/sprite_preview/main.py +18 -0
  81. pyscratch/tools/sprite_preview/main_panel/animation_display.py +77 -0
  82. pyscratch/tools/sprite_preview/main_panel/frame_bin.py +33 -0
  83. pyscratch/tools/sprite_preview/main_panel/play_edit_ui.py +64 -0
  84. pyscratch/tools/sprite_preview/main_panel/set_as_sprite_folder.py +22 -0
  85. pyscratch/tools/sprite_preview/main_panel/sprite_edit_ui.py +174 -0
  86. pyscratch/tools/sprite_preview/main_panel/warning_message.py +25 -0
  87. pyscratch/tools/sprite_preview/right_panel/back_button.py +35 -0
  88. pyscratch/tools/sprite_preview/right_panel/cut_button.py +32 -0
  89. pyscratch/tools/sprite_preview/right_panel/cut_parameter_fitting.py +152 -0
  90. pyscratch/tools/sprite_preview/right_panel/cut_parameters.py +42 -0
  91. pyscratch/tools/sprite_preview/right_panel/file_display.py +84 -0
  92. pyscratch/tools/sprite_preview/right_panel/file_display_area.py +57 -0
  93. pyscratch/tools/sprite_preview/right_panel/spritesheet_view.py +262 -0
  94. pyscratch/tools/sprite_preview/right_panel/ss_select_corner.py +208 -0
  95. pyscratch/tools/sprite_preview/settings.py +14 -0
  96. pyscratch/tools/sprite_preview/utils/input_box.py +235 -0
  97. pyscratch/tools/sprite_preview/utils/render_wrapped_file_name.py +86 -0
  98. pyscratch_pysc-1.0.3.dist-info/METADATA +37 -0
  99. pyscratch_pysc-1.0.3.dist-info/RECORD +101 -0
  100. pyscratch_pysc-1.0.3.dist-info/WHEEL +5 -0
  101. pyscratch_pysc-1.0.3.dist-info/top_level.txt +3 -0
@@ -0,0 +1,238 @@
1
+ """
2
+ broadcast messages:
3
+ order_change ((old, new))
4
+ preview_click(dict(surface=surface, order=order))
5
+ change_animation_done (frames: List)
6
+
7
+
8
+ receice messages:
9
+ change_animation
10
+ reload the animation from the animation path
11
+ remove and create the frame cards for this animation
12
+
13
+ shared_data:
14
+ scrolling_offset (read only)
15
+ animation_path
16
+ frame_card_list
17
+ """
18
+
19
+ from typing import Dict, List
20
+
21
+ import numpy as np
22
+ import pyscratch as pysc
23
+ from pyscratch.sprite import Sprite
24
+ from settings import *
25
+ from pygame import Surface
26
+ from math import floor
27
+ from pathlib import Path
28
+
29
+
30
+ # Sprite Function: the frame preview card
31
+ FRAME_PREVIEW_MARGIN = 10
32
+ preview_width = LEFT_PANEL_WIDTH-FRAME_PREVIEW_MARGIN*2
33
+ preview_height = preview_width
34
+
35
+ def FramePreviewCard(surface:Surface, order):
36
+
37
+ preview_bg = pysc.create_rect_sprite(
38
+ (255, 255, 255),
39
+ preview_width,
40
+ preview_height
41
+ )
42
+ preview_bg['surface'] = surface
43
+ preview_bg['order'] = order
44
+ preview_bg.oob_limit = np.inf
45
+
46
+ preview_bg.set_draggable(True)
47
+
48
+
49
+ # set xy
50
+ ypos = FRAME_PREVIEW_MARGIN + order*(preview_height+FRAME_PREVIEW_MARGIN) + preview_height/2
51
+
52
+ xpos = LEFT_PANEL_WIDTH/2
53
+ preview_bg.set_xy((xpos, ypos))
54
+ preview_bg.y += pysc.game['scrolling_offset']
55
+
56
+ # display preview
57
+ image_margin = 20
58
+ fit = "horizontal" if surface.get_width() >= surface.get_height() else "vertical"
59
+ pv_surface = pysc.scale_to_fit_aspect(surface, (preview_width-image_margin, preview_height-image_margin ), fit)
60
+ preview_bg.draw(pv_surface, (preview_width/2, preview_height/2))
61
+
62
+
63
+ # send message on click
64
+ def on_click():
65
+
66
+
67
+ pysc.game.broadcast_message('preview_click', dict(surface=surface, order=order))
68
+ pysc.game.broadcast_message('show_bin', None)
69
+
70
+
71
+ preview_bg.when_this_sprite_clicked().add_handler(on_click)
72
+
73
+
74
+ # scrolling
75
+ def on_scrolling(offset):
76
+ preview_bg.y = ypos + offset
77
+ preview_bg.when_receive_message('scrolling').add_handler(on_scrolling)
78
+
79
+
80
+
81
+
82
+ # dragging
83
+ def on_mouse_release():
84
+ pysc.game.broadcast_message('hide_bin', None)
85
+
86
+ left_panel: pysc.Sprite = pysc.game['left_panel']
87
+
88
+ frame_card_list = pysc.game['frame_card_list']
89
+
90
+
91
+
92
+ new_order = ((preview_bg.y-pysc.game['scrolling_offset'])-preview_height/2-FRAME_PREVIEW_MARGIN)/(preview_height+FRAME_PREVIEW_MARGIN)
93
+ new_order = floor(new_order+0.5)
94
+
95
+
96
+ preview_bg.x = xpos
97
+
98
+ preview_bg.y = ypos + pysc.game['scrolling_offset']
99
+
100
+ new_order = min(max(new_order, 0), len(frame_card_list)-1)
101
+
102
+ if not (to_remove := pysc.game['frame_bin'].is_touching_mouse()):
103
+ if not left_panel.is_touching(preview_bg): return
104
+ if new_order == order: return
105
+
106
+
107
+ print(f"{order} -> {new_order}")
108
+
109
+ first_half = frame_card_list[:order]
110
+ second_half = frame_card_list[order+1:] if (order+1)<len(frame_card_list) else []
111
+
112
+ temp = first_half + second_half
113
+
114
+ #print([c['order'] for c in temp] )
115
+
116
+ if not to_remove:
117
+ temp = temp[:new_order] + [preview_bg] + (temp[new_order:] if (new_order)<len(temp) else [])
118
+
119
+ #print([c['order'] for c in temp] )
120
+
121
+ write_new_frame_list([f['surface'] for f in temp])
122
+
123
+ # update
124
+ pysc.game.broadcast_message('change_animation', pysc.game['animation_path'])
125
+
126
+ pysc.game.when_this_sprite_click_released(preview_bg).add_handler(on_mouse_release)
127
+
128
+ return preview_bg
129
+
130
+
131
+ def on_cut_sprite_frame_drop(data):
132
+ if not 'animation_path' in pysc.game.shared_data:
133
+ pysc.game.broadcast_message('warning', "Animation not selected yet.")
134
+ return
135
+
136
+
137
+
138
+ sprite: pysc.Sprite = data['sprite']
139
+ surface: Surface = data['surface']
140
+ mos_x, mos_y = data['position']
141
+ frame_card_list = pysc.game['frame_card_list']
142
+
143
+
144
+ left_panel: pysc.Sprite = pysc.game['left_panel']
145
+
146
+ if not left_panel.is_touching_mouse(): return
147
+
148
+
149
+
150
+ order = ((mos_y-pysc.game['scrolling_offset'])-preview_height/2-FRAME_PREVIEW_MARGIN)/(preview_height+FRAME_PREVIEW_MARGIN)
151
+ order = floor(order+0.5)
152
+
153
+
154
+
155
+ frame_card_list = pysc.game['frame_card_list']
156
+
157
+ first_half = frame_card_list[:order]
158
+ second_half = frame_card_list[order:] if (order)<len(frame_card_list) else []
159
+
160
+ frame_list = [f['surface'] for f in first_half] +[surface]+ [f['surface'] for f in second_half]
161
+
162
+ write_new_frame_list(frame_list)
163
+
164
+ # update
165
+ pysc.game.broadcast_message('change_animation', pysc.game['animation_path'])
166
+
167
+ sprite.x = sprite['x']
168
+ sprite.y = sprite['y']
169
+
170
+
171
+ pysc.game.when_receive_message('cut_sprite_frame_drop').add_handler(on_cut_sprite_frame_drop)
172
+
173
+
174
+
175
+
176
+ # helper function
177
+ import shutil
178
+ def write_new_frame_list(frame_list: List[Surface]):
179
+ # TODO: frame quality degrade over time?
180
+ temp_folder = Path('temp')
181
+ temp_folder.mkdir(exist_ok=True)
182
+ shutil.rmtree(temp_folder)
183
+ temp_folder.mkdir()
184
+
185
+ suffix = 'png' # TODO: allow changing suffix
186
+ for i, f in enumerate(frame_list):
187
+ pygame.image.save(f, temp_folder/f"{i}.{suffix}")
188
+
189
+ shutil.rmtree(pysc.game['animation_path'])
190
+ shutil.copytree(temp_folder, pysc.game['animation_path'])
191
+ shutil.rmtree(temp_folder)
192
+
193
+
194
+
195
+ # event: when there is a change to the animation
196
+ # reload the animation from the animation path
197
+ pysc.game['frame_card_list'] = []
198
+ def on_change_animation(path: Path):
199
+
200
+ #pysc.game['scrolling_offset'] = 0
201
+
202
+
203
+
204
+ pysc.game['animation_path'] = path
205
+ for c in pysc.game['frame_card_list']:
206
+ c.remove()
207
+ pysc.game['frame_card_list'] = []
208
+
209
+ def extract_images(path: Path):
210
+ index2image: Dict[int, pygame.Surface] = {}
211
+
212
+ for f in path.iterdir():
213
+ if f.is_dir():
214
+ continue
215
+
216
+ if not f.stem.isdigit():
217
+ print(f'skipping: {f.name}')
218
+ continue
219
+ index2image[int(f.stem)] = pygame.image.load(f).convert_alpha()
220
+
221
+ return [index2image[i] for i in sorted(index2image.keys())]
222
+
223
+ try:
224
+ frames = extract_images(path)
225
+ except:
226
+ print('invalid folder structure.')
227
+ return
228
+
229
+
230
+ for i, f in enumerate(frames):
231
+ pysc.game.shared_data['frame_card_list'].append(
232
+ FramePreviewCard(f, i)
233
+ )
234
+
235
+ pysc.game.broadcast_message("change_animation_done", frames)
236
+
237
+
238
+ pysc.game.when_receive_message('change_animation').add_handler(on_change_animation)
@@ -0,0 +1,42 @@
1
+ """
2
+ broadcast messages:
3
+ scrolling (scrolling_offset)
4
+
5
+ shared_data:
6
+ scrolling_offset
7
+ """
8
+
9
+
10
+ from pathlib import Path
11
+ from typing import Dict
12
+
13
+ from pygame import Surface
14
+ import pyscratch as pysc
15
+ from settings import *
16
+
17
+
18
+
19
+ # Sprite: the panel (the background of the preview frames)
20
+ PANEL_BG_COLOUR = 199, 207, 224
21
+ panel = pysc.create_rect_sprite(
22
+ PANEL_BG_COLOUR,
23
+ LEFT_PANEL_WIDTH,
24
+ SCREEN_HEIGHT# - PANEL_MARGIN*2
25
+ )
26
+ panel.set_xy((LEFT_PANEL_WIDTH/2, SCREEN_HEIGHT/2))
27
+
28
+ # event: scrolling
29
+ pysc.game['scrolling_offset'] = 0
30
+ def on_mouse_scroll(updown):
31
+ if not panel.is_touching_mouse(): return
32
+ if updown == 'up':
33
+ pysc.game['scrolling_offset'] += 10
34
+ else:
35
+
36
+ pysc.game['scrolling_offset'] -= 10
37
+
38
+ pysc.game.broadcast_message("scrolling", pysc.game['scrolling_offset'])
39
+
40
+ pysc.game.when_mouse_scroll().add_handler(on_mouse_scroll)
41
+ pysc.game['left_panel'] = panel
42
+
@@ -0,0 +1,18 @@
1
+ from pathlib import Path
2
+ import pyscratch as pysc
3
+ from settings import *
4
+
5
+ from right_panel import file_display_area, spritesheet_view, cut_parameters, back_button, cut_button, ss_select_corner, cut_parameter_fitting
6
+ from main_panel import sprite_edit_ui, play_edit_ui, animation_display, frame_bin, set_as_sprite_folder, warning_message
7
+ from left_panel import frame_preview_card, frame_preview_panel
8
+
9
+ bg = pysc.create_rect((221, 221, 221), SCREEN_WIDTH, SCREEN_HEIGHT)
10
+ pysc.game.update_screen_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
11
+ pysc.game.set_backdrops([bg])
12
+ pysc.game.switch_backdrop(0)
13
+
14
+ pysc.game.broadcast_message('folder_update', Path('assets'))
15
+ pysc.game.broadcast_message('cut_or_nav_mode_change', 'nav')
16
+ #pysc.game.broadcast_message('change_sprite_selection', Path('./testing_assets/cat'))
17
+
18
+ pysc.game.start(30)
@@ -0,0 +1,77 @@
1
+ """
2
+ shared_data:
3
+ display_sprite
4
+ scale_factor
5
+ frame_interval
6
+ is_playing
7
+
8
+ receive messages:
9
+ preview_click
10
+ change the frame of the display sprite when the preview is clicked
11
+
12
+ scale_factor_change
13
+ change the scale of the display sprite
14
+
15
+ change_animation_done
16
+ destory and create the display sprite for a new animation
17
+ """
18
+
19
+ from pathlib import Path
20
+ from typing import Dict
21
+
22
+ from pygame import Surface
23
+ import pyscratch as pysc
24
+ from settings import *
25
+
26
+
27
+ pysc.game['display_sprite'] = None
28
+
29
+
30
+ def create_display_sprite(frames):
31
+
32
+ #frame_list = [c['surface'] for c in pysc.game['frame_card_list']]
33
+ #print(frames)
34
+ if display_sprite:=pysc.game['display_sprite']:
35
+ display_sprite.remove()
36
+ x, y = display_sprite.x, display_sprite.y
37
+ else:
38
+ x, y = 350, 200
39
+
40
+ if not len(frames):
41
+ pysc.game['display_sprite'] = None
42
+ return
43
+
44
+
45
+ sprite = pysc.Sprite({'always':frames})
46
+ sprite.set_xy((x, y))
47
+
48
+ sprite.set_draggable(True)
49
+
50
+ if pysc.game['scale_factor']:
51
+ sprite.set_scale(pysc.game['scale_factor'])
52
+
53
+ pysc.game['display_sprite'] = sprite
54
+
55
+ def play(_):
56
+ #TODO: if the user put a big value in frame_interval, and change it back to a small one
57
+ # the animation will wait for the big frame_interval until it comes back again
58
+ while True:
59
+ itv = pysc.game['frame_interval']
60
+ if pysc.game['is_playing'] and itv:
61
+ sprite.next_frame()
62
+ yield itv if itv else 0.1
63
+
64
+ sprite.when_timer_above(0).add_handler(play)
65
+
66
+
67
+ def on_scale_factor_change(scale):
68
+ print(scale)
69
+ if scale:
70
+ sprite.set_scale(scale)
71
+
72
+ sprite.when_receive_message("scale_factor_change").add_handler(on_scale_factor_change)
73
+ sprite.when_receive_message('preview_click').add_handler(lambda d: sprite.set_frame(d['order']))
74
+
75
+
76
+
77
+ pysc.game.when_receive_message("change_animation_done").add_handler(create_display_sprite)
@@ -0,0 +1,33 @@
1
+ """
2
+ msg in:
3
+ show_bin
4
+ hide_bin
5
+
6
+ shared data
7
+ frame_bin
8
+ """
9
+
10
+
11
+ import pyscratch as pysc
12
+ from settings import *
13
+
14
+
15
+ frame_bin = pysc.create_rect_sprite((255, 127, 127), 100, 100)
16
+ frame_bin.write_text("bin", DEFAULT_FONT48, offset=(50, 50))
17
+
18
+ def set_xy():
19
+
20
+ container = pysc.game['main_bottom_panel']
21
+
22
+ frame_bin.hide()
23
+ frame_bin.lock_to(container, (0,0))
24
+ frame_bin.x = 0
25
+ frame_bin.y = 0
26
+
27
+ frame_bin.when_game_start().add_handler(set_xy)
28
+
29
+
30
+ frame_bin.when_receive_message('show_bin').add_handler(lambda d: frame_bin.show())
31
+ frame_bin.when_receive_message('hide_bin').add_handler(lambda d: frame_bin.hide())
32
+
33
+ pysc.game['frame_bin'] = frame_bin
@@ -0,0 +1,64 @@
1
+ from utils.input_box import IntegerInputBox, FloatInputBoxVerticallyLabel
2
+ import pyscratch as pysc
3
+ from settings import *
4
+ frame_itv = FloatInputBoxVerticallyLabel("frame_interval", default_value="0.2")
5
+
6
+ def set_xy():
7
+ container = pysc.game['main_bottom_panel']
8
+ frame_itv.lock_to(container, (0,0))
9
+ frame_itv.set_xy((200, 30))
10
+
11
+ frame_itv.when_game_start().add_handler(
12
+ set_xy
13
+ )
14
+
15
+ def new_switch(text0, text1, data_key):
16
+ container = pysc.game.shared_data['main_bottom_panel']
17
+ container_width, container_height = pysc.game.shared_data['main_bottom_size']
18
+
19
+ button_w, button_h = 80, 50
20
+ button = pysc.create_rect_sprite((221, 221, 221), button_w, button_h)
21
+
22
+ pysc.game.shared_data[data_key] = False
23
+ button.write_text(text0, DEFAULT_FONT48, colour=(0,0,0), offset=(button_w/2, button_h/2))
24
+
25
+ def on_click():
26
+ pysc.game.shared_data[data_key] = not pysc.game.shared_data[data_key]
27
+
28
+ if pysc.game.shared_data[data_key]:
29
+ button.write_text(text1, DEFAULT_FONT48, colour=(0,0,0), offset=(button_w/2, button_h/2))
30
+ else:
31
+ button.write_text(text0, DEFAULT_FONT48, colour=(0,0,0), offset=(button_w/2, button_h/2))
32
+
33
+ button.when_this_sprite_clicked().add_handler(on_click)
34
+
35
+
36
+ button.lock_to(container, (-(container_width-button_w)/2, -(container_height-button_h)/2), reset_xy=True)
37
+ return button
38
+
39
+
40
+ def create_play_button():
41
+ container = pysc.game.shared_data['main_bottom_panel']
42
+
43
+ play_button = new_switch('Play','Pause', 'is_playing')
44
+ play_button.lock_to(container, (0,0))
45
+
46
+ play_button.set_xy((0, 70))
47
+
48
+ pysc.game.when_game_start().add_handler(create_play_button)
49
+
50
+
51
+
52
+
53
+
54
+ scale_factor_input = FloatInputBoxVerticallyLabel("scale_factor", "scale_factor_change", default_value="1")
55
+
56
+ def set_xy2():
57
+ container = pysc.game.shared_data['main_bottom_panel']
58
+ scale_factor_input.lock_to(container, (0,0))
59
+ scale_factor_input.set_xy((200, 120))
60
+
61
+ scale_factor_input.when_game_start().add_handler(
62
+ set_xy2
63
+ )
64
+
@@ -0,0 +1,22 @@
1
+ from utils.input_box import IntegerInputBox, FloatInputBoxVerticallyLabel
2
+ import pyscratch as pysc
3
+ from settings import *
4
+
5
+ button = pysc.create_rect_sprite((150, 150, 150), 220, 50)
6
+ button.write_text('Set current folder as sprite', DEFAULT_FONT24, offset=(110, 25))
7
+
8
+ def set_xy():
9
+ container = pysc.game['main_bottom_panel']
10
+ button.lock_to(container, (0,0))
11
+ button.x = 0
12
+ button.y = 0
13
+
14
+ button.when_game_start().add_handler(set_xy)
15
+
16
+
17
+ def on_click():
18
+ pysc.game.broadcast_message('change_sprite_selection', pysc.game['path'])
19
+ pass
20
+
21
+
22
+ button.when_this_sprite_clicked().add_handler(on_click)
@@ -0,0 +1,174 @@
1
+ """
2
+ shared_data
3
+ animation_dict (order -> animation selection button)
4
+ sprite_folder_path
5
+ path (read): navigation path
6
+ main_bottom_size (read)
7
+ main_bottom_panel (read)
8
+
9
+ broadcast messages:
10
+ folder_update (navigation path)
11
+ change_sprite_selection (path of the sprite folder)
12
+ change_animation (path of the animation folder)
13
+
14
+
15
+ receive messages:
16
+ change_sprite_selection
17
+ change the animation panel when another sprite is selected
18
+ """
19
+
20
+
21
+ from pathlib import Path
22
+ from typing import cast
23
+ import pyscratch as pysc
24
+ from settings import *
25
+
26
+ container_width = SCREEN_WIDTH - LEFT_PANEL_WIDTH - RIGHT_PANEL_WIDTH - PANEL_MARGIN*3
27
+ container_height = 300
28
+
29
+ # container
30
+ container = pysc.create_rect_sprite((230, 230, 230), container_width, container_height)
31
+ container.x = container_width/2+LEFT_PANEL_WIDTH+PANEL_MARGIN
32
+ container.y = SCREEN_HEIGHT-container_height/2-PANEL_MARGIN
33
+ pysc.game['main_bottom_panel'] = container
34
+ pysc.game['main_bottom_size'] = container_width, container_height
35
+
36
+ # sprite function
37
+ def NewButton(text):
38
+ button_w, button_h = 150, 50
39
+ button = pysc.create_rect_sprite((221, 221, 221), button_w, button_h)
40
+ button.write_text(text, DEFAULT_FONT48, colour=(0,0,0), offset=(button_w/2, button_h/2))
41
+ button.lock_to(container, (-(container_width-button_w)/2, -(container_height-button_h)/2), reset_xy=True)
42
+ return button
43
+
44
+
45
+ # sprite: add sprite button
46
+ add_sprite_button = NewButton("New Sprite")
47
+ add_sprite_button.y=10
48
+ add_sprite_button.x=200
49
+
50
+ # event: the click of the add sprite button
51
+ def on_click1():
52
+ folder_path: Path = pysc.game.shared_data['path']
53
+
54
+ c = 0
55
+ while True:
56
+
57
+ new_folder = (folder_path / f"unnamed_sprite_{c}")
58
+ if not new_folder.exists():
59
+ new_folder.mkdir()
60
+ break
61
+ else:
62
+ c+=1
63
+ pysc.game.broadcast_message('folder_update', folder_path)
64
+ pysc.game.broadcast_message('cut_or_nav_mode_change', 'nav')
65
+ pysc.game.broadcast_message('change_sprite_selection', new_folder)
66
+
67
+ add_sprite_button.when_this_sprite_clicked().add_handler(on_click1)
68
+
69
+
70
+ # sprite function: animation selection
71
+ def AnimationSelection(order, path):
72
+
73
+
74
+ w, h = 120, 30
75
+ on_select = pysc.create_rect((150,150, 150), w, h)
76
+ not_on_select = pysc.create_rect((127, 127, 127), w, h)
77
+ sprite = pysc.Sprite(dict(on_select=[on_select], not_on_select=[not_on_select]))
78
+
79
+ sprite.lock_to(container, (-(container_width-w)/2, -(container_height-h)/2))
80
+ sprite.x = 3
81
+ sprite.y = order*(h+3)+3
82
+
83
+ sprite.set_animation('on_select')
84
+ sprite.write_text(path.stem, DEFAULT_FONT24, offset=(w/2, h/2))
85
+
86
+ sprite.set_animation('not_on_select')
87
+ sprite.write_text(path.stem, DEFAULT_FONT24, offset=(w/2, h/2))
88
+
89
+
90
+
91
+ def on_click():
92
+ sprite.set_animation('on_select')
93
+
94
+ pysc.game.broadcast_message('change_animation', path)
95
+ pysc.game.broadcast_message('deselect', sprite)
96
+
97
+
98
+ sprite.when_this_sprite_clicked().add_handler(on_click)
99
+
100
+
101
+ def on_deselect(s):
102
+ if not sprite is s:
103
+ sprite.set_animation('not_on_select')
104
+
105
+ sprite.when_receive_message('deselect').add_handler(on_deselect)
106
+
107
+ return sprite
108
+
109
+ # event: msg: change_sprite_selection:
110
+ # remove and create the animation buttons when sprite change
111
+ pysc.game['animation_dict'] = {}
112
+ def on_msg_change_sprite_selection(sprite_folder:Path):
113
+ """
114
+ change the animation selection buttons
115
+ """
116
+
117
+ pysc.game['sprite_folder_path'] = sprite_folder
118
+
119
+ #pysc.game['frame_dict'] =
120
+
121
+
122
+
123
+ # remove all the old buttons
124
+ for k, v in pysc.game['animation_dict'].items():
125
+ v.remove()
126
+ pysc.game['animation_dict'] = {}
127
+
128
+ animation_dict = pysc.game['animation_dict']
129
+
130
+
131
+ # add the new buttons
132
+ c = 0
133
+ for f in sprite_folder.iterdir():
134
+ if f.is_dir():
135
+ animation_dict[c] = AnimationSelection(c, f)
136
+ c+=1
137
+
138
+ pysc.game.when_receive_message("change_sprite_selection").add_handler(on_msg_change_sprite_selection)
139
+
140
+
141
+
142
+
143
+ # sprite: add animation button
144
+ add_animation_button = NewButton("New Animation")
145
+ add_animation_button.x = 370
146
+ add_animation_button.y = 10
147
+
148
+ # event: click of the add animation button
149
+ def on_click2():
150
+
151
+
152
+ if not (folder_path:= pysc.game.shared_data.get('sprite_folder_path')):
153
+ pysc.game.broadcast_message('warning', "Sprite folder not selected yet")
154
+ return
155
+
156
+ folder_path = cast(Path, folder_path)
157
+ c = 0
158
+ while True:
159
+
160
+
161
+ new_folder = (folder_path / f"animation_{c}")
162
+ if not new_folder.exists():
163
+ new_folder.mkdir()
164
+ break
165
+ else:
166
+ c+=1
167
+
168
+ pysc.game.broadcast_message('folder_update', pysc.game.shared_data['path'])
169
+
170
+ # no actual change. just to trigger the update
171
+ pysc.game.broadcast_message('change_sprite_selection', folder_path)
172
+
173
+
174
+ add_animation_button.when_this_sprite_clicked().add_handler(on_click2)
@@ -0,0 +1,25 @@
1
+ from utils.render_wrapped_file_name import render_wrapped_file_name
2
+ import pyscratch as pysc
3
+ from settings import *
4
+
5
+ w, h = 400, 100
6
+ message_display = pysc.create_rect_sprite((255, 255, 255), w, h)
7
+ message_display.hide()
8
+ ori_xy = 200, 200
9
+ message_display.set_draggable(True)
10
+
11
+ def on_warning_message(message):
12
+
13
+ message_display.show()
14
+ message_display.set_xy(ori_xy)
15
+ txt = render_wrapped_file_name(message, 200, DEFAULT_FONT24, color=(255,0,0))
16
+ message_display.draw(txt, offset=(w/2, h/2))
17
+
18
+
19
+
20
+ message_display.when_receive_message('warning').add_handler(on_warning_message)
21
+
22
+ def on_click():
23
+ message_display.hide()
24
+
25
+ message_display.when_this_sprite_clicked().add_handler(on_click)