batframework 1.0.7__tar.gz → 1.0.8a2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. batframework-1.0.8a2/PKG-INFO +58 -0
  2. batframework-1.0.8a2/README.md +45 -0
  3. {batframework-1.0.7 → batframework-1.0.8a2}/pyproject.toml +2 -2
  4. batframework-1.0.8a2/src/batFramework/__init__.py +66 -0
  5. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/action.py +20 -42
  6. batframework-1.0.8a2/src/batFramework/actionContainer.py +38 -0
  7. batframework-1.0.8a2/src/batFramework/animatedSprite.py +117 -0
  8. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/audioManager.py +25 -39
  9. batframework-1.0.8a2/src/batFramework/camera.py +123 -0
  10. batframework-1.0.8a2/src/batFramework/constants.py +75 -0
  11. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/cutscene.py +24 -32
  12. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/cutsceneBlocks.py +33 -30
  13. batframework-1.0.8a2/src/batFramework/debugger.py +48 -0
  14. batframework-1.0.8a2/src/batFramework/dynamicEntity.py +23 -0
  15. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/easing.py +23 -28
  16. batframework-1.0.8a2/src/batFramework/entity.py +123 -0
  17. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/gui/__init__.py +1 -3
  18. batframework-1.0.8a2/src/batFramework/gui/button.py +84 -0
  19. batframework-1.0.8a2/src/batFramework/gui/constraints.py +204 -0
  20. batframework-1.0.8a2/src/batFramework/gui/container.py +49 -0
  21. batframework-1.0.8a2/src/batFramework/gui/debugger.py +47 -0
  22. batframework-1.0.8a2/src/batFramework/gui/frame.py +19 -0
  23. batframework-1.0.8a2/src/batFramework/gui/image.py +23 -0
  24. batframework-1.0.8a2/src/batFramework/gui/indicator.py +40 -0
  25. batframework-1.0.8a2/src/batFramework/gui/interactiveWidget.py +22 -0
  26. batframework-1.0.8a2/src/batFramework/gui/label.py +110 -0
  27. batframework-1.0.8a2/src/batFramework/gui/layout.py +81 -0
  28. batframework-1.0.8a2/src/batFramework/gui/root.py +60 -0
  29. batframework-1.0.8a2/src/batFramework/gui/shape.py +86 -0
  30. batframework-1.0.8a2/src/batFramework/gui/toggle.py +62 -0
  31. batframework-1.0.8a2/src/batFramework/gui/widget.py +307 -0
  32. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/manager.py +14 -21
  33. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/particles.py +20 -41
  34. batframework-1.0.8a2/src/batFramework/scene.py +226 -0
  35. batframework-1.0.8a2/src/batFramework/sceneManager.py +165 -0
  36. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/stateMachine.py +0 -1
  37. batframework-1.0.8a2/src/batFramework/time.py +75 -0
  38. batframework-1.0.8a2/src/batFramework/transition.py +157 -0
  39. batframework-1.0.8a2/src/batFramework/utils.py +184 -0
  40. batframework-1.0.8a2/src/batframework.egg-info/PKG-INFO +58 -0
  41. {batframework-1.0.7 → batframework-1.0.8a2}/src/batframework.egg-info/SOURCES.txt +1 -9
  42. batframework-1.0.7/LICENCE +0 -21
  43. batframework-1.0.7/PKG-INFO +0 -55
  44. batframework-1.0.7/README.md +0 -41
  45. batframework-1.0.7/src/batFramework/__init__.py +0 -60
  46. batframework-1.0.7/src/batFramework/actionContainer.py +0 -77
  47. batframework-1.0.7/src/batFramework/animatedSprite.py +0 -150
  48. batframework-1.0.7/src/batFramework/camera.py +0 -293
  49. batframework-1.0.7/src/batFramework/constants.py +0 -59
  50. batframework-1.0.7/src/batFramework/dynamicEntity.py +0 -24
  51. batframework-1.0.7/src/batFramework/entity.py +0 -160
  52. batframework-1.0.7/src/batFramework/enums.py +0 -14
  53. batframework-1.0.7/src/batFramework/fontManager.py +0 -57
  54. batframework-1.0.7/src/batFramework/gui/button.py +0 -150
  55. batframework-1.0.7/src/batFramework/gui/constraints.py +0 -277
  56. batframework-1.0.7/src/batFramework/gui/container.py +0 -60
  57. batframework-1.0.7/src/batFramework/gui/debugger.py +0 -111
  58. batframework-1.0.7/src/batFramework/gui/dialogueBox.py +0 -70
  59. batframework-1.0.7/src/batFramework/gui/frame.py +0 -25
  60. batframework-1.0.7/src/batFramework/gui/image.py +0 -42
  61. batframework-1.0.7/src/batFramework/gui/indicator.py +0 -46
  62. batframework-1.0.7/src/batFramework/gui/interactiveWidget.py +0 -73
  63. batframework-1.0.7/src/batFramework/gui/label.py +0 -173
  64. batframework-1.0.7/src/batFramework/gui/layout.py +0 -96
  65. batframework-1.0.7/src/batFramework/gui/root.py +0 -101
  66. batframework-1.0.7/src/batFramework/gui/shape.py +0 -79
  67. batframework-1.0.7/src/batFramework/gui/slider.py +0 -5
  68. batframework-1.0.7/src/batFramework/gui/textInput.py +0 -88
  69. batframework-1.0.7/src/batFramework/gui/toggle.py +0 -70
  70. batframework-1.0.7/src/batFramework/gui/widget.py +0 -350
  71. batframework-1.0.7/src/batFramework/resourceManager.py +0 -72
  72. batframework-1.0.7/src/batFramework/scene.py +0 -327
  73. batframework-1.0.7/src/batFramework/sceneManager.py +0 -125
  74. batframework-1.0.7/src/batFramework/sprite.py +0 -33
  75. batframework-1.0.7/src/batFramework/tileset.py +0 -64
  76. batframework-1.0.7/src/batFramework/time.py +0 -86
  77. batframework-1.0.7/src/batFramework/transition.py +0 -3
  78. batframework-1.0.7/src/batFramework/utils.py +0 -37
  79. batframework-1.0.7/src/batframework.egg-info/PKG-INFO +0 -55
  80. {batframework-1.0.7 → batframework-1.0.8a2}/setup.cfg +0 -0
  81. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/transitionManager.py +0 -0
  82. {batframework-1.0.7 → batframework-1.0.8a2}/src/batFramework/triggerZone.py +0 -0
  83. {batframework-1.0.7 → batframework-1.0.8a2}/src/batframework.egg-info/dependency_links.txt +0 -0
  84. {batframework-1.0.7 → batframework-1.0.8a2}/src/batframework.egg-info/requires.txt +0 -0
  85. {batframework-1.0.7 → batframework-1.0.8a2}/src/batframework.egg-info/top_level.txt +0 -0
