batframework 1.0.8a7__py3-none-any.whl → 1.0.8a8__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 (70) hide show
  1. batFramework/__init__.py +51 -68
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +82 -141
  5. batFramework/audioManager.py +26 -69
  6. batFramework/camera.py +69 -259
  7. batFramework/constants.py +54 -16
  8. batFramework/cutscene.py +29 -39
  9. batFramework/cutsceneBlocks.py +43 -36
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -18
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +97 -48
  14. batFramework/gui/__init__.py +2 -10
  15. batFramework/gui/button.py +78 -9
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +32 -174
  18. batFramework/gui/debugger.py +43 -131
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -56
  21. batFramework/gui/indicator.py +21 -38
  22. batFramework/gui/interactiveWidget.py +13 -192
  23. batFramework/gui/label.py +74 -309
  24. batFramework/gui/layout.py +63 -231
  25. batFramework/gui/root.py +38 -134
  26. batFramework/gui/shape.py +57 -237
  27. batFramework/gui/toggle.py +51 -101
  28. batFramework/gui/widget.py +250 -358
  29. batFramework/manager.py +19 -52
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +123 -281
  32. batFramework/sceneManager.py +116 -178
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +58 -145
  35. batFramework/transition.py +124 -195
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +1 -1
  38. batFramework/utils.py +147 -112
  39. batframework-1.0.8a8.dist-info/METADATA +53 -0
  40. batframework-1.0.8a8.dist-info/RECORD +42 -0
  41. {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/WHEEL +1 -1
  42. batFramework/character.py +0 -27
  43. batFramework/easingController.py +0 -58
  44. batFramework/enums.py +0 -113
  45. batFramework/fontManager.py +0 -65
  46. batFramework/gui/clickableWidget.py +0 -220
  47. batFramework/gui/constraints/__init__.py +0 -1
  48. batFramework/gui/constraints/constraints.py +0 -815
  49. batFramework/gui/dialogueBox.py +0 -99
  50. batFramework/gui/draggableWidget.py +0 -40
  51. batFramework/gui/meter.py +0 -74
  52. batFramework/gui/radioButton.py +0 -84
  53. batFramework/gui/slider.py +0 -240
  54. batFramework/gui/style.py +0 -10
  55. batFramework/gui/styleManager.py +0 -48
  56. batFramework/gui/textInput.py +0 -247
  57. batFramework/object.py +0 -123
  58. batFramework/particle.py +0 -115
  59. batFramework/renderGroup.py +0 -67
  60. batFramework/resourceManager.py +0 -100
  61. batFramework/scrollingSprite.py +0 -114
  62. batFramework/sprite.py +0 -51
  63. batFramework/templates/__init__.py +0 -2
  64. batFramework/templates/character.py +0 -44
  65. batFramework/templates/states.py +0 -166
  66. batFramework/tileset.py +0 -46
  67. batframework-1.0.8a7.dist-info/LICENCE +0 -21
  68. batframework-1.0.8a7.dist-info/METADATA +0 -43
  69. batframework-1.0.8a7.dist-info/RECORD +0 -62
  70. {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,9 @@
1
1
  import batFramework as bf
2
2
  import pygame
3
- from typing import List, Dict, Tuple, Union, Optional, Self
4
3
 
5
4
 
6
- def search_index(target: int, lst: List[int]) -> int:
5
+
6
+ def search_index(target, lst):
7
7
  cumulative_sum = 0
8
8
  for index, value in enumerate(lst):
9
9
  cumulative_sum += value
@@ -12,165 +12,106 @@ def search_index(target: int, lst: List[int]) -> int:
12
12
  return -1
13
13
 
14
14
 
15
- class Animation:
16
- def __init__(
17
- self,
18
- name: str
19
- ) -> None:
20
- self.name = name
21
- self.frames: list[pygame.Surface] = []
22
- self.frames_flipX : list[pygame.Surface] = []
23
- self.duration_list = []
24
- self.duration_list_length = 1
25
-
26
- def from_surface(self,surface:pygame.Surface,size : Tuple[int,int])->Self:
27
- self.frames : List[pygame.Surface] = list(bf.utils.split_surface(surface, size).values())
28
- self.frames_flipX : List[pygame.Surface] = list(bf.utils.split_surface(surface, size,func=lambda s : pygame.transform.flip(s,True,False)).values())
29
- return self
30
-
31
- def __repr__(self):
32
- return f"Animation({self.name})"
33
-
34
- def counter_to_frame(self, counter: Union[float, int]) -> int:
35
- if not self.frames :
36
- raise ValueError("Animation has no frames")
37
- return search_index(
38
- int(counter % self.duration_list_length), self.duration_list
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
39
20
  )
40
21
 
41
- def get_frame(self, counter: Union[float, int], flip: bool) -> pygame.Surface:
42
- i = self.counter_to_frame(counter)
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)
43
31
  return self.frames_flipX[i] if flip else self.frames[i]
44
32
 
45
- def set_duration_list(self, duration_list: Union[List[int], int]) -> Self:
46
- if isinstance(duration_list, int):
47
- duration_list = [duration_list] * len(self.frames)
48
- if len(duration_list) != len(self.frames):
49
- raise ValueError("duration_list should have values for all frames")
50
- self.duration_list = duration_list
51
- self.duration_list_length = sum(self.duration_list)
52
- return self
53
-
54
- class AnimatedSprite(bf.Entity):
55
- def __init__(self, size: Optional[Tuple[int, int]] = None) -> None:
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:
56
44
  super().__init__(size, no_surface=True)
57
- self.float_counter: float = 0
58
- self.animations: Dict[str, Animation] = {}
59
- self.current_state: Optional[Animation] = None
60
- self.flipX: bool = False
61
- self._locked: bool = False
62
- self._paused: bool = False
63
- self.animation_end_callback = None
64
- self.transition_end_animation = None
65
-
66
- def set_animation_end_callback(self,callback)->Self:
67
- self.animation_end_callback = callback
68
- return self
69
-
70
- @property
71
- def paused(self) -> bool:
72
- return self._paused
73
-
74
- @paused.setter
75
- def paused(self, value: bool) -> None:
76
- self._paused = value
77
-
78
- def toggle_pause(self) -> None:
79
- self.paused = not self.paused
80
-
81
- def set_counter(self, value: float) -> None:
82
- self.float_counter = value
45
+ self.float_counter = 0
46
+ self.animStates: dict[str, AnimState] = {}
47
+ self.current_animState :str = ""
48
+ self.flipX = False
49
+ self._locked = False
83
50
 
84
- def set_frame(self, frame_index: int) -> None:
85
- if not self.current_state:
86
- return
87
- self.set_counter(sum(self.current_state.duration_list[:frame_index]))
51
+ def set_counter(self,value:float):
52
+ self.float_counter = value
53
+
88
54
 
89
- def lock(self) -> None:
55
+ def lock_animState(self):
90
56
  self._locked = True
91
57
 
92
- def unlock(self) -> None:
58
+ def unlock_animState(self):
93
59
  self._locked = False
94
60
 
95
- def set_flipX(self, value: bool) -> None:
61
+ def set_flipX(self, value):
96
62
  self.flipX = value
97
63
 
98
- def remove_animation(self, name: str) -> bool:
99
- if name not in self.animations:
100
- return False
101
- self.animations.pop(name)
102
- if self.current_state and self.current_state.name == name:
103
- self.current_state = (
104
- list(self.animations.values())[0] if self.animations else None
105
- )
106
- return True
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)
107
76
 
