batframework 1.0.7__py3-none-any.whl → 1.0.8a2__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 (51) hide show
  1. batFramework/__init__.py +47 -41
  2. batFramework/action.py +20 -42
  3. batFramework/actionContainer.py +4 -43
  4. batFramework/animatedSprite.py +65 -98
  5. batFramework/audioManager.py +25 -39
  6. batFramework/camera.py +56 -226
  7. batFramework/constants.py +48 -32
  8. batFramework/cutscene.py +24 -32
  9. batFramework/cutsceneBlocks.py +33 -30
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +7 -8
  12. batFramework/easing.py +23 -28
  13. batFramework/entity.py +52 -89
  14. batFramework/gui/__init__.py +1 -3
  15. batFramework/gui/button.py +58 -124
  16. batFramework/gui/constraints.py +90 -163
  17. batFramework/gui/container.py +18 -29
  18. batFramework/gui/debugger.py +42 -106
  19. batFramework/gui/frame.py +9 -15
  20. batFramework/gui/image.py +17 -36
  21. batFramework/gui/indicator.py +14 -20
  22. batFramework/gui/interactiveWidget.py +12 -63
  23. batFramework/gui/label.py +50 -113
  24. batFramework/gui/layout.py +51 -66
  25. batFramework/gui/root.py +29 -70
  26. batFramework/gui/shape.py +41 -34
  27. batFramework/gui/toggle.py +29 -37
  28. batFramework/gui/widget.py +131 -174
  29. batFramework/manager.py +14 -21
  30. batFramework/particles.py +20 -41
  31. batFramework/scene.py +72 -173
  32. batFramework/sceneManager.py +80 -40
  33. batFramework/stateMachine.py +0 -1
  34. batFramework/time.py +51 -62
  35. batFramework/transition.py +154 -0
  36. batFramework/utils.py +150 -3
  37. batframework-1.0.8a2.dist-info/METADATA +58 -0
  38. batframework-1.0.8a2.dist-info/RECORD +42 -0
  39. {batframework-1.0.7.dist-info → batframework-1.0.8a2.dist-info}/WHEEL +1 -1
  40. batFramework/enums.py +0 -14
  41. batFramework/fontManager.py +0 -57
  42. batFramework/gui/dialogueBox.py +0 -70
  43. batFramework/gui/slider.py +0 -5
  44. batFramework/gui/textInput.py +0 -88
  45. batFramework/resourceManager.py +0 -72
  46. batFramework/sprite.py +0 -33
  47. batFramework/tileset.py +0 -64
  48. batframework-1.0.7.dist-info/LICENCE +0 -21
  49. batframework-1.0.7.dist-info/METADATA +0 -55
  50. batframework-1.0.7.dist-info/RECORD +0 -50
  51. {batframework-1.0.7.dist-info → batframework-1.0.8a2.dist-info}/top_level.txt +0 -0
batFramework/__init__.py CHANGED
@@ -1,60 +1,66 @@
1
1
  import pygame
2
- import batFramework as bf
3
- import sys
4
2
  from .constants import Constants as const
3
+ import os
4
+ import json
5
+ initialized = False
6
+
7
+ def init(
8
+ resolution:tuple[int,int],
9
+ flags:int=0,
10
+ vsync:int = 0,
11
+ default_text_size=None,
12
+ default_font=None,
13
+ resource_path:str|None=None,
14
+ window_title:str="BatFramework Project",
15
+ fps_limit : int = 0
16
+ ):
17
+ global initialized
18
+ if not initialized:
19
+ pygame.init()
20
+ pygame.display.set_caption(window_title)
21
+
22
+ # Initialize display
23
+ const.init_screen(resolution,flags,vsync)
24
+ const.set_fps_limit(fps_limit)
25
+
26
+ # Initialize default text size
27
+ if default_text_size: const.set_default_text_size(default_text_size)
28
+ # Initialize resource path for game data
29
+ if resource_path: const.set_resource_path(resource_path)
30
+
31
+ # Initialize default font cache
32
+ from .utils import Utils
33
+ if default_font is None or isinstance(default_font,str):
34
+ Utils.init_font(default_font)
35
+ else:
36
+ raise ValueError(f"default_font '{default_font}' can be either string or None")
37
+
38
+ f = list(Utils.FONTS[None].values())[0]
39
+ print(f"Set default font to : {f.name} {'' if default_font is not None else '(default value)'}")
40
+ initialized = True
41
+
5
42
  from .constants import Colors as color
