batframework 1.0.9a11__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. batFramework/__init__.py +52 -76
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +114 -56
  5. batFramework/audioManager.py +36 -82
  6. batFramework/camera.py +69 -263
  7. batFramework/constants.py +53 -29
  8. batFramework/cutscene.py +109 -243
  9. batFramework/cutsceneBlocks.py +176 -0
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -16
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +85 -92
  14. batFramework/gui/__init__.py +3 -14
  15. batFramework/gui/button.py +78 -12
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +31 -188
  18. batFramework/gui/debugger.py +43 -126
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -55
  21. batFramework/gui/indicator.py +22 -95
  22. batFramework/gui/interactiveWidget.py +12 -229
  23. batFramework/gui/label.py +77 -311
  24. batFramework/gui/layout.py +66 -414
  25. batFramework/gui/root.py +35 -203
  26. batFramework/gui/shape.py +57 -247
  27. batFramework/gui/toggle.py +48 -114
  28. batFramework/gui/widget.py +243 -457
  29. batFramework/manager.py +29 -113
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +217 -22
  32. batFramework/sceneManager.py +129 -161
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +75 -0
  35. batFramework/transition.py +124 -129
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +4 -4
  38. batFramework/utils.py +144 -266
  39. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/METADATA +24 -22
  40. batframework-1.1.0.dist-info/RECORD +43 -0
  41. batFramework/animation.py +0 -77
  42. batFramework/baseScene.py +0 -240
  43. batFramework/cutsceneManager.py +0 -34
  44. batFramework/drawable.py +0 -77
  45. batFramework/easingController.py +0 -58
  46. batFramework/enums.py +0 -135
  47. batFramework/fontManager.py +0 -65
  48. batFramework/gui/animatedLabel.py +0 -89
  49. batFramework/gui/clickableWidget.py +0 -244
  50. batFramework/gui/constraints/__init__.py +0 -1
  51. batFramework/gui/constraints/constraints.py +0 -980
  52. batFramework/gui/draggableWidget.py +0 -44
  53. batFramework/gui/meter.py +0 -96
  54. batFramework/gui/radioButton.py +0 -35
  55. batFramework/gui/selector.py +0 -250
  56. batFramework/gui/slider.py +0 -397
  57. batFramework/gui/style.py +0 -10
  58. batFramework/gui/styleManager.py +0 -54
  59. batFramework/gui/syncedVar.py +0 -49
  60. batFramework/gui/textInput.py +0 -306
  61. batFramework/gui/tooltip.py +0 -30
  62. batFramework/particle.py +0 -118
  63. batFramework/propertyEaser.py +0 -79
  64. batFramework/renderGroup.py +0 -34
  65. batFramework/resourceManager.py +0 -130
  66. batFramework/sceneLayer.py +0 -138
  67. batFramework/scrollingSprite.py +0 -115
  68. batFramework/sprite.py +0 -51
  69. batFramework/templates/__init__.py +0 -1
  70. batFramework/templates/controller.py +0 -97
  71. batFramework/tileset.py +0 -46
  72. batFramework/timeManager.py +0 -213
  73. batframework-1.0.9a11.dist-info/RECORD +0 -67
  74. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/LICENSE +0 -0
  75. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/WHEEL +0 -0
  76. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/top_level.txt +0 -0
@@ -1,59 +1,117 @@
1
1
  import batFramework as bf
2
2
  import pygame