108
- def add_animation(
109
- self,
110
- animation:Animation
111
- ) -> bool:
112
- if animation.name in self.animations:
77
+ def set_animState(self, state:str, reset_counter=True, lock=False):
78
+ if state not in self.animStates or self._locked:
113
79
  return False
114
- self.animations[animation.name] = animation
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()
115
92
  return True
116
93
 
117
- def set_animation(
118
- self, state: str, reset_counter: bool = True, lock: bool = False
119
- ) -> bool:
120
- if state not in self.animations or self._locked:
121
- return False
122
-
123
- animation = self.animations[state]
124
- self.current_state = animation
94
+ def get_state(self):
95
+ return self.animStates.get(self.current_animState,None)
125
96
 
126
- if self.current_state.frames:
127
- self.rect = self.current_state.frames[0].get_frect(center=self.rect.center)
97
+ def get_frame_index(self):
98
+ return self.animStates[self.current_animState].get_frame_index(
99
+ self.float_counter
100
+ )
128
101
 
129
- if reset_counter or (self.float_counter > animation.duration_list_length):
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:
130
106
  self.float_counter = 0
107
+ self.do_update(dt)
131
108
 
132
- if lock:
133
- self.lock()
134
-
135
- if self.transition_end_animation is not None:
136
- self.transition_end_animation = None
137
- return True
138
-
139
- def transition_to_animation(self,transition:str,animation:str)->Self:
140
- self.set_animation(transition)
141
- self.transition_end_animation = animation
142
- return self
143
-
144
- def get_current_animation(self) -> Optional[Animation]:
145
- return self.current_state
146
-
147
- def update(self, dt: float) -> None:
148
- s = self.get_current_animation()
149
- if self.animations and s is not None:
150
- if not self.paused:
151
- self.float_counter += 60 * dt
152
- if self.float_counter > s.duration_list_length:
153
- if self.transition_end_animation is not None:
154
- # print(f"{self.transition_end_animation=}, {self.get_current_animation()=}")
155
- self.set_animation(self.transition_end_animation)
156
- if self.animation_end_callback is not None:
157
- self.animation_end_callback()
158
- self.float_counter = 0
159
- super().update(dt)
160
-
161
-
162
- def get_current_frame(self)->pygame.Surface:
163
- return self.current_state.get_frame(self.float_counter, self.flipX)
164
-
165
- def draw(self, camera: bf.Camera) -> None:
166
- if (
167
- not self.visible
168
- or not camera.rect.colliderect(self.rect)
169
- or not self.current_state
170
- ):
171
- return
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))
172
113
  camera.surface.blit(
173
- self.get_current_frame(),
174
- camera.world_to_screen(self.rect),
114
+ self.get_state().get_frame(self.float_counter, self.flipX),
115
+ camera.transpose(self.rect),
175
116
  )