43
+ from .constants import Axis as axis
6
44
  from .utils import Singleton
7
- from .enums import *
8
- from .resourceManager import ResourceManager
9
- from .fontManager import FontManager
10
45
  from .utils import Utils as utils
11
- from .tileset import Tileset
12
- from .time import TimeManager, Timer
13
- from .cutscene import Cutscene, CutsceneManager
46
+ from .time import Time, Timer
47
+ from .cutscene import Cutscene,CutsceneManager
14
48
  from .cutsceneBlocks import *
15
49
  from .easing import Easing, EasingAnimation
16
50
  from .audioManager import AudioManager
17
- import batFramework.transition as transition
51
+ from .utils import Layout, Alignment, Direction
52
+ from .transition import *
18
53
  from .action import Action
19
- from .actionContainer import *
54
+ from .actionContainer import ActionContainer
20
55
  from .camera import Camera
21
56
  from .entity import Entity
22
57
  from .dynamicEntity import DynamicEntity
23
- from .sprite import Sprite
24
58
  from .animatedSprite import AnimatedSprite, AnimState
25
59
  from .stateMachine import State, StateMachine
60
+ from .particles import Particle, ParticleManager
61
+ # from .debugger import Debugger
26
62
  from .scene import Scene
27
63
  from .gui import *
28
64
  from .sceneManager import SceneManager
29
65
  from .manager import Manager
30
66
 
31
-
32
- def init_screen(resolution: tuple[int, int], flags: int = 0, vsync: int = 0):
33
- const.RESOLUTION = resolution
34
- const.FLAGS = flags
35
- const.VSYNC = vsync
36
- const.SCREEN = pygame.display.set_mode(
37
- const.RESOLUTION,const.FLAGS, vsync=const.VSYNC
38
- )
39
- print(
40
- f"Window : {resolution[0]}x{resolution[1]} [vsync:{pygame.display.is_vsync()}]"
41
- )
42
-
43
- def init(
44
- resolution: tuple[int, int],
45
- flags: int = 0,
46
- vsync: int = 0,
47
- default_text_size=None,
48
- default_font=None,
49
- resource_path: str | None = None,
50
- window_title: str = "BatFramework Project",
51
- fps_limit: int = 0):
52
- pygame.display.set_caption(window_title)
53
- init_screen(resolution,flags,vsync)
54
-
55
- ResourceManager().set_resource_path(resource_path if resource_path is not None else ".")
56
- if resource_path is not None : ResourceManager().load_dir(ResourceManager().RESOURCE_PATH)
57
- if default_text_size is not None : FontManager().set_default_text_size(default_text_size)
58
- FontManager().init_font(default_font)
59
- const.BF_INITIALIZED = True
60
- const.set_fps_limit(fps_limit)
batFramework/action.py CHANGED
@@ -12,21 +12,20 @@ class Action:
12
12
  Args:
13
13
  name (str): The name of the action.
14
14
  """
15
- self._name :str= name
16
- self._active :bool= False
17
- self._type :ActionType = ActionType.INSTANTANEOUS
18
- self._key_control : set= set()
19
- self._mouse_control :set = set()
20
- self._gamepad_button_control :set = set()
21
- self._gamepad_axis_control :set = set()
15
+ self._name = name
16
+ self._active = False
17
+ self._type = ActionType.INSTANTANEOUS
18
+ self._key_control = set()
19
+ self._mouse_control = set()
20
+ self._gamepad_button_control = set()
21
+ self._gamepad_axis_control = set()
22
22
  self._holding = set()
23
23
  self._unique = True
24
- self.data: Any = None
24
+ self.data : Any = None
25
25
 
26
26
  def set_unique(self, val: bool) -> None:
27
27
  """
28
28
  Set whether this action is unique (exclusive).
29
- When in an action Container, unique actions -when active - break the propagation of their event to other actions.
30
29
 