3
- from typing import List, Dict, Tuple, Union, Optional, Self, Callable, Any
4
- from .animation import Animation
5
-
6
- class AnimatedSprite(bf.Drawable):
7
- def __init__(self,*args,**kwargs) -> None:
8
- super().__init__(None, no_surface=True,*args,**kwargs)
9
- self.animations : dict[str,Animation] = {}
10
- self.counter = 0 # int counter
11
- self._fcounter = 0.0 # counter
12
- self.current_animation : str = None
13
- self.end_callback : Callable[[],Any] = None
14
- self._flipX : bool = False
15
-
16
- @property
17
- def flipX(self)->bool:
18
- return self._flipX
19
-
20
- @flipX.setter
21
- def flipX(self,value:bool):
22
- self._flipX = value
23
-
24
- def set_end_callback(self,callback : Callable[[],Any]):
25
- self.end_callback = callback
26
-
27
- def add_animation(self,name:str,animation:Animation)->Self:
28
- self.animations[name] = animation
29
- if self.rect.size == (0,0):
30
- self.rect.size = animation.frames[0].get_size()
31
- return self
32
-
33
- def set_animation(self,name:str,reset_counter:bool=True):
34
- if name not in self.animations :
35
- raise ValueError
36
- self.current_animation = name
37
- if reset_counter:
38
- self._fcounter = 0
39
-
40
- def get_current_frame(self)->int|None:
41
- if not self.current_animation:
42
- return None
43
- return self.animations[self.current_animation].counter_to_frame(self._fcounter)
44
-
45
- def update(self, dt):
46
- super().update(dt)
47
- if not self.current_animation:
3
+
4
+
5
+
6
+ def search_index(target, lst):
7
+ cumulative_sum = 0
8
+ for index, value in enumerate(lst):
9
+ cumulative_sum += value
10
+ if cumulative_sum >= target:
11
+ return index
12
+ return -1
13
+
14
+
15
+ class AnimState:
16
+ def __init__(self, file, width, height, frame_length_list:list|int) -> None:
17
+ self.frames: list[pygame.Surface] = bf.utils.img_slice(file, width, height)
18
+ self.frames_flipX: list[pygame.Surface] = bf.utils.img_slice(
19
+ file, width, height, True
20
+ )
21
+
22
+ self.frame_length_list = []
23
+ self.ffl_length = 0
24
+ self.set_frame_length_list(frame_length_list)
25
+
26
+ def get_frame_index(self, counter:float|int):
27
+ return search_index(int(counter % self.ffl_length), self.frame_length_list)
28
+
29
+ def get_frame(self, counter, flip):
30
+ i = self.get_frame_index(counter)
31
+ return self.frames_flipX[i] if flip else self.frames[i]
32
+
33
+ def set_frame_length_list(self,frame_length_list:list[int]|int):
34
+ if isinstance(frame_length_list,int):
35
+ frame_length_list = [frame_length_list] * len(self.frames)
36
+ if len(frame_length_list) != len(self.frames) :
37
+ raise ValueError("frame_length_list should have values for all frames")
38
+ self.frame_length_list = frame_length_list
39
+ self.ffl_length = sum(self.frame_length_list)
40
+
41
+
42
+ class AnimatedSprite(bf.DynamicEntity):
43
+ def __init__(self, size=None) -> None:
44
+ super().__init__(size, no_surface=True)
45
+ self.float_counter = 0
46
+ self.animStates: dict[str, AnimState] = {}
47
+ self.current_animState :str = ""
48
+ self.flipX = False
49
+ self._locked = False
50
+
51
+ def set_counter(self,value:float):
52
+ self.float_counter = value
53
+
54
+
55
+ def lock_animState(self):
56
+ self._locked = True
57
+
58
+ def unlock_animState(self):
59
+ self._locked = False
60
+
61
+ def set_flipX(self, value):
62
+ self.flipX = value
63
+
64
+ def remove_animState(self, name:str):
65
+ if not name in self.animStates :return
66
+ self.animStates.pop(name)
67
+ if self.current_animState == name : self.current_animState = list(self.animStates.keys())[0] if self.animStates else ""
68
+
69
+ def add_animState(
70
+ self, name: str, file: str, size: tuple[int, int], frame_length_list: list[int]
71
+ ):
72
+ if name in self.animStates:
48
73
  return
