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.
- batFramework/__init__.py +51 -68
- batFramework/action.py +99 -126
- batFramework/actionContainer.py +9 -53
- batFramework/animatedSprite.py +82 -141
- batFramework/audioManager.py +26 -69
- batFramework/camera.py +69 -259
- batFramework/constants.py +54 -16
- batFramework/cutscene.py +29 -39
- batFramework/cutsceneBlocks.py +43 -36
- batFramework/debugger.py +48 -0
- batFramework/dynamicEntity.py +9 -18
- batFramework/easing.py +71 -0
- batFramework/entity.py +97 -48
- batFramework/gui/__init__.py +2 -10
- batFramework/gui/button.py +78 -9
- batFramework/gui/constraints.py +204 -0
- batFramework/gui/container.py +32 -174
- batFramework/gui/debugger.py +43 -131
- batFramework/gui/frame.py +19 -0
- batFramework/gui/image.py +20 -56
- batFramework/gui/indicator.py +21 -38
- batFramework/gui/interactiveWidget.py +13 -192
- batFramework/gui/label.py +74 -309
- batFramework/gui/layout.py +63 -231
- batFramework/gui/root.py +38 -134
- batFramework/gui/shape.py +57 -237
- batFramework/gui/toggle.py +51 -101
- batFramework/gui/widget.py +250 -358
- batFramework/manager.py +19 -52
- batFramework/particles.py +77 -0
- batFramework/scene.py +123 -281
- batFramework/sceneManager.py +116 -178
- batFramework/stateMachine.py +8 -11
- batFramework/time.py +58 -145
- batFramework/transition.py +124 -195
- batFramework/transitionManager.py +0 -0
- batFramework/triggerZone.py +1 -1
- batFramework/utils.py +147 -112
- batframework-1.0.8a8.dist-info/METADATA +53 -0
- batframework-1.0.8a8.dist-info/RECORD +42 -0
- {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/WHEEL +1 -1
- batFramework/character.py +0 -27
- batFramework/easingController.py +0 -58
- batFramework/enums.py +0 -113
- batFramework/fontManager.py +0 -65
- batFramework/gui/clickableWidget.py +0 -220
- batFramework/gui/constraints/__init__.py +0 -1
- batFramework/gui/constraints/constraints.py +0 -815
- batFramework/gui/dialogueBox.py +0 -99
- batFramework/gui/draggableWidget.py +0 -40
- batFramework/gui/meter.py +0 -74
- batFramework/gui/radioButton.py +0 -84
- batFramework/gui/slider.py +0 -240
- batFramework/gui/style.py +0 -10
- batFramework/gui/styleManager.py +0 -48
- batFramework/gui/textInput.py +0 -247
- batFramework/object.py +0 -123
- batFramework/particle.py +0 -115
- batFramework/renderGroup.py +0 -67
- batFramework/resourceManager.py +0 -100
- batFramework/scrollingSprite.py +0 -114
- batFramework/sprite.py +0 -51
- batFramework/templates/__init__.py +0 -2
- batFramework/templates/character.py +0 -44
- batFramework/templates/states.py +0 -166
- batFramework/tileset.py +0 -46
- batframework-1.0.8a7.dist-info/LICENCE +0 -21
- batframework-1.0.8a7.dist-info/METADATA +0 -43
- batframework-1.0.8a7.dist-info/RECORD +0 -62
- {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/top_level.txt +0 -0
batFramework/animatedSprite.py
CHANGED
@@ -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
|
-
|
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
|
16
|
-
def __init__(
|
17
|
-
self,
|
18
|
-
|
19
|
-
|
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
|
-
|
42
|
-
|
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
|
46
|
-
if isinstance(
|
47
|
-
|
48
|
-
if len(
|
49
|
-
raise ValueError("
|
50
|
-
self.
|
51
|
-
self.
|
52
|
-
|
53
|
-
|
54
|
-
class AnimatedSprite(bf.
|
55
|
-
def __init__(self, size
|
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
|
58
|
-
self.
|
59
|
-
self.
|
60
|
-
self.flipX
|
61
|
-
self._locked
|
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
|
85
|
-
|
86
|
-
|
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
|
55
|
+
def lock_animState(self):
|
90
56
|
self._locked = True
|
91
57
|
|
92
|
-
def
|
58
|
+
def unlock_animState(self):
|
93
59
|
self._locked = False
|
94
60
|
|
95
|
-
def set_flipX(self, value
|
61
|
+
def set_flipX(self, value):
|
96
62
|
self.flipX = value
|
97
63
|
|
98
|
-
def
|
99
|
-
if name
|
100
|
-
|
101
|
-
self.
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
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
|
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.
|
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
|
118
|
-
self,
|
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
|
-
|
127
|
-
|
97
|
+
def get_frame_index(self):
|
98
|
+
return self.animStates[self.current_animState].get_frame_index(
|
99
|
+
self.float_counter
|
100
|
+
)
|
128
101
|
|
129
|
-
|
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
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
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.
|
174
|
-
camera.
|
114
|
+
self.get_state().get_frame(self.float_counter, self.flipX),
|
115
|
+
camera.transpose(self.rect),
|
175
116
|
)
|
176
|
-
return
|
117
|
+
return True
|
batFramework/audioManager.py
CHANGED
@@ -5,25 +5,24 @@ pygame.mixer.init()
|
|
5
5
|
|
6
6
|
|
7
7
|
class AudioManager(metaclass=bf.Singleton):
|
8
|
-
def __init__(self)
|
9
|
-
self.sounds: dict = {}
|
10
|
-
self.musics: dict = {}
|
11
|
-
self.current_music
|
12
|
-
self.music_volume
|
13
|
-
self.sound_volume
|
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
|
16
|
+
def free_sounds(self, force=False):
|
17
17
|
if force:
|
18
18
|
self.sounds = {}
|
19
19
|
return
|
20
|
-
|
21
|
-
|
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
|
-
|
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
|
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.
|
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
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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.
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
-
|
103
|
-
|
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
|