31
30
  Args:
32
31
  val (bool): True if the action is unique, False otherwise.
@@ -52,7 +51,7 @@ class Action:
52
51
  self._active = value
53
52
  self._holding = set()
54
53
 
55
- def add_key_control(self, *keys) -> "Action":
54
+ def add_key_control(self, *keys) -> 'Action':
56
55
  """
57
56
  Add key controls to the action.
58
57
 
@@ -65,26 +64,7 @@ class Action:
65
64
  self._key_control.update(keys)
66
65
  return self
67
66
 
68
- def remove_key_control(self, *keys:int) -> "Action":
69
- """
70
- Remove key controls to the action.
71
-
72
- Args:
73
- *keys (int): Key codes to control this action.
74
-
75
- Returns:
76
- Action: The updated Action object for method chaining.
77
- """
78
- self._key_control = self._key_control - set(keys)
79
- return self
80
-
81
- def replace_key_control(self, key, new_key) -> "Action":
82
- if not key in self._key_control : return self
83
- self.remove_key_control(key)
84
- self.add_key_control(new_key)
85
- return self
86
-
87
- def add_mouse_control(self, *mouse_buttons:int) -> "Action":
67
+ def add_mouse_control(self, *mouse_buttons) -> 'Action':
88
68
  """
89
69
  Add mouse control to the action.
90
70
 
@@ -106,7 +86,7 @@ class Action:
106
86
  """
107
87
  return self._name
108
88
 
109
- def set_continuous(self) -> "Action":
89
+ def set_continuous(self) -> 'Action':
110
90
  """
111
91
  Set the action type to continuous.
112
92
 
@@ -126,7 +106,7 @@ class Action:
126
106
  """
127
107
  return self._type == ActionType.CONTINUOUS
128
108
 
129
- def set_instantaneous(self) -> "Action":
109
+ def set_instantaneous(self) -> 'Action':
130
110
  """
131
111
  Set the action type to instantaneous.
132
112
 
@@ -146,7 +126,7 @@ class Action:
146
126
  """
147
127
  return self._type == ActionType.INSTANTANEOUS
148
128
 
149
- def set_holding(self) -> "Action":
129
+ def set_holding(self) -> 'Action':
150
130
  """
151
131
  Set the action type to holding.
152
132
 
@@ -165,14 +145,9 @@ class Action:
165
145
  """
166
146
  return self._type == ActionType.HOLDING
167
147
 
168
- def process_update(self, event: pygame.Event) -> None:
169
- if (
170
- self.is_active()
171
- and event.type == pygame.MOUSEMOTION
172
- and self.is_holding_type()
173
- and pygame.MOUSEMOTION in self._mouse_control
174
- ):
175
- self.data = {"pos": event.pos, "rel": event.rel}
148
+ def process_update(self,event:pygame.Event)->None:
149
+ if self.is_active() and event.type == pygame.MOUSEMOTION and self.is_holding_type() and pygame.MOUSEMOTION in self._mouse_control:
150
+ self.data = {"pos":event.pos,"rel":event.rel}
176
151
 
177
152
  def process_activate(self, event: pygame.event.Event) -> bool:
178
153
  """
@@ -230,7 +205,10 @@ class Action:
230
205
  if not self._holding:
231
206
  self._active = False
232
207
  return True
233
- elif event.type == pygame.MOUSEMOTION and event.type in self._mouse_control:
208
+ elif (
209
+ event.type == pygame.MOUSEMOTION
210
+ and event.type in self._mouse_control
211
+ ):
234
212
  self.value = None
235
213
  if event.type in self._holding:
236
214
  self._holding.remove(event.type)
@@ -1,5 +1,4 @@
1
1
  import batFramework as bf
2
- import pygame
3
2
 
4
3
 
5
4
  class ActionContainer:
@@ -15,20 +14,14 @@ class ActionContainer:
15
14
  for action in actions:
16
15
  self._actions[action.get_name()] = action
17
16
 
18
- def get(self, name: str) -> bf.Action:
17
+ def get(self,name:str)->bf.Action:
19
18
  return self._actions.get(name)
20
19
 
