pyscratch-pysc 1.0.3__py3-none-any.whl → 2.0.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.
Files changed (146) hide show
  1. assets/startup-assets/tutorial-steps/1-create-sprites/main.py +10 -0
  2. assets/startup-assets/tutorial-steps/1-create-sprites/player.py +5 -0
  3. assets/startup-assets/tutorial-steps/1-create-sprites-task/enemy.py +4 -0
  4. assets/startup-assets/tutorial-steps/1-create-sprites-task/main.py +11 -0
  5. assets/startup-assets/tutorial-steps/1-create-sprites-task/player.py +5 -0
  6. assets/startup-assets/tutorial-steps/2-basic-events/enemy.py +4 -0
  7. assets/startup-assets/tutorial-steps/2-basic-events/main.py +11 -0
  8. assets/startup-assets/tutorial-steps/2-basic-events/player.py +31 -0
  9. assets/startup-assets/tutorial-steps/2-basic-events-task1/enemy.py +4 -0
  10. assets/startup-assets/tutorial-steps/2-basic-events-task1/main.py +11 -0
  11. assets/startup-assets/tutorial-steps/2-basic-events-task1/player.py +23 -0
  12. assets/startup-assets/tutorial-steps/2-basic-events-task2/enemy.py +14 -0
  13. assets/startup-assets/tutorial-steps/2-basic-events-task2/main.py +11 -0
  14. assets/startup-assets/tutorial-steps/2-basic-events-task2/player.py +23 -0
  15. assets/startup-assets/tutorial-steps/3-loops-conditions/enemy.py +14 -0
  16. assets/startup-assets/tutorial-steps/3-loops-conditions/main.py +11 -0
  17. assets/startup-assets/tutorial-steps/3-loops-conditions/player.py +23 -0
  18. assets/startup-assets/tutorial-steps/3-loops-conditions-task1/enemy.py +14 -0
  19. assets/startup-assets/tutorial-steps/3-loops-conditions-task1/main.py +11 -0
  20. assets/startup-assets/tutorial-steps/3-loops-conditions-task1/player.py +34 -0
  21. assets/startup-assets/tutorial-steps/3-loops-conditions-task2/enemy.py +23 -0
  22. assets/startup-assets/tutorial-steps/3-loops-conditions-task2/main.py +11 -0
  23. assets/startup-assets/tutorial-steps/3-loops-conditions-task2/player.py +41 -0
  24. assets/startup-assets/tutorial-steps/4-variables/enemy.py +23 -0
  25. assets/startup-assets/tutorial-steps/4-variables/main.py +11 -0
  26. assets/startup-assets/tutorial-steps/4-variables/player.py +59 -0
  27. assets/startup-assets/tutorial-steps/5-sprite-object/enemy.py +19 -0
  28. assets/startup-assets/tutorial-steps/5-sprite-object/main.py +11 -0
  29. assets/startup-assets/tutorial-steps/5-sprite-object/player.py +20 -0
  30. assets/startup-assets/tutorial-steps/5-sprite-object-task1/enemy.py +19 -0
  31. assets/startup-assets/tutorial-steps/5-sprite-object-task1/main.py +11 -0
  32. assets/startup-assets/tutorial-steps/5-sprite-object-task1/player.py +38 -0
  33. assets/startup-assets/tutorial-steps/5-sprite-object-task2/enemy.py +20 -0
  34. assets/startup-assets/tutorial-steps/5-sprite-object-task2/main.py +11 -0
  35. assets/startup-assets/tutorial-steps/5-sprite-object-task2/player.py +58 -0
  36. assets/startup-assets/tutorial-steps/6-referencing-sprites/enemy.py +32 -0
  37. assets/startup-assets/tutorial-steps/6-referencing-sprites/main.py +11 -0
  38. assets/startup-assets/tutorial-steps/6-referencing-sprites/player.py +59 -0
  39. assets/startup-assets/tutorial-steps/6-referencing-sprites-task/enemy.py +37 -0
  40. assets/startup-assets/tutorial-steps/6-referencing-sprites-task/main.py +11 -0
  41. assets/startup-assets/tutorial-steps/6-referencing-sprites-task/player.py +60 -0
  42. assets/startup-assets/tutorial-steps/7-parameterised-events/enemy.py +37 -0
  43. assets/startup-assets/tutorial-steps/7-parameterised-events/main.py +11 -0
  44. assets/startup-assets/tutorial-steps/7-parameterised-events/player.py +83 -0
  45. assets/startup-assets/tutorial-steps/7-parameterised-events-msg/enemy.py +37 -0
  46. assets/startup-assets/tutorial-steps/7-parameterised-events-msg/main.py +11 -0
  47. assets/startup-assets/tutorial-steps/7-parameterised-events-msg/player.py +86 -0
  48. assets/startup-assets/tutorial-steps/7-parameterised-events-task/enemy.py +35 -0
  49. assets/startup-assets/tutorial-steps/7-parameterised-events-task/main.py +11 -0
  50. assets/startup-assets/tutorial-steps/7-parameterised-events-task/player.py +86 -0
  51. assets/startup-assets/tutorial-steps/8-backdrop-music/enemy.py +35 -0
  52. assets/startup-assets/tutorial-steps/8-backdrop-music/main.py +11 -0
  53. assets/startup-assets/tutorial-steps/8-backdrop-music/player.py +86 -0
  54. assets/startup-assets/tutorial-steps/9-polish/enemy.py +39 -0
  55. assets/startup-assets/tutorial-steps/9-polish/enemy_red.py +40 -0
  56. assets/startup-assets/tutorial-steps/9-polish/main.py +12 -0
  57. assets/startup-assets/tutorial-steps/9-polish/player.py +119 -0
  58. examples/fish/assets/startup-assets/tutorial-steps/1-create-sprites/main.py +10 -0
  59. examples/fish/assets/startup-assets/tutorial-steps/1-create-sprites/player.py +5 -0
  60. examples/fish/assets/startup-assets/tutorial-steps/1-create-sprites-task/enemy.py +4 -0
  61. examples/fish/assets/startup-assets/tutorial-steps/1-create-sprites-task/main.py +11 -0
  62. examples/fish/assets/startup-assets/tutorial-steps/1-create-sprites-task/player.py +5 -0
  63. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events/enemy.py +4 -0
  64. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events/main.py +11 -0
  65. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events/player.py +31 -0
  66. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events-task1/enemy.py +4 -0
  67. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events-task1/main.py +11 -0
  68. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events-task1/player.py +23 -0
  69. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events-task2/enemy.py +14 -0
  70. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events-task2/main.py +11 -0
  71. examples/fish/assets/startup-assets/tutorial-steps/2-basic-events-task2/player.py +23 -0
  72. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions/enemy.py +14 -0
  73. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions/main.py +11 -0
  74. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions/player.py +23 -0
  75. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions-task1/enemy.py +14 -0
  76. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions-task1/main.py +11 -0
  77. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions-task1/player.py +34 -0
  78. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions-task2/enemy.py +23 -0
  79. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions-task2/main.py +11 -0
  80. examples/fish/assets/startup-assets/tutorial-steps/3-loops-conditions-task2/player.py +41 -0
  81. examples/fish/assets/startup-assets/tutorial-steps/4-variables/enemy.py +23 -0
  82. examples/fish/assets/startup-assets/tutorial-steps/4-variables/main.py +11 -0
  83. examples/fish/assets/startup-assets/tutorial-steps/4-variables/player.py +59 -0
  84. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object/enemy.py +19 -0
  85. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object/main.py +11 -0
  86. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object/player.py +20 -0
  87. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object-task1/enemy.py +19 -0
  88. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object-task1/main.py +11 -0
  89. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object-task1/player.py +38 -0
  90. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object-task2/enemy.py +20 -0
  91. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object-task2/main.py +11 -0
  92. examples/fish/assets/startup-assets/tutorial-steps/5-sprite-object-task2/player.py +58 -0
  93. examples/fish/assets/startup-assets/tutorial-steps/6-referencing-sprites/enemy.py +32 -0
  94. examples/fish/assets/startup-assets/tutorial-steps/6-referencing-sprites/main.py +11 -0
  95. examples/fish/assets/startup-assets/tutorial-steps/6-referencing-sprites/player.py +59 -0
  96. examples/fish/assets/startup-assets/tutorial-steps/6-referencing-sprites-task/enemy.py +37 -0
  97. examples/fish/assets/startup-assets/tutorial-steps/6-referencing-sprites-task/main.py +11 -0
  98. examples/fish/assets/startup-assets/tutorial-steps/6-referencing-sprites-task/player.py +60 -0
  99. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events/enemy.py +37 -0
  100. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events/main.py +11 -0
  101. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events/player.py +83 -0
  102. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events-msg/enemy.py +37 -0
  103. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events-msg/main.py +11 -0
  104. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events-msg/player.py +86 -0
  105. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events-task/enemy.py +35 -0
  106. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events-task/main.py +11 -0
  107. examples/fish/assets/startup-assets/tutorial-steps/7-parameterised-events-task/player.py +86 -0
  108. examples/fish/assets/startup-assets/tutorial-steps/8-backdrop-music/enemy.py +35 -0
  109. examples/fish/assets/startup-assets/tutorial-steps/8-backdrop-music/main.py +11 -0
  110. examples/fish/assets/startup-assets/tutorial-steps/8-backdrop-music/player.py +86 -0
  111. examples/fish/assets/startup-assets/tutorial-steps/9-polish/enemy.py +39 -0
  112. examples/fish/assets/startup-assets/tutorial-steps/9-polish/enemy_red.py +40 -0
  113. examples/fish/assets/startup-assets/tutorial-steps/9-polish/main.py +12 -0
  114. examples/fish/assets/startup-assets/tutorial-steps/9-polish/player.py +119 -0
  115. examples/getting-started/step 7 - Referencing other sprites/enemy.py +1 -6
  116. examples/tutorial-day1/chest.py +21 -0
  117. examples/tutorial-day1/enemy.py +106 -0
  118. examples/tutorial-day1/friend.py +51 -0
  119. examples/tutorial-day1/in-steps/1-create-sprites/chest.py +5 -0
  120. examples/tutorial-day1/in-steps/1-create-sprites/enemy.py +5 -0
  121. examples/tutorial-day1/in-steps/1-create-sprites/main.py +9 -0
  122. examples/tutorial-day1/in-steps/2-basic-events/chest.py +24 -0
  123. examples/tutorial-day1/in-steps/2-basic-events/enemy.py +18 -0
  124. examples/tutorial-day1/in-steps/2-basic-events/main.py +9 -0
  125. examples/tutorial-day1/in-steps/3-flow/chest.py +25 -0
  126. examples/tutorial-day1/in-steps/3-flow/enemy.py +56 -0
  127. examples/tutorial-day1/in-steps/3-flow/friend.py +47 -0
  128. examples/tutorial-day1/in-steps/3-flow/main.py +9 -0
  129. examples/tutorial-day1/in-steps/4-variables/chest.py +37 -0
  130. examples/tutorial-day1/in-steps/4-variables/enemy.py +76 -0
  131. examples/tutorial-day1/in-steps/4-variables/friend.py +49 -0
  132. examples/tutorial-day1/in-steps/4-variables/main.py +9 -0
  133. examples/tutorial-day1/in-steps/5-backdrops/chest.py +37 -0
  134. examples/tutorial-day1/in-steps/5-backdrops/enemy.py +76 -0
  135. examples/tutorial-day1/in-steps/5-backdrops/friend.py +49 -0
  136. examples/tutorial-day1/in-steps/5-backdrops/main.py +26 -0
  137. examples/tutorial-day1/main.py +48 -0
  138. examples/tutorial-day1/target.py +14 -0
  139. examples/tutorial-day1/text.py +23 -0
  140. pyscratch/game_module.py +73 -32
  141. pyscratch/sprite.py +42 -10
  142. {pyscratch_pysc-1.0.3.dist-info → pyscratch_pysc-2.0.0.dist-info}/METADATA +8 -3
  143. pyscratch_pysc-2.0.0.dist-info/RECORD +239 -0
  144. pyscratch_pysc-1.0.3.dist-info/RECORD +0 -101
  145. {pyscratch_pysc-1.0.3.dist-info → pyscratch_pysc-2.0.0.dist-info}/WHEEL +0 -0
  146. {pyscratch_pysc-1.0.3.dist-info → pyscratch_pysc-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,76 @@
1
+ import pyscratch as pysc
2
+ from pyscratch import game
3
+
4
+ enemy = pysc.create_single_costume_sprite("assets/fish_red_skeleton_outline.png")
5
+
6
+
7
+ def clicked():
8
+ """
9
+ when the enemy is clicked:
10
+ change the enemy location with a fade out effect
11
+ """
12
+ game['score'] += 10
13
+
14
+
15
+ for i in range(10):
16
+ yield 1/game.framerate
17
+ enemy.set_transparency(1-i/10) # print(1-i/10) if you find this confusing.
18
+ enemy.scale_by(0.9)
19
+
20
+ enemy.x = pysc.random_number(0, game.screen_width)
21
+ enemy.y = pysc.random_number(0, game.screen_height)
22
+
23
+ enemy.set_transparency(1)
24
+ enemy.set_scale(1)
25
+
26
+ enemy.when_this_sprite_clicked().add_handler(clicked)
27
+
28
+
29
+ def movement():
30
+ """
31
+ when_game_start:
32
+ the movement of the enemy
33
+ """
34
+
35
+ centre = (game.screen_width/2, game.screen_height/2)
36
+
37
+ while True:
38
+ yield 1/game.framerate
39
+
40
+ speed = 5+game['score']*0.1
41
+ speed = max(1, speed)
42
+
43
+
44
+ # get the distance to the mouse
45
+ mouse_x, mouse_y = pysc.get_mouse_pos()
46
+ distance_to_mouse = enemy.distance_to((mouse_x, mouse_y))
47
+
48
+ # enemy avoids the mouse when it is close to the mouse
49
+ if distance_to_mouse < 200:
50
+ enemy.point_towards_mouse()
51
+ enemy.direction += 180
52
+ enemy.move_indir(speed)
53
+
54
+ # otherwise, go to the centre of the screen
55
+ else:
56
+ enemy.point_towards(centre)
57
+ enemy.move_indir(speed)
58
+
59
+
60
+ enemy.when_game_start().add_handler(movement)
61
+
62
+
63
+
64
+ def reduce_score():
65
+ """
66
+ reduce the score for every 0.1 second the enemy is in the centre
67
+ """
68
+ centre = (game.screen_width/2, game.screen_height/2)
69
+
70
+ while True:
71
+ yield 0.1
72
+
73
+ if enemy.distance_to(centre) < 50:
74
+ game['score'] -= 1
75
+
76
+ enemy.when_game_start().add_handler(reduce_score)
@@ -0,0 +1,49 @@
1
+ import pyscratch as pysc
2
+ import pygame
3
+ game = pysc.game
4
+
5
+ friend = pysc.create_single_costume_sprite("assets/fish_orange_outline.png")
6
+
7
+ def movement():
8
+ """
9
+ when_game_start:
10
+ the movement of the friend: always moving away from the curosr
11
+ """
12
+ centre = game.screen_width/2, game.screen_height/2
13
+ while True:
14
+ yield 1/game.framerate
15
+ mouse_x, mouse_y = pysc.get_mouse_pos()
16
+ if friend.distance_to((mouse_x, mouse_y)) < 200:
17
+ friend.point_towards_mouse()
18
+ friend.direction += 180
19
+ friend.move_indir(2)
20
+
21
+ else:
22
+ friend.point_towards(centre)
23
+ friend.move_indir(2)
24
+
25
+ friend.when_game_start().add_handler(movement)
26
+
27
+
28
+
29
+ def check_if_centred():
30
+ """
31
+ when_game_start:
32
+ move away when near the centre
33
+ """
34
+ centre = game.screen_width/2, game.screen_height/2
35
+ while True:
36
+ yield 1/game.framerate
37
+ if friend.distance_to(centre) < 50:
38
+ game['score'] += 10
39
+
40
+ new_x = pysc.random_number(0, game.screen_width)
41
+ new_y = pysc.random_number(0, game.screen_height)
42
+
43
+ friend.x = new_x
44
+ friend.y = new_y
45
+
46
+ friend.when_game_start().add_handler(check_if_centred)
47
+
48
+
49
+
@@ -0,0 +1,26 @@
1
+ import pyscratch as pysc
2
+ from pyscratch import game
3
+ import chest, enemy, friend
4
+
5
+ # background
6
+ bg0 = pysc.load_image("assets/undersea_bg.png")
7
+ bg0 = pysc.scale_to_fit_aspect(bg0, (1024, 576))
8
+ game.add_backdrop('bg0', bg0)
9
+
10
+ bg1 = pysc.load_image("assets/Cat In Space Wallpaper Hq.jpg")
11
+ bg1 = pysc.scale_to_fit_aspect(bg1, (1024, 576))
12
+ game.add_backdrop('bg1', bg1)
13
+
14
+
15
+
16
+ def on_game_start():
17
+ game.switch_backdrop('bg0')
18
+
19
+ game.when_game_start().add_handler(on_game_start)
20
+
21
+
22
+ # starting the game
23
+ game.update_screen_mode((1024, 576))
24
+ game.start(show_mouse_position=True)
25
+
26
+
@@ -0,0 +1,48 @@
1
+ import pyscratch as pysc
2
+ import pygame
3
+ import target, enemy, chest, friend#, text
4
+
5
+ game = pysc.game
6
+
7
+ # mouse
8
+ pygame.mouse.set_visible(False)
9
+
10
+
11
+ # background
12
+ bg0 = pysc.load_image("assets/undersea_bg.png")
13
+ bg0 = pysc.scale_to_fit_aspect(bg0, (1024, 576))
14
+ game.add_backdrop('bg0', bg0)
15
+
16
+ bg1 = pysc.load_image("assets/Cat In Space Wallpaper Hq.jpg")
17
+ bg1 = pysc.scale_to_fit_aspect(bg1, (1024, 576))
18
+ game.add_backdrop('bg1', bg1)
19
+
20
+ game.switch_backdrop('bg0')
21
+
22
+ # sound
23
+ game.load_sound("hit", "assets/impactMetal_light_004.ogg")
24
+ game.load_sound("background", "assets/Circus-Theme-Entry-of-the-Gladiators-Ragtime-Version(chosic.com).mp3")
25
+
26
+ def play_loop():
27
+ while True:
28
+ game.play_sound("background", volume=0)
29
+ yield 2*60+33
30
+ game.when_game_start().add_handler(play_loop)
31
+
32
+
33
+
34
+
35
+ def background():
36
+ while True:
37
+ yield 1/game.framerate
38
+ if game['score'] < 0:
39
+ game.switch_backdrop('bg1')
40
+
41
+
42
+ game.when_game_start().add_handler(background)
43
+
44
+
45
+ game.update_screen_mode((1024, 576))
46
+ game.start(show_mouse_position=True)
47
+
48
+
@@ -0,0 +1,14 @@
1
+ import pyscratch as pysc
2
+ game = pysc.game
3
+ target = pysc.create_single_costume_sprite("assets/target_b.png")
4
+
5
+ # 3. Flow control
6
+ def follow_mouse():
7
+ game.bring_to_front(target)
8
+ while True:
9
+ yield 1/game.framerate
10
+ mouse_x, mouse_y = pysc.get_mouse_pos()
11
+ target.x = mouse_x
12
+ target.y = mouse_y
13
+
14
+ target.when_game_start().add_handler(follow_mouse)
@@ -0,0 +1,23 @@
1
+ import pyscratch as pysc
2
+ import pygame
3
+ game = pysc.game
4
+
5
+ text_box = pysc.create_rect_sprite((200, 200, 200, 20), 700, 90)
6
+ font = pygame.font.Font('assets/Kenney Future.ttf', size=96)
7
+
8
+ text_box.write_text("YOU LOSE", font, offset=(350, 45))
9
+
10
+
11
+ text_box.hide()
12
+
13
+ text_box.set_draggable(True)
14
+ text_box.set_xy((260, 195))
15
+ text_box.direction = -35
16
+
17
+
18
+
19
+ def game_end():
20
+ text_box.show()
21
+
22
+ text_box.when_backdrop_switched(1).add_handler(game_end)
23
+
pyscratch/game_module.py CHANGED
@@ -12,6 +12,7 @@ from pathlib import Path
12
12
  import threading
13
13
  import time
14
14
  import json, inspect
15
+ from typing_extensions import deprecated
15
16
 
16
17
  import numpy as np
17
18
  import pygame
@@ -309,16 +310,23 @@ class Game:
309
310
  self._mouse_drag_trigger = self.create_pygame_event([pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP, pygame.MOUSEMOTION])
310
311
  self._mouse_drag_trigger.add_handler(self.__mouse_drag_handler)
311
312
 
312
- ## Backdrops
313
- self.backdrops: List[pygame.Surface] = []
314
- """A list of all the loaded backdrop images. You will not need to interact with this property directly."""
313
+ # Backdrops
314
+ self.backdrops_by_key: Dict[str, pygame.Surface] = {}
315
+ self.backdrop_indices_by_key: Dict[str, int] = {}
316
+ self.backdrop_keys: List[str] = []
317
+
318
+ # TODO: testing needed
315
319
 
316
320
  self.__screen_width: int = 0
317
321
  self.__screen_height: int = 0
318
322
  self.__framerate: float = 0
319
323
 
320
-
324
+ # TODO index and key need to be changed together
325
+ # the index is remained for the next_backdrop function
321
326
  self.__backdrop_index = None
327
+ self.__backdrop_key = None
328
+
329
+ # TODO: the event is now triggered by the name not the index
322
330
  self._backdrop_change_triggers: List[Event] = []
323
331
 
324
332
  self._top_edge: Sprite
@@ -627,8 +635,8 @@ class Game:
627
635
  # Drawing
628
636
 
629
637
  #self._screen.fill((30, 30, 30))
630
- if not (self.__backdrop_index is None):
631
- self._screen.blit(self.backdrops[self.__backdrop_index], (0, 0))
638
+ if not (self.__backdrop_key is None):
639
+ self._screen.blit(self.backdrops_by_key[self.__backdrop_key], (0, 0))
632
640
  else:
633
641
  self._screen.fill((255,255,255))
634
642
  helper._draw_guide_lines(self._screen, guide_lines_font, 100, 500)
@@ -724,6 +732,9 @@ class Game:
724
732
  self._space.gravity = xy
725
733
 
726
734
  def _new_sprite_of_file(self, caller_file):
735
+ """
736
+ return a index of the sprite created in the file
737
+ """
727
738
  if not caller_file in self._sprite_count_per_file:
728
739
  self._sprite_count_per_file[caller_file] = 0
729
740
  else:
@@ -732,16 +743,17 @@ class Game:
732
743
  return self._sprite_count_per_file[caller_file]
733
744
 
734
745
 
735
- def _add_sprite(self, sprite: Sprite, to_show=True, caller_file=None):
746
+ def _add_sprite(self, sprite: Sprite, caller_file=None):
736
747
 
737
748
  self._all_sprites.add(sprite)
738
749
  if len(self._all_sprites) > self.max_number_sprite:
739
750
  raise RuntimeError('Reached the maximum number sprite. ')
740
751
  #self._space.add(sprite.body, sprite.shape)
741
752
  self._sprite_click_trigger[sprite] = []
742
- if to_show:
743
- self._all_sprites_to_show.add(sprite)
744
- sprite.update()
753
+ # if to_show:
754
+ # sprite.show()
755
+ #self._all_sprites_to_show.add(sprite)
756
+ #sprite.update()
745
757
 
746
758
  if self.__started_interactive:
747
759
  sprite.set_draggable(True)
@@ -784,16 +796,12 @@ class Game:
784
796
  def _show_sprite(self, sprite: Sprite):
785
797
  """
786
798
  Show the sprite.
787
-
788
- You can use the alias `sprite.show()` to do the same.
789
799
  """
790
800
  self._all_sprites_to_show.add(sprite)
791
801
 
792
802
  def _hide_sprite(self, sprite: Sprite):
793
803
  """
794
804
  Hide the sprite.
795
-
796
- You can use the alias `sprite.hide()` to do the same.
797
805
  """
798
806
  self._all_sprites_to_show.remove(sprite)
799
807
 
@@ -831,6 +839,7 @@ class Game:
831
839
  """
832
840
  self._all_sprites_to_show.get_layer_of_sprite(sprite)
833
841
 
842
+ @deprecated("use add_backdrop")
834
843
  def set_backdrops(self, images: List[pygame.Surface]):
835
844
  """
836
845
  Set the list of all available backdrops. This function is meant to be run before the game start.
@@ -849,32 +858,63 @@ class Game:
849
858
  pysc.game.switch_backdrop(1)
850
859
  ```
851
860
  """
852
- self.backdrops = images
853
-
861
+ for idx, img in enumerate(images):
862
+ self.add_backdrop(str(idx), img)
863
+
864
+ def add_backdrop(self, key, image: pygame.Surface):
865
+ """
866
+ Add the image as a backdrop, and index it with the key so it can be switched to using switch_backdrop
867
+
868
+ Example:
869
+ ```python
870
+ bg0 = pysc.load_image("assets/undersea_bg.png")'
871
+
872
+ game.add_backdrop('background0', bg0)
873
+ game.switch_backdrop('background0')
874
+ ```
875
+
876
+ """
877
+ assert not key in self.backdrops_by_key, f"the name '{key}' is already in used"
878
+ self.backdrop_keys.append(key)
879
+ self.backdrops_by_key[key] = image
880
+ self.backdrop_indices_by_key[key] = len(self.backdrop_keys) - 1 # minus one since the new one is added in the previous line
881
+
882
+
854
883
  @property
855
884
  def backdrop_index(self):
856
885
  """
857
- The index of the current backdrops. For example, if you do `game.switch_backdrop(0)`, `game.backdrop_index` would be `0`.
886
+ The index of the current backdrops.
858
887
  """
859
888
  return self.__backdrop_index
889
+
860
890
 
861
- def switch_backdrop(self, index:Optional[int]=None):
891
+ @property
892
+ def backdrop_key(self):
893
+ """
894
+ The key (i.e. name) of the current backdrops.
895
+ """
896
+ return self.__backdrop_key
897
+
898
+ def switch_backdrop(self, key:Optional[str]=None):
862
899
  """
863
900
  Change the backdrop by specifying the index of the backdrop.
864
901
  """
865
902
 
866
- if index != self.__backdrop_index:
867
- self.__backdrop_index = index
903
+ if key != self.__backdrop_key:
904
+ self.__backdrop_key = key
905
+ self.__backdrop_index = None if key is None else self.backdrop_indices_by_key[key]
868
906
  for t in self._backdrop_change_triggers:
869
- t.trigger(index)
870
- self._specific_backdrop_event_emitter.on_event(self.__backdrop_index)
907
+ t.trigger(key)
908
+ self._specific_backdrop_event_emitter.on_event(key)
871
909
 
910
+ # TODO: testing needed
872
911
  def next_backdrop(self):
873
912
  """
874
913
  Switch to the next backdrop.
875
914
  """
876
915
  if not self.__backdrop_index is None:
877
- self.switch_backdrop((self.__backdrop_index+1) % len(self.backdrops))
916
+ idx = (self.__backdrop_index+1) % len(self.backdrops_by_key)
917
+ self.switch_backdrop(self.backdrop_keys[idx])
878
918
 
879
919
  # all events
880
920
 
@@ -1026,19 +1066,19 @@ class Game:
1026
1066
  t = _declare_callback_type(t, sample_callback)
1027
1067
  return t
1028
1068
 
1029
-
1030
- def when_backdrop_switched(self, backdrop_index, associated_sprites : Iterable[Sprite]=[]) -> Event[[]]:
1069
+ # TODO: testing needed
1070
+ def when_backdrop_switched(self, backdrop_key: str, associated_sprites : Iterable[Sprite]=[]) -> Event[[]]:
1031
1071
  """
1032
1072
  It is recommended to use the `Sprite.when_backdrop_switched` alias instead of this method,
1033
1073
  so you don't need to specify the `associated_sprites` in every event.
1034
1074
 
1035
- Returns an `Event` that is triggered when the game is switched to a backdrop at `backdrop_index`.
1075
+ Returns an `Event` that is triggered when the game is switched to a backdrop with the key `backdrop_key`.
1036
1076
 
1037
1077
  The event handler does not take in any parameter.
1038
1078
 
1039
1079
  Parameters
1040
1080
  ---
1041
- backdrop_index: int
1081
+ backdrop_key: str
1042
1082
  The index of the backdrop
1043
1083
 
1044
1084
  associated_sprites: List[Sprite]
@@ -1053,10 +1093,11 @@ class Game:
1053
1093
  return
1054
1094
  t = _declare_callback_type(t, sample_callback)
1055
1095
 
1056
- self._specific_backdrop_event_emitter.add_event(backdrop_index, t)
1096
+ self._specific_backdrop_event_emitter.add_event(backdrop_key, t)
1057
1097
  return t
1058
-
1059
- def when_any_backdrop_switched(self, associated_sprites : Iterable[Sprite]=[]) -> Event[[int]]:
1098
+
1099
+ # TODO: testing needed
1100
+ def when_any_backdrop_switched(self, associated_sprites : Iterable[Sprite]=[]) -> Event[[Union[str,None]]]:
1060
1101
  """
1061
1102
  It is recommended to use the `Sprite.when_any_backdrop_switched` alias instead of this method,
1062
1103
  so you don't need to specify the `associated_sprites` in every event.
@@ -1064,7 +1105,7 @@ class Game:
1064
1105
  Returns an `Event` that is triggered when the backdrop is switched.
1065
1106
 
1066
1107
  The event handler have to take one parameter:
1067
- - **idx** (int): The index of the new backdrop
1108
+ - **str** (str): The key of the new backdrop
1068
1109
 
1069
1110
  Parameters
1070
1111
  ---
@@ -1075,7 +1116,7 @@ class Game:
1075
1116
  t = self._create_event(associated_sprites)
1076
1117
  self._backdrop_change_triggers.append(t)
1077
1118
  if TYPE_CHECKING:
1078
- def sample_callback(idx: int)-> Any:
1119
+ def sample_callback(key: Union[str, None])-> Any:
1079
1120
  return
1080
1121
  t = _declare_callback_type(t, sample_callback)
1081
1122
 
pyscratch/sprite.py CHANGED
@@ -165,7 +165,7 @@ def create_single_costume_sprite(image_path, *args, **kwargs):
165
165
  return Sprite(frame_dict, "always", *args, **kwargs)
166
166
 
167
167
 
168
- def create_shared_data_display_sprite(key, font, size = (150, 50), bg_colour=(127, 127, 127), text_colour=(255,255,255), position: Optional[Tuple[float, float]]=None, update_period=0.1, **kwargs):
168
+ def create_shared_data_display_sprite(key, font:Optional[pygame.font.Font]=None, size = (150, 50), bg_colour=(127, 127, 127), text_colour=(255,255,255), position: Optional[Tuple[float, float]]=None, update_period=0.1, **kwargs):
169
169
  """
170
170
  Create a display for a variable inside shared_data given the dictionary key (i.e. the name of the variable).
171
171
  The variable display will update every `update_period` seconds.
@@ -191,8 +191,9 @@ def create_shared_data_display_sprite(key, font, size = (150, 50), bg_colour=(12
191
191
  ---
192
192
  key: str
193
193
  The dictionary key of the variable in `game.shared_data` that you want to display.
194
- font: pygame.font.Font
194
+ font: None or pygame.font.Font
195
195
  The pygame font object. Refer to the website of pygame for more details.
196
+ If None, a default font will be used.
196
197
  size: Tuple[float, float]
197
198
  The size of the display panel
198
199
  bg_colour: Tuple[int, int, int] or Tuple[int, int, int, int]
@@ -207,6 +208,9 @@ def create_shared_data_display_sprite(key, font, size = (150, 50), bg_colour=(12
207
208
  Whatever the `Sprite` constructor takes, except `frame_dict`,`starting_animation` & `position`
208
209
  """
209
210
 
211
+ if font is None:
212
+ font = pygame.font.Font(None, 36)
213
+
210
214
  w, h = size
211
215
  if position is None:
212
216
  position = w/2+25, h/2+25
@@ -713,7 +717,17 @@ class Sprite(pygame.sprite.Sprite):
713
717
  if not caller_file == this_file:
714
718
  break
715
719
 
720
+
721
+ self._intend_to_show = True
722
+ self._shown = False
723
+ self.hide()
724
+
716
725
  count = game._add_sprite(self, caller_file=caller_file)
726
+
727
+ self.update()
728
+ self.show()
729
+
730
+
717
731
  self.identifier: str
718
732
  """
719
733
  An identifier of the sprite for loading sprite states (position and direction).
@@ -760,8 +774,10 @@ class Sprite(pygame.sprite.Sprite):
760
774
 
761
775
  x, y = self._body.position
762
776
  self.image, self.rect, self.mask = self._drawing_manager.on_update(x, y, self.__direction.angle_degrees)
763
-
777
+ self._shown = self._intend_to_show
778
+
764
779
  self._physics_manager.on_update(self.image)
780
+
765
781
 
766
782
  if self.__is_dragging:
767
783
  self._body.velocity=0,0
@@ -1364,12 +1380,17 @@ class Sprite(pygame.sprite.Sprite):
1364
1380
  ```
1365
1381
  """
1366
1382
 
1367
- if not self in game._all_sprites_to_show:
1368
- return False
1383
+ # if not self in game._all_sprites_to_show:
1384
+ # return False
1385
+
1386
+ # if not other_sprite in game._all_sprites_to_show:
1387
+ # return False
1369
1388
 
1370
- if not other_sprite in game._all_sprites_to_show:
1389
+ if not self._shown:
1390
+ return False
1391
+
1392
+ if not other_sprite._shown:
1371
1393
  return False
1372
-
1373
1394
 
1374
1395
  if not pygame.sprite.collide_rect(self, other_sprite):
1375
1396
  return False
@@ -1380,6 +1401,9 @@ class Sprite(pygame.sprite.Sprite):
1380
1401
  """
1381
1402
  Returns whether or not this sprite is touching the mouse
1382
1403
  """
1404
+ if not self._shown:
1405
+ return False
1406
+
1383
1407
  mos_x, mos_y = pygame.mouse.get_pos()
1384
1408
 
1385
1409
  if not self.rect.collidepoint((mos_x, mos_y)):
@@ -1411,12 +1435,17 @@ class Sprite(pygame.sprite.Sprite):
1411
1435
  The hidden sprite is still in the space but it cannot touch another sprites
1412
1436
  """
1413
1437
  game._hide_sprite(self)
1438
+ self._shown = False
1439
+ self._intend_to_show = False
1414
1440
 
1415
1441
  def show(self):
1416
1442
  """
1417
1443
  Shows the sprite.
1418
1444
  """
1419
1445
  game._show_sprite(self)
1446
+ self._intend_to_show = True
1447
+ # self._shown is set to True only during the update
1448
+
1420
1449
 
1421
1450
  @override
1422
1451
  def remove(self, *_):
@@ -1430,7 +1459,8 @@ class Sprite(pygame.sprite.Sprite):
1430
1459
  my_sprite.remove()
1431
1460
  ```
1432
1461
  """
1433
- game._remove_sprite(self)
1462
+ self.hide() # prevent collision
1463
+ game._remove_sprite(self)
1434
1464
  self.__removed = True
1435
1465
 
1436
1466
 
@@ -1455,8 +1485,10 @@ class Sprite(pygame.sprite.Sprite):
1455
1485
  shape_size_factor = self._physics_manager.shape_size_factor,
1456
1486
  body_type = self._body.body_type,
1457
1487
  )
1458
- if not self in game._all_sprites_to_show:
1459
- game._hide_sprite(sprite)
1488
+ if not self._intend_to_show:
1489
+ sprite.hide()
1490
+ else:
1491
+ sprite.show()
1460
1492
 
1461
1493
  if self.__rotation_style == _RotationStyle.LEFTRIGHT:
1462
1494
  sprite.set_rotation_style_left_right()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyscratch-pysc
3
- Version: 1.0.3
3
+ Version: 2.0.0
4
4
  Summary: A Python game development framework designed to provide an easy transitioning from Scratch to Python
5
5
  Author-email: Daniel Ka-Wa Chan <kwdaniel525@protonmail.com>
6
6
  License: MIT
@@ -22,10 +22,15 @@ For more information, see: https://kwdchan.github.io/pyscratch/
22
22
 
23
23
 
24
24
 
25
+ ## Change History
26
+ ### 12 Oct 2025
27
+ **v2.0.0**
28
+ The backdrops are now indexed by keys instead of integers
25
29
 
26
30
 
27
-
28
- ## Change History
31
+ ### 12 Sep 2025
32
+ **v1.0.4**
33
+ Fixed the show/hide collision related problem due to the deferral of movement to the frame update.
29
34
 
30
35
  ### 07 Sep 2025
31
36
  **v1.0.3**