@@ -0,0 +1,58 @@
1
+ Metadata-Version: 2.1
2
+ Name: batframework
3
+ Version: 1.0.8a2
4
+ Summary: Pygame framework for making games easier.
5
+ Author-email: Turan Baturay <baturayturan@gmail.com>
6
+ Project-URL: Homepage, https://github.com/TuranBaturay/batFramework
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: pygame-ce
13
+
14
+ # batFramework
15
+
16
+ batFramework is a Python game framework built using Pygame, designed to simplify game development by providing entities, scenes, a scene manager, and various utilities.
17
+
18
+ ## Purpose and Overview
19
+ The primary objective of batFramework is to streamline game development by utilizing entities and scenes that hold entities. It employs a manager, which inherits from the scene manager, to handle scenes, propagate events, and manage updates and rendering.
20
+
21
+ ## Installation and Setup
22
+ To install batFramework, you can use pip:
23
+ ```pip install batFramework```
24
+
25
+
26
+ The only dependency required is pygame-ce.
27
+
28
+ ## Usage Instructions
29
+ To create a basic app using batFramework, here's an example:
30
+
31
+ ```python
32
+ import batFramework as bf
33
+
34
+ # Initialize the framework
35
+ bf.init((1280, 720), window_title="My Amazing Program")
36
+
37
+ # Create a manager and a scene
38
+ bf.Manager(bf.Scene("main")).run()
39
+ ```
40
+ In practice, users can inherit bf.Scene to create their own scenes, adding specific behaviors, entities, etc.
41
+
42
+ ## Features and Functionalities
43
+
44
+ - Scene management for organizing game components
45
+ - Cutscene support to facilitate storytelling sequences
46
+ - Audio management for music and sound effects with volume control
47
+ - Entity, sprite, and animated sprite support
48
+ - Utility modules such as time management and easingAnimation
49
+
50
+ Users can leverage these functionalities to build games efficiently using batFramework.
51
+
52
+ For more detailed usage and examples, please refer to the documentation or codebase.
53
+
54
+
55
+ # License
56
+ MIT License
57
+
58
+
@@ -0,0 +1,45 @@
1
+ # batFramework
2
+
3
+ batFramework is a Python game framework built using Pygame, designed to simplify game development by providing entities, scenes, a scene manager, and various utilities.
4
+
5
+ ## Purpose and Overview
6
+ The primary objective of batFramework is to streamline game development by utilizing entities and scenes that hold entities. It employs a manager, which inherits from the scene manager, to handle scenes, propagate events, and manage updates and rendering.
7
+
8
+ ## Installation and Setup
9
+ To install batFramework, you can use pip:
10
+ ```pip install batFramework```
11
+
12
+
13
+ The only dependency required is pygame-ce.
14
+
15
+ ## Usage Instructions
16
+ To create a basic app using batFramework, here's an example:
17
+
18
+ ```python
19
+ import batFramework as bf
20
+
21
+ # Initialize the framework
22
+ bf.init((1280, 720), window_title="My Amazing Program")
23
+
24
+ # Create a manager and a scene
25
+ bf.Manager(bf.Scene("main")).run()
26
+ ```
27
+ In practice, users can inherit bf.Scene to create their own scenes, adding specific behaviors, entities, etc.
28
+
29
+ ## Features and Functionalities
30
+
31
+ - Scene management for organizing game components
32
+ - Cutscene support to facilitate storytelling sequences
33
+ - Audio management for music and sound effects with volume control
34
+ - Entity, sprite, and animated sprite support
35
+ - Utility modules such as time management and easingAnimation
36
+
37
+ Users can leverage these functionalities to build games efficiently using batFramework.
38
+
39
+ For more detailed usage and examples, please refer to the documentation or codebase.
40
+
41
+
42
+ # License
43
+ MIT License
44
+
45
+
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "batframework"
7
- version = "1.0.7"
7
+ version = "1.0.8a2"
8
8
  authors = [
9
9
  { name="Turan Baturay", email="baturayturan@gmail.com" }
10
10
  ]