21
- def has_action(self, name: str):
20
+ def has_action(self, name:str):
22
21
  return name in self._actions
23
22
 
24
- def get_all(self) -> list[bf.Action]:
25
- return self._actions
26
-
27
- def is_active(self, *names: str) -> bool:
28
- return all(
29
- self._actions.get(name).is_active() if name in self._actions else False
30
- for name in names
31
- )
23
+ def is_active(self, *names:str)->bool:
24
+ return all(self._actions.get(name).is_active() if name in self._actions else False for name in names)
32
25
 
33
26
  def process_event(self, event):
34
27
  for action in self._actions.values():
@@ -43,35 +36,3 @@ class ActionContainer:
43
36
  def hard_reset(self):
44
37
  for action in self._actions.values():
45
38
  action.hard_reset()
46
-
47
-
48
- class DirectionalKeyControls(ActionContainer):
49
- def __init__(self):
50
- super().__init__(
51
- bf.Action("up").add_key_control(pygame.K_UP).set_holding(),
52
- bf.Action("down").add_key_control(pygame.K_DOWN).set_holding(),
53
- bf.Action("left").add_key_control(pygame.K_LEFT).set_holding(),
54
- bf.Action("right").add_key_control(pygame.K_RIGHT).set_holding(),
55
- )
56
-
57
-
58
- class WASDControls(ActionContainer):
59
- def __init__(self):
60
- super().__init__(
61
- bf.Action("up").add_key_control(pygame.K_w).set_holding(),
62
- bf.Action("down").add_key_control(pygame.K_s).set_holding(),
63
- bf.Action("left").add_key_control(pygame.K_a).set_holding(),
64
- bf.Action("right").add_key_control(pygame.K_d).set_holding(),
65
- )
66
-
67
-
68
- class HybridControls(ActionContainer):
69
- def __init__(self):
70
- super().__init__(
71
- bf.Action("up").add_key_control(pygame.K_UP, pygame.K_w).set_holding(),
72
- bf.Action("down").add_key_control(pygame.K_DOWN, pygame.K_s).set_holding(),
73
- bf.Action("left").add_key_control(pygame.K_LEFT, pygame.K_a).set_holding(),
74
- bf.Action("right")
75
- .add_key_control(pygame.K_RIGHT, pygame.K_r)
76
- .set_holding(),
77
- )
@@ -2,6 +2,7 @@ import batFramework as bf
2
2
  import pygame
3
3
 
4
4
 
5
+
5
6
  def search_index(target, lst):
6
7
  cumulative_sum = 0
7
8
  for index, value in enumerate(lst):
@@ -12,139 +13,105 @@ def search_index(target, lst):
12
13
 
13
14
 
14
15
  class AnimState:
15
- def __init__(
16
- self, name: str, file, width, height, duration_list: list | int,convert_alpha:bool=True
17
- ) -> None:
18
- self.frames: list[pygame.Surface] =bf.utils.img_slice(
19
- file, width, height,
20
- False,convert_alpha
21
- )
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)
22
18
  self.frames_flipX: list[pygame.Surface] = bf.utils.img_slice(
23
- file, width, height,
24
- True,convert_alpha
19
+ file, width, height, True
25
20
  )
26
-
27
- self.name = name
28
- self.duration_list :list[int]= []
29
- self.duration_list_length = 0
30
- self.set_duration_list(duration_list)
31
21
 
32
- def __repr__(self):
33
- return f"AnimState({self.name})"
22
+ self.frame_length_list = []
23
+ self.ffl_length = 0
24
+ self.set_frame_length_list(frame_length_list)
34
25
 
35
- def counter_to_frame(self, counter: float | int)->int:
36
- return search_index(int(counter % self.duration_list_length), self.duration_list)
26
+ def get_frame_index(self, counter:float|int):
27
+ return search_index(int(counter % self.ffl_length), self.frame_length_list)
37
28
 
38
29
  def get_frame(self, counter, flip):
39
- i = self.counter_to_frame(counter)
30
+ i = self.get_frame_index(counter)
40
31
  return self.frames_flipX[i] if flip else self.frames[i]
41
32
 