49
- self._fcounter += dt
50
- self.counter = int(self._fcounter)
51
- if self.counter >= self.animations[self.current_animation].numFrames:
52
- if self.end_callback:
53
- self.end_callback()
54
-
55
-
56
- def draw(self, camera):
57
- self.surface.blit(self.animations[self.current_animation].get_frame(self.counter,self.flipX),(0,0))
58
- super().draw(camera)
59
-
74
+ self.animStates[name] = AnimState(file, *size, frame_length_list)
75
+ if len(self.animStates) == 1 : self.set_animState(name)
76
+
77
+ def set_animState(self, state:str, reset_counter=True, lock=False):
78
+ if state not in self.animStates or self._locked:
79
+ return False
80
+ self.current_animState = state
81
+ self.rect = (
82
+ self.animStates[self.current_animState]
83
+ .frames[0]
84
+ .get_frect(center=self.rect.center)
85
+ )
86
+ if reset_counter or self.float_counter > sum(
87
+ self.get_state().frame_length_list
88
+ ):
89
+ self.float_counter = 0
90
+ if lock:
91
+ self.lock_animState()
92
+ return True
93
+
94
+ def get_state(self):
95
+ return self.animStates.get(self.current_animState,None)
96
+
97
+ def get_frame_index(self):
98
+ return self.animStates[self.current_animState].get_frame_index(
99
+ self.float_counter
100
+ )
101
+
102
+ def update(self, dt: float):
103
+ if not self.animStates : return
104
+ self.float_counter += 60 * dt
105
+ if self.float_counter > self.get_state().ffl_length:
106
+ self.float_counter = 0
107
+ self.do_update(dt)
108
+
109
+ def draw(self, camera: bf.Camera) -> bool:
110
+ if not self.visible or not camera.intersects(self.rect) or not self.animStates:
111
+ return False
112
+ # pygame.draw.rect(camera.surface,"purple",camera.transpose(self.rect).move(2,2))
113
+ camera.surface.blit(
114
+ self.get_state().get_frame(self.float_counter, self.flipX),
115
+ camera.transpose(self.rect),
116
+ )
117
+ return True
@@ -1,53 +1,43 @@
1
1
  import batFramework as bf
2
2
  import pygame
3
3
 
4
-
4
+ pygame.mixer.init()
5
5
 
6
6
 
7
7
  class AudioManager(metaclass=bf.Singleton):
8
- def __init__(self) -> None:
9
- self.sounds: dict = {}
10
- self.musics: dict = {}
11
- self.current_music: str | None = None
12
- self.music_volume: float = 1
13
- self.sound_volume: float = 1
14
- pygame.mixer.music.set_endevent(bf.const.MUSIC_END_EVENT)
15
-
16
- def free_sounds(self, force: bool = False):
8
+ def __init__(self):
9
+ self.sounds: dict[str : dict[str, pygame.mixer.Sound, bool]] = {}
10
+ self.musics: dict[str:str] = {}
11
+ self.current_music = None
12
+ self.music_volume = 1
13
+ self.sound_volume = 1
14
+ pygame.mixer_music.set_endevent(bf.const.MUSIC_END_EVENT)
15
+
16
+ def free_sounds(self, force=False):
17
17
  if force:
18
18
  self.sounds = {}
19
19
  return
20
- self.sounds: dict = {
21
- key: value for key, value in self.sounds.items() if value["persistent"]
22
- }
20
+ to_remove = []
21
+ for name, data in self.sounds.items():
22
+ if not data["persistent"]:
23
+ to_remove.append(name)
23
24
 
24
- def free_music(self):
25
- if self.current_music:
26
- pygame.mixer.music.unload(self.current_music)
25
+ _ = [self.sounds.pop(i) for i in to_remove]
27
26
 
28
27
  def set_sound_volume(self, volume: float):
29
28
  self.sound_volume = volume
30
29
 
31
30
  def set_music_volume(self, volume: float):
32
31
  self.music_volume = volume
33
- pygame.mixer.music.set_volume(volume)
34
-
35
- def get_music_volume(self) -> float:
36
- return self.music_volume
37
-
38
- def get_sound_volume(self) -> float:
39
- return self.sound_volume
32
+ pygame.mixer_music.set_volume(volume)
40
33
 
41
- def has_sound(self, name: str):
34
+ def has_sound(self, name):
42
35
  return name in self.sounds
43
36
 