@@ -15,7 +15,7 @@ classifiers = [
15
15
  "License :: OSI Approved :: MIT License",
16
16
  "Operating System :: OS Independent",
17
17
  ]
18
- requires-python = ">=3.11"
18
+ requires-python = ">=3.10"
19
19
  dependencies=[
20
20
  "pygame-ce"
21
21
  ]
@@ -0,0 +1,66 @@
1
+ import pygame
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
+
42
+ from .constants import Colors as color
43
+ from .constants import Axis as axis
44
+ from .utils import Singleton
45
+ from .utils import Utils as utils
46
+ from .time import Time, Timer
47
+ from .cutscene import Cutscene,CutsceneManager
48
+ from .cutsceneBlocks import *
49
+ from .easing import Easing, EasingAnimation
50
+ from .audioManager import AudioManager
51
+ from .utils import Layout, Alignment, Direction
52
+ from .transition import *
53
+ from .action import Action
54
+ from .actionContainer import ActionContainer
55
+ from .camera import Camera
56
+ from .entity import Entity
57
+ from .dynamicEntity import DynamicEntity
58
+ from .animatedSprite import AnimatedSprite, AnimState
59
+ from .stateMachine import State, StateMachine
60
+ from .particles import Particle, ParticleManager
61
+ # from .debugger import Debugger
62
+ from .scene import Scene
63
+ from .gui import *
64
+ from .sceneManager import SceneManager
65
+ from .manager import Manager
66
+
@@ -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)
@@ -0,0 +1,38 @@
1
+ import batFramework as bf
2
+
3
+
4
+ class ActionContainer:
5
+ def __init__(self, *actions: list[bf.Action]) -> None:
6
+ self._actions: dict[str, bf.Action] = {}
7
+ if actions:
8
+ self.add_action(*actions)
9
+
10
+ def clear(self):
11
+ self._actions = {}
12
+
13
+ def add_action(self, *actions: bf.Action):
14
+ for action in actions:
15
+ self._actions[action.get_name()] = action
16
+
17
+ def get(self,name:str)->bf.Action:
18
+ return self._actions.get(name)
19
+
20
+ def has_action(self, name:str):
21
+ return name in self._actions
22
+
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)
25
+
26
+ def process_event(self, event):
27
+ for action in self._actions.values():
28
+ a = action.process_event(event)
29
+ if a and action._unique:
30
+ break
31
+
32
+ def reset(self):
33
+ for action in self._actions.values():
34
+ action.reset()
35
+
36
+ def hard_reset(self):
37
+ for action in self._actions.values():
38
+ action.hard_reset()
@@ -0,0 +1,117 @@
1
+ import batFramework as bf
2
+ import pygame
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:
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):
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
@@ -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