42
- def set_duration_list(self, duration_list: list[int] | int):
43
- if isinstance(duration_list, int):
44
- duration_list = [duration_list] * len(self.frames)
45
- if len(duration_list) != len(self.frames):
46
- raise ValueError("duration_list should have values for all frames")
47
- self.duration_list = duration_list
48
- self.duration_list_length = sum(self.duration_list)
49
-
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
+
50
41
 
51
42
  class AnimatedSprite(bf.DynamicEntity):
52
43
  def __init__(self, size=None) -> None:
53
44
  super().__init__(size, no_surface=True)
54
- self.float_counter :float= 0
45
+ self.float_counter = 0
55
46
  self.animStates: dict[str, AnimState] = {}
56
- self.current_state: AnimState|None = None
47
+ self.current_animState :str = ""
57
48
  self.flipX = False
58
49
  self._locked = False
59
- self.paused : bool = False
60
-
61
- def pause(self)->None:
62
- self.paused = True
63
-
64
- def resume(self)->None:
65
- self.paused = False
66
50
 
67
- def toggle_pause(self)->None:
68
- self.paused = not self.paused
69
-
70
- def set_counter(self, value: float)->None:
51
+ def set_counter(self,value:float):
71
52
  self.float_counter = value
53
+
72
54
 
73
- def set_frame(self,frame_index:int)->None:
74
- if not self.current_state : return
75
- total = sum(self.current_state.duration_list)
76
- frame_index = max(0,min(total,frame_index))
77
- new_counter = 0
78
- i = 0
79
- while frame_index < total:
80
- if self.current_state.counter_to_frame(new_counter)>=frame_index:
81
- break
82
- new_counter +=self.current_state.duration_list[i]
83
- i+=1
84
- self.set_counter(new_counter)
85
- def lock(self)->None:
55
+ def lock_animState(self):
86
56
  self._locked = True
87
57
 
88
- def unlock(self)->None:
58
+ def unlock_animState(self):
89
59
  self._locked = False
90
60
 
91
- def set_flipX(self, value)->None:
61
+ def set_flipX(self, value):
92
62
  self.flipX = value
93
63
 
94
- def remove_animState(self, name: str)->bool:
95
- if not name in self.animStates:
96
- return False
97
- self.animStates.pop(name)
98
- if self.current_state and self.current_state.name == name:
99
- self.current_animState = (
100
- list(self.animStates.keys())[0] if self.animStates else ""
101
- )
102
- return True
103
-
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
+
104
69
  def add_animState(
105
- self, name: str, file: str, size: tuple[int, int], duration_list: list[int],
106
- convert_alpha:bool=True
107
- )->bool:
70
+ self, name: str, file: str, size: tuple[int, int], frame_length_list: list[int]
71
+ ):
108
72
  if name in self.animStates:
109
- return False
110
- self.animStates[name] = AnimState(name, file, *size, duration_list,convert_alpha)
111
- if len(self.animStates) == 1:
112
- self.set_animState(name)
113
- return True
114
-
115
- def set_animState(self, state: str, reset_counter=True, lock=False)->bool:
73
+ return
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):
116
78
  if state not in self.animStates or self._locked:
117
79
  return False
118
-
119
- animState = self.animStates[state]
120
- self.current_state = animState
121
-
122
- self.rect = (self.current_state.frames[0].get_frect(center=self.rect.center))
123
-
124
- if reset_counter or self.float_counter > sum(animState.duration_list):
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
+ ):
125
89
  self.float_counter = 0
126
90
  if lock:
127
- self.lock()
91
+ self.lock_animState()
128
92
  return True
129
93
 
130
- def get_animState(self)->AnimState|None:
131
- return self.current_state
94
+ def get_state(self):
95
+ return self.animStates.get(self.current_animState,None)
132
96
 
133
- def update(self, dt: float)->None:
134
- s = self.get_animState()
135
- if not self.animStates or s is None :
136
- return
137
- if not self.paused :
138
- self.float_counter += 60 * dt
139
- if self.float_counter > s.duration_list_length:
140
- self.float_counter = 0
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
141
107
  self.do_update(dt)
142
108
 