44
37
  def load_sound(self, name, path, persistent=False) -> pygame.mixer.Sound:
45
- """
46
- if persistent==True the sound won't be unloaded when sounds are freed (unless force is used)
47
- """
48
38
  if name in self.sounds:
49
39
  return self.sounds[name]["sound"]
50
- path = bf.ResourceManager().get_path(path)
40
+ path = bf.utils.get_path(path)
51
41
  self.sounds[name] = {
52
42
  "path": path,
53
43
  "sound": pygame.mixer.Sound(path),
@@ -55,77 +45,41 @@ class AudioManager(metaclass=bf.Singleton):
55
45
  }
56
46
  return self.sounds[name]["sound"]
57
47
 
58
- def load_sounds(self, sound_data: tuple[str, str, bool]) -> None:
59
- for data in sound_data:
60
- self.load_sound(*data)
61
- return
62
-
63
- def play_sound(self, name, volume=1) -> bool:
64
- """
65
- Play the sound file with the given name.
66
- returns True if the sound was played
67
-
68
- """
69
- try:
70
- self.sounds[name]["sound"].set_volume(volume * self.sound_volume)
71
- self.sounds[name]["sound"].play()
72
- return True
73
- except KeyError:
74
- print(f"Sound '{name}' not loaded in AudioManager.")
75
- return False
76
-
77
- def stop_sound(self, name) -> bool:
78
- try:
48
+ def play_sound(self, name, volume=1):
49
+ self.sounds[name]["sound"].set_volume(volume * self.sound_volume)
50
+ self.sounds[name]["sound"].play()
51
+
52
+ def stop_sound(self, name):
53
+ if name in self.sounds:
79
54
  self.sounds[name]["sound"].stop()
80
- return True
81
- except KeyError:
82
- return False
83
- print(f"Sound '{name}' not loaded in AudioManager.")
84
55
 
85
56
  def load_music(self, name, path):
86
- self.musics[name] = bf.ResourceManager().get_path(path)
87
- return
88
-
89
- def load_musics(self, *music_data:tuple[str, str]):
90
- for data in music_data:
91
- self.load_music(*data)
92
- return
93
-
94
- def play_music(self, name, loop=0, fade=500) -> bool:
95
- """
96
- Play the sound file with the given 'name'.
97
- Fades with the given 'fade' time in ms.
98
- Music will loop 'loop' times (indefinitely if -1).
99
- returns True if the sound was played
100
- """
101
- try:
102
- pygame.mixer.music.load(self.musics[name])
103
- pygame.mixer.music.play(loop, fade_ms=fade)
57
+ self.musics[name] = bf.utils.get_path(path)
58
+
59
+ def play_music(self, name, loop=0, fade=500):
60
+ if name in self.musics:
61
+ pygame.mixer_music.load(self.musics[name])
62
+ pygame.mixer_music.play(loop, fade_ms=fade)
104
63
  self.current_music = name
105
- return True
106
- except KeyError:
107
- print(f"Music '{name}' not loaded in AudioManager.")
108
- return False
64
+ else:
65
+ print(f"Music '{name}' not found in AudioManager.")
109
66
 
110
67
  def stop_music(self):
111
68
  if not self.current_music:
112
69
  return
113
- pygame.mixer.music.stop()
70
+ pygame.mixer_music.stop()
114
71
 
115
72
  def fadeout_music(self, fade_ms: int):
116
73
  if not self.current_music:
117
74
  return
118
- pygame.mixer.music.fadeout(fade_ms)
75
+ pygame.mixer_music.fadeout(fade_ms)
119
76
 
120
77
  def pause_music(self):
121
78
  if not self.current_music:
122
79
  return
123
- pygame.mixer.music.pause()
80
+ pygame.mixer_music.pause()
124
81
 
125
82
  def resume_music(self):
126
83
  if not self.current_music:
127
84
  return
128
- pygame.mixer.music.unpause()
129
-
130
- def get_current_music(self) -> str | None:
131
- return self.current_music
85
+ pygame.mixer_music.unpause()