batframework 0.1.13__py3-none-any.whl → 1.0.1__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 (47) hide show
  1. batFramework/__init__.py +41 -46
  2. batFramework/action.py +42 -20
  3. batFramework/actionContainer.py +43 -4
  4. batFramework/animatedSprite.py +26 -20
  5. batFramework/camera.py +177 -47
  6. batFramework/constants.py +26 -51
  7. batFramework/cutscene.py +15 -15
  8. batFramework/cutsceneBlocks.py +11 -9
  9. batFramework/dynamicEntity.py +7 -6
  10. batFramework/easing.py +28 -23
  11. batFramework/entity.py +87 -49
  12. batFramework/enums.py +14 -0
  13. batFramework/fontManager.py +57 -0
  14. batFramework/gui/__init__.py +2 -2
  15. batFramework/gui/button.py +82 -31
  16. batFramework/gui/constraints.py +137 -104
  17. batFramework/gui/container.py +27 -28
  18. batFramework/gui/debugger.py +92 -42
  19. batFramework/gui/frame.py +15 -15
  20. batFramework/gui/image.py +37 -17
  21. batFramework/gui/indicator.py +18 -14
  22. batFramework/gui/interactiveWidget.py +11 -10
  23. batFramework/gui/label.py +60 -56
  24. batFramework/gui/layout.py +50 -47
  25. batFramework/gui/root.py +43 -30
  26. batFramework/gui/shape.py +34 -41
  27. batFramework/gui/slider.py +5 -0
  28. batFramework/gui/toggle.py +31 -27
  29. batFramework/gui/widget.py +148 -128
  30. batFramework/manager.py +18 -13
  31. batFramework/particles.py +16 -13
  32. batFramework/resourceManager.py +55 -0
  33. batFramework/scene.py +141 -83
  34. batFramework/sceneManager.py +21 -16
  35. batFramework/sprite.py +31 -0
  36. batFramework/stateMachine.py +1 -0
  37. batFramework/tileset.py +7 -9
  38. batFramework/time.py +61 -50
  39. batFramework/transition.py +20 -12
  40. batFramework/utils.py +2 -65
  41. batframework-1.0.1.dist-info/LICENCE +21 -0
  42. {batframework-0.1.13.dist-info → batframework-1.0.1.dist-info}/METADATA +3 -2
  43. batframework-1.0.1.dist-info/RECORD +48 -0
  44. {batframework-0.1.13.dist-info → batframework-1.0.1.dist-info}/WHEEL +1 -1
  45. batFramework/debugger.py +0 -48
  46. batframework-0.1.13.dist-info/RECORD +0 -43
  47. {batframework-0.1.13.dist-info → batframework-1.0.1.dist-info}/top_level.txt +0 -0
batFramework/__init__.py CHANGED
@@ -1,67 +1,62 @@
1
1
  import pygame
2
+ import batFramework as bf
3
+ import sys
2
4
  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
5
  from .constants import Colors as color
43
- from .constants import Axis as axis
44
6
  from .utils import Singleton
7
+ from .enums import *
8
+ from .resourceManager import ResourceManager
9
+ from .fontManager import FontManager
10
+ # if const.BF_INITIALIZED:
45
11
  from .utils import Utils as utils
46
12
  from .tileset import Tileset
47
- from .time import Time, Timer
48
- from .cutscene import Cutscene,CutsceneManager
13
+ from .time import TimeManager, Timer
14
+ from .cutscene import Cutscene, CutsceneManager
49
15
  from .cutsceneBlocks import *
50
16
  from .easing import Easing, EasingAnimation
51
17
  from .audioManager import AudioManager
52
- from .utils import Layout, Alignment, Direction
53
- from .transition import *
18
+ # import batFramework.transition as transition
54
19
  from .action import Action
55
- from .actionContainer import ActionContainer
20
+ from .actionContainer import *
56
21
  from .camera import Camera
57
22
  from .entity import Entity
58
23
  from .dynamicEntity import DynamicEntity
24
+ from .sprite import Sprite
59
25
  from .animatedSprite import AnimatedSprite, AnimState
60
26
  from .stateMachine import State, StateMachine
61
- from .particles import Particle, ParticleManager
62
27
  # from .debugger import Debugger
63
28
  from .scene import Scene
64
29
  from .gui import *
65
30
  from .sceneManager import SceneManager
66
31
  from .manager import Manager
67
32
 