143
- def draw(self, camera: bf.Camera) -> int:
144
- if not self.visible or not camera.intersects(self.rect) or not self.current_state:
145
- return 0
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))
146
113
  camera.surface.blit(
147
- self.current_state.get_frame(self.float_counter, self.flipX),
114
+ self.get_state().get_frame(self.float_counter, self.flipX),
148
115
  camera.transpose(self.rect),
149
116
  )
150
- return 1
117
+ return True
@@ -5,19 +5,24 @@ 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
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
14
  pygame.mixer_music.set_endevent(bf.const.MUSIC_END_EVENT)
15
15
 
16
- def free_sounds(self, force:bool=False):
16
+ def free_sounds(self, force=False):
17
17
  if force:
18
18
  self.sounds = {}
19
19
  return
20
- self.sounds = {key:value for key,value in self.sounds.items() if value["persistent"]}
20
+ to_remove = []
21
+ for name, data in self.sounds.items():
22
+ if not data["persistent"]:
23
+ to_remove.append(name)
24
+
25
+ _ = [self.sounds.pop(i) for i in to_remove]
21
26
 
22
27
  def set_sound_volume(self, volume: float):
23
28
  self.sound_volume = volume
@@ -26,54 +31,38 @@ class AudioManager(metaclass=bf.Singleton):
26
31
  self.music_volume = volume
27
32
  pygame.mixer_music.set_volume(volume)
28
33
 
29
- def has_sound(self, name:str):
34
+ def has_sound(self, name):
30
35
  return name in self.sounds
31
36
 
32
37
  def load_sound(self, name, path, persistent=False) -> pygame.mixer.Sound:
33
38
  if name in self.sounds:
34
39
  return self.sounds[name]["sound"]
35
- path = bf.ResourceManager().get_path(path)
40
+ path = bf.utils.get_path(path)
36
41
  self.sounds[name] = {
37
42
  "path": path,
38
43
  "sound": pygame.mixer.Sound(path),
39
- "persistent": persistent
44
+ "persistent": persistent,
40
45
  }
41
46
  return self.sounds[name]["sound"]
42
47
 
43
- def load_sounds(self,sound_data_list:list[tuple[str,str,bool]])->None:
44
- for data in sound_data_list:
45
- self.load_sound(*data)
46
- return
47
-
48
48
  def play_sound(self, name, volume=1):
49
- try:
50
- self.sounds[name]["sound"].set_volume(volume * self.sound_volume)
51
- self.sounds[name]["sound"].play()
52
- except KeyError:
53
- print(f"Sound '{name}' not loaded in AudioManager.")
49
+ self.sounds[name]["sound"].set_volume(volume * self.sound_volume)
50
+ self.sounds[name]["sound"].play()
54
51
 
55
52
  def stop_sound(self, name):
56
- try:
53
+ if name in self.sounds:
57
54
  self.sounds[name]["sound"].stop()
58
- except KeyError:
59
-
60
- print(f"Sound '{name}' not loaded in AudioManager.")
55
+
61
56
  def load_music(self, name, path):
62
- self.musics[name] = bf.ResourceManager().get_path(path)
63
- return
64
-
65
- def load_musics(self,music_data_list:list[tuple[str,str]]):
66
- for data in music_data_list:
67
- self.load_music(*data)
68
- return
69
-
57
+ self.musics[name] = bf.utils.get_path(path)
58
+
70
59
  def play_music(self, name, loop=0, fade=500):
71
- try:
60
+ if name in self.musics:
72
61
  pygame.mixer_music.load(self.musics[name])
73
62
  pygame.mixer_music.play(loop, fade_ms=fade)
74
63
  self.current_music = name
75
- except KeyError:
76
- print(f"Music '{name}' not loaded in AudioManager.")
64
+ else:
65
+ print(f"Music '{name}' not found in AudioManager.")
77
66
 
78
67
  def stop_music(self):
79
68
  if not self.current_music:
@@ -94,6 +83,3 @@ class AudioManager(metaclass=bf.Singleton):
94
83
  if not self.current_music:
95
84
  return
96
85
  pygame.mixer_music.unpause()
97
-
98
- def get_current_music(self)->str|None:
99
- return self.current_music