176
- return
117
+ return True
@@ -5,25 +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: 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
@@ -32,19 +31,13 @@ class AudioManager(metaclass=bf.Singleton):
32
31
  self.music_volume = volume
33
32
  pygame.mixer_music.set_volume(volume)
34
33
 
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
40
-
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
38
  if name in self.sounds:
46
39
  return self.sounds[name]["sound"]
47
- path = bf.ResourceManager().get_path(path)
40
+ path = bf.utils.get_path(path)
48
41
  self.sounds[name] = {
49
42
  "path": path,
50
43
  "sound": pygame.mixer.Sound(path),
@@ -52,57 +45,24 @@ class AudioManager(metaclass=bf.Singleton):
52
45
  }
53
46
  return self.sounds[name]["sound"]
54
47
 
55
- def load_sounds(self, sound_data_list: list[tuple[str, str, bool]]) -> None:
56
- for data in sound_data_list:
57
- self.load_sound(*data)
58
- return
59
-
60
- def play_sound(self, name, volume=1) -> bool:
61
- """
62
- Play the sound file with the given name.
63
- returns True if the sound was played
64
-
65
- """
66
- try:
67
- self.sounds[name]["sound"].set_volume(volume * self.sound_volume)
68
- self.sounds[name]["sound"].play()
69
- return True
70
- except KeyError:
71
- print(f"Sound '{name}' not loaded in AudioManager.")
72
- return False
73
-
74
- def stop_sound(self, name) -> bool:
75
- 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:
76
54
  self.sounds[name]["sound"].stop()
77
- return True
78
- except KeyError:
79
- return False
80
- print(f"Sound '{name}' not loaded in AudioManager.")
81
55
 
82
56
  def load_music(self, name, path):
83
- self.musics[name] = bf.ResourceManager().get_path(path)
84
- return
85
-
86
- def load_musics(self, music_data_list: list[tuple[str, str]]):
87
- for data in music_data_list:
88
- self.load_music(*data)
89
- return
90
-
91
- def play_music(self, name, loop=0, fade=500) -> bool:
92
- """
93
- Play the sound file with the given 'name'.
94
- Fades with the given 'fade' time in ms.
95
- Music will loop 'loop' times (indefinitely if -1).
96
- returns True if the sound was played
97
- """
98
- try:
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:
99
61
  pygame.mixer_music.load(self.musics[name])
100
62
  pygame.mixer_music.play(loop, fade_ms=fade)
101
63
  self.current_music = name
102
- return True
103
- except KeyError:
104
- return False
105
- # print(f"Music '{name}' not loaded in AudioManager.")
64
+ else:
65
+ print(f"Music '{name}' not found in AudioManager.")
106
66
 
107
67
  def stop_music(self):
108
68
  if not self.current_music:
@@ -123,6 +83,3 @@ class AudioManager(metaclass=bf.Singleton):
123
83
  if not self.current_music:
124
84
  return
125
85
  pygame.mixer_music.unpause()
126
-
127
- def get_current_music(self) -> str | None:
128
- return self.current_music