33
+
34
+ def init_screen(resolution: tuple[int, int], flags: int = 0, vsync: int = 0):
35
+ const.RESOLUTION = resolution
36
+ const.FLAGS = flags
37
+ const.VSYNC = vsync
38
+ const.SCREEN = pygame.display.set_mode(
39
+ const.RESOLUTION,const.FLAGS, vsync=const.VSYNC
40
+ )
41
+ print(
42
+ f"Window : {resolution[0]}x{resolution[1]} [vsync:{pygame.display.is_vsync()}]"
43
+ )
44
+
45
+ def init(
46
+ resolution: tuple[int, int],
47
+ flags: int = 0,
48
+ vsync: int = 0,
49
+ default_text_size=None,
50
+ default_font=None,
51
+ resource_path: str | None = None,
52
+ window_title: str = "BatFramework Project",
53
+ fps_limit: int = 0):
54
+ pygame.display.set_caption(window_title)
55
+ init_screen(resolution,flags,vsync)
56
+
57
+ ResourceManager().set_resource_path(resource_path if resource_path is not None else ".")
58
+ ResourceManager().load_dir(ResourceManager().RESOURCE_PATH)
59
+ if default_text_size is not None : FontManager().set_default_text_size(default_text_size)
60
+ FontManager().init_font(default_font)
61
+ const.BF_INITIALIZED = True
62
+ const.set_fps_limit(fps_limit)
batFramework/action.py CHANGED
@@ -12,20 +12,21 @@ class Action:
12
12
  Args:
13
13
  name (str): The name of the action.
14
14
  """
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()
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()
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.
29
30
 
30
31
  Args:
31
32
  val (bool): True if the action is unique, False otherwise.
@@ -51,7 +52,7 @@ class Action:
51
52
  self._active = value
52
53
  self._holding = set()
53
54
 
54
- def add_key_control(self, *keys) -> 'Action':
55
+ def add_key_control(self, *keys) -> "Action":
55
56
  """
56
57
  Add key controls to the action.
57
58
 
@@ -64,7 +65,26 @@ class Action:
64
65
  self._key_control.update(keys)
65
66
  return self
66
67
 
67
- def add_mouse_control(self, *mouse_buttons) -> 'Action':
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":
68
88
  """
69
89
  Add mouse control to the action.
70
90
 
@@ -86,7 +106,7 @@ class Action:
86
106
  """
87
107
  return self._name
88
108
 
89
- def set_continuous(self) -> 'Action':
109
+ def set_continuous(self) -> "Action":
90
110
  """
91
111
  Set the action type to continuous.
92
112
 
@@ -106,7 +126,7 @@ class Action:
106
126
  """
107
127
  return self._type == ActionType.CONTINUOUS
108
128
 
109
- def set_instantaneous(self) -> 'Action':
129
+ def set_instantaneous(self) -> "Action":
110
130
  """
111
131
  Set the action type to instantaneous.
112
132
 
@@ -126,7 +146,7 @@ class Action:
126
146
  """
127
147
  return self._type == ActionType.INSTANTANEOUS
128
148
 
129
- def set_holding(self) -> 'Action':
149
+ def set_holding(self) -> "Action":
130
150
  """
131
151
  Set the action type to holding.
132
152
 
@@ -145,9 +165,14 @@ class Action:
145
165
  """
146
166
  return self._type == ActionType.HOLDING
147
167
 
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}
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}
151
176
 
152
177
  def process_activate(self, event: pygame.event.Event) -> bool:
153
178
  """
@@ -205,10 +230,7 @@ class Action:
205
230
  if not self._holding:
206
231
  self._active = False
207
232
  return True
208
- elif (
209
- event.type == pygame.MOUSEMOTION
210
- and event.type in self._mouse_control
211
- ):
233
+ elif event.type == pygame.MOUSEMOTION and event.type in self._mouse_control:
212
234
  self.value = None
213
235
  if event.type in self._holding:
214
236
  self._holding.remove(event.type)
@@ -1,4 +1,5 @@
1
1
  import batFramework as bf
2
+ import pygame
2
3
 
3
4
 
4
5
  class ActionContainer:
@@ -14,14 +15,20 @@ class ActionContainer:
14
15
  for action in actions:
15
16
  self._actions[action.get_name()] = action
16
17
 
17
- def get(self,name:str)->bf.Action:
18
+ def get(self, name: str) -> bf.Action:
18
19
  return self._actions.get(name)
19
20
 
20
- def has_action(self, name:str):
21
+ def has_action(self, name: str):
21
22
  return name in self._actions
22
23
 
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)
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
+ )
25
32
 
26
33
  def process_event(self, event):
27
34
  for action in self._actions.values():
@@ -36,3 +43,35 @@ class ActionContainer:
36
43
  def hard_reset(self):
37
44
  for action in self._actions.values():
38
45
  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,7 +2,6 @@ import batFramework as bf
2
2
  import pygame
3
3
 
4
4
 
5
-
6
5
  def search_index(target, lst):
7
6
  cumulative_sum = 0
8
7
  for index, value in enumerate(lst):
@@ -13,12 +12,14 @@ def search_index(target, lst):
13
12
 
14
13
 
15
14
  class AnimState:
16
- def __init__(self,name:str, file, width, height, frame_length_list:list|int) -> None:
15
+ def __init__(
16
+ self, name: str, file, width, height, frame_length_list: list | int
17
+ ) -> None:
17
18
  self.frames: list[pygame.Surface] = bf.utils.img_slice(file, width, height)
18
19
  self.frames_flipX: list[pygame.Surface] = bf.utils.img_slice(
19
20
  file, width, height, True
20
21
  )
21
- self.name= name
22
+ self.name = name
22
23
  self.frame_length_list = []
23
24
  self.ffl_length = 0
24
25
  self.set_frame_length_list(frame_length_list)
@@ -26,34 +27,33 @@ class AnimState:
26
27
  def __repr__(self):
27
28
  return f"AnimState({self.name})"
28
29
 
29
- def get_frame_index(self, counter:float|int):
30
+ def get_frame_index(self, counter: float | int):
30
31
  return search_index(int(counter % self.ffl_length), self.frame_length_list)
31
32
 
32
33
  def get_frame(self, counter, flip):
33
34
  i = self.get_frame_index(counter)
34
35
  return self.frames_flipX[i] if flip else self.frames[i]
35
36
 
36
- def set_frame_length_list(self,frame_length_list:list[int]|int):
37
- if isinstance(frame_length_list,int):
37
+ def set_frame_length_list(self, frame_length_list: list[int] | int):
38
+ if isinstance(frame_length_list, int):
38
39
  frame_length_list = [frame_length_list] * len(self.frames)
39
- if len(frame_length_list) != len(self.frames) :
40
+ if len(frame_length_list) != len(self.frames):
40
41
  raise ValueError("frame_length_list should have values for all frames")
41
42
  self.frame_length_list = frame_length_list
42
43
  self.ffl_length = sum(self.frame_length_list)
43
-
44
+
44
45
 
45
46
  class AnimatedSprite(bf.DynamicEntity):
46
47
  def __init__(self, size=None) -> None:
47
48
  super().__init__(size, no_surface=True)
48
49
  self.float_counter = 0
49
50
  self.animStates: dict[str, AnimState] = {}
50
- self.current_animState :str = ""
51
+ self.current_animState: str = ""
51
52
  self.flipX = False
52
53
  self._locked = False
53
54
 
54
- def set_counter(self,value:float):
55
+ def set_counter(self, value: float):
55
56
  self.float_counter = value
56
-
57
57
 
58
58
  def lock_animState(self):
59
59
  self._locked = True
@@ -64,20 +64,25 @@ class AnimatedSprite(bf.DynamicEntity):
64
64
  def set_flipX(self, value):
65
65
  self.flipX = value
66
66
 
67
- def remove_animState(self, name:str):
68
- if not name in self.animStates :return
69
- self.animStates.pop(name)
70
- if self.current_animState == name : self.current_animState = list(self.animStates.keys())[0] if self.animStates else ""
67
+ def remove_animState(self, name: str):
68
+ if not name in self.animStates:
69
+ return
70
+ self.animStates.pop(name)
71
+ if self.current_animState == name:
72
+ self.current_animState = (
73
+ list(self.animStates.keys())[0] if self.animStates else ""
74
+ )
71
75
 
72
76
  def add_animState(
73
77
  self, name: str, file: str, size: tuple[int, int], frame_length_list: list[int]
74
78
  ):
75
79
  if name in self.animStates:
76
80
  return
77
- self.animStates[name] = AnimState(name,file, *size, frame_length_list)
78
- if len(self.animStates) == 1 : self.set_animState(name)
81
+ self.animStates[name] = AnimState(name, file, *size, frame_length_list)
82
+ if len(self.animStates) == 1:
83
+ self.set_animState(name)
79
84
 
80
- def set_animState(self, state:str, reset_counter=True, lock=False):
85
+ def set_animState(self, state: str, reset_counter=True, lock=False):
81
86
  if state not in self.animStates or self._locked:
82
87
  return False
83
88
  self.current_animState = state
@@ -95,7 +100,7 @@ class AnimatedSprite(bf.DynamicEntity):
95
100
  return True
96
101
 
97
102
  def get_state(self):
98
- return self.animStates.get(self.current_animState,None)
103
+ return self.animStates.get(self.current_animState, None)
99
104
 
100
105
  def get_frame_index(self):
101
106
  return self.animStates[self.current_animState].get_frame_index(
@@ -103,7 +108,8 @@ class AnimatedSprite(bf.DynamicEntity):
103
108
  )
104
109
 
105
110
  def update(self, dt: float):
106
- if not self.animStates : return
111
+ if not self.animStates:
112
+ return
107
113
  self.float_counter += 60 * dt
108
114
  if self.float_counter > self.get_state().ffl_length:
109
115
  self.float_counter = 0