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
@@ -0,0 +1,48 @@
1
+ import batFramework as bf
2
+ import pygame
3
+
4
+
5
+ class Debugger(bf.Label):
6
+ def __init__(self, manager) -> None:
7
+ super().__init__()
8
+ self.manager: bf.Manager = manager
9
+ self.refresh_rate = 0
10
+ self._refresh_counter = 0
11
+ self.dynamic_data = {}
12
+ self.static_data = {}
13
+ self.render_order = 99
14
+ self.set_outline_color((20, 20, 20))
15
+ # self.set_background_color((0,0,0,0))
16
+ self.set_text_color("white")
17
+ # self.set_padding((30,30))
18
+ self.set_refresh_rate(20)
19
+ self.add_dynamic_data("FPS", lambda: str(round(self.manager.get_fps())))
20
+ self.add_dynamic_data("BLITS", lambda: str(self.parent_scene.blit_calls))
21
+ self.set_visible(False)
22
+
23
+ def set_refresh_rate(self, val: int):
24
+ self.refresh_rate = val
25
+
26
+ def update(self, dt: float):
27
+ visible = self.manager._debugging == 1
28
+ self.set_visible(visible)
29
+ if not visible:
30
+ return
31
+ self._refresh_counter -= dt * 60
32
+ if self._refresh_counter < 0:
33
+ self._refresh_counter = self.refresh_rate
34
+ self._refresh_debug_info()
35
+
36
+ def add_dynamic_data(self, key, func):
37
+ self.dynamic_data[key] = func
38
+
39
+ def set_static_data(self, key, value):
40
+ self.static_data[key] = value
41
+
42
+ def _refresh_debug_info(self):
43
+ lines = []
44
+ lines.extend([f"{key}:{value}" for key, value in self.static_data.items()])
45
+ lines.extend([f"{key}:{func()}" for key, func in self.dynamic_data.items()])
46
+ debug_text = "\n".join(lines)
47
+ self.set_text(debug_text)
48
+ self.update_surface() # Update the surface after modifying the text
@@ -2,16 +2,15 @@ import pygame
2
2
  import batFramework as bf
3
3
  from typing import Self
4
4
 
5
-
6
5
  class DynamicEntity(bf.Entity):
7
6
  def __init__(
8
7
  self,
9
- size: None | tuple[int, int] = None,
10
- no_surface: bool = False,
11
- surface_flags: int = 0,
12
- convert_alpha: bool = False,
8
+ size : None|tuple[int,int]=None,
9
+ no_surface : bool =False,
10
+ surface_flags : int =0,
11
+ convert_alpha : bool=False
13
12
  ) -> None:
14
- super().__init__(size, no_surface, surface_flags, convert_alpha)
13
+ super().__init__(size,no_surface,surface_flags,convert_alpha)
15
14
  self.velocity = pygame.math.Vector2(0, 0)
16
15
 
17
16
  def on_collideX(self, collider: Self):
@@ -20,5 +19,5 @@ class DynamicEntity(bf.Entity):
20
19
  def on_collideY(self, collider: Self):
21
20
  return False
22
21
 
23
- def move_by_velocity(self,dt) -> None:
24
- self.set_position(self.rect.x + self.velocity.x * dt, self.rect.y + self.velocity.y * dt)
22
+ def move_by_velocity(self)->None:
23
+ self.set_position(self.rect.x + self.velocity.x, self.rect.y + self.velocity.y)
batFramework/easing.py CHANGED
@@ -2,51 +2,47 @@ from enum import Enum
2
2
  import pygame
3
3
  import batFramework as bf
4
4
 
5
-
6
5
  class Easing(Enum):
7
- EASE_IN = (0.12, 0, 0.39, 0)
8
- EASE_OUT = (0.61, 1, 0.88, 1)
6
+ EASE_IN = (0.12, 0, 0.39, 0)
7
+ EASE_OUT = (0.61, 1, 0.88, 1)
9
8
  EASE_IN_OUT = (0.37, 0, 0.63, 1)
10
- EASE_IN_OUT_ELASTIC = (0.7, -0.5, 0.3, 1.5)
11
- LINEAR = (1, 1, 0, 0)
9
+ EASE_IN_OUT_ELASTIC = (.7,-0.5,.3,1.5)
10
+ LINEAR = (1, 1, 0, 0)
12
11
  # Add more easing functions as needed
13
12
 
14
13
  def __init__(self, *control_points):
15
14
  self.control_points = control_points
16
15
 
17
-
18
16
  class EasingAnimation(bf.Timer):
19
17
  _cache = {}
20
-
21
18
  def __init__(
22
19
  self,
23
- name: str = '',
24
- easing_function: Easing = Easing.LINEAR,
25
- duration: int = 100,
20
+ name:str=None,
21
+ easing_function:Easing=Easing.LINEAR,
22
+ duration:int=100,
26
23
  update_callback=None,
27
24
  end_callback=None,
28
- loop: bool = False,
29
- reusable: bool = False,
30
- )->None:
25
+ loop:bool=False,
26
+ reusable:bool=False
27
+ ):
31
28
  self.easing_function = easing_function
32
29
  self.update_callback = update_callback
33
30
  self.value = 0.0
34
- super().__init__(name, duration, loop, end_callback, reusable)
35
-
31
+ super().__init__(name,duration,loop,end_callback,reusable)
32
+
36
33
  def get_value(self):
37
34
  return self.value
38
35
 
39
36
  def start(self):
40
- self.value = 0
41
- super().start() # self.elapsed_progress set to 0 here
42
-
43
- def update(self,dt) -> bool:
44
- if super().update(dt):
45
- return True # If timer ended now, end() is called. So don't process value.
37
+ self.value = 0
38
+ super().start() # self.elapsed_progress set to 0 here
39
+
40
+ def update(self)->bool:
41
+ if super().update():
42
+ return True# If timer ended now, end() is called. So don't process value.
46
43
  self._process_value()
47
44
  # if self.name == 0: print("UPDATING (callback) in easing")
48
- if self.update_callback:
49
- self.update_callback(self.value)
45
+ if self.update_callback: self.update_callback(self.value)
50
46
  return False
51
47
 
52
48
  def end(self):
@@ -54,14 +50,13 @@ class EasingAnimation(bf.Timer):
54
50
 
55
51
  self.elapsed_progress = 1
56
52
  self._process_value()
57
- if self.update_callback:
58
- self.update_callback(self.value)
59
- self.value = 0
60
- super().end() # sets elapsed_progress to 0
53
+ if self.update_callback: self.update_callback(self.value)
54
+ self.value = 0
55
+ super().end() # sets elapsed_progress to 0
61
56
 
62
57
  def _process_value(self):
63
58
  p0, p1, p2, p3 = self.easing_function.control_points
64
- cache_key = (self.easing_function,self.elapsed_progress, p0, p1, p2, p3)
59
+ cache_key = (self.elapsed_progress, p0, p1, p2, p3)
65
60
  if cache_key in EasingAnimation._cache:
66
61
  y = EasingAnimation._cache[cache_key]
67
62
  else:
batFramework/entity.py CHANGED
@@ -1,59 +1,51 @@
1
- from typing import Any, Self
2
1
  import pygame
3
2
  import batFramework as bf
3
+ from typing import Any
4
4
 
5
5
  class Entity:
6
- """
7
- Basic entity class
8
- """
9
- __instance_count = 0
10
-
6
+ instance_num = 0
11
7
  def __init__(
12
8
  self,
13
- size: None | tuple[int, int] = None,
14
- no_surface: bool = False,
15
- surface_flags: int = 0,
16
- convert_alpha: bool = False,
9
+ size : None|tuple[int,int]=None,
10
+ no_surface : bool =False,
11
+ surface_flags : int =0,
12
+ convert_alpha : bool=False
17
13
  ) -> None:
18
14
  self.convert_alpha = convert_alpha
19
15
  if size is None:
20
- size = (10, 10)
16
+ size= (100,100)
17
+
21
18
  if no_surface:
22
19
  self.surface = None
23
20
  else:
24
- self.surface = pygame.Surface(size, surface_flags)
25
-
21
+ self.surface = (pygame.Surface(size, surface_flags))
22
+
26
23
  if convert_alpha and self.surface is not None:
27
24
  self.surface = self.surface.convert_alpha()
28
- self.surface.fill((0, 0, 0, 0))
25
+ self.surface.fill((0,0,0,0))
29
26
 
30
- self.rect = pygame.FRect(0, 0, *size)
27
+ self.uid: Any = Entity.instance_num
31
28
  self.tags: list[str] = []
32
29
  self.parent_scene: bf.Scene | None = None
33
- self.visible: bool = True
34
- self.debug_color: tuple = bf.color.DARK_RED
35
- self.render_order: int = 0
36
- self.uid: Any = Entity.__instance_count
37
- Entity.__instance_count += 1
38
-
39
- def set_render_order(self, render_order: int) -> Self:
40
- self.render_order = render_order
41
- return self
30
+ self.rect = pygame.FRect(0, 0, *size)
31
+
32
+ self.visible = True
33
+ self._debug_color : tuple = bf.color.DARK_RED
34
+ self.render_order = 0
35
+ self.z_depth = 1
36
+ Entity.instance_num += 1
42
37
 
43
38
  def get_bounding_box(self):
44
- yield (self.rect, self.debug_color)
39
+ yield (self.rect,self._debug_color)
45
40
 
46
- def set_debug_color(self, color) -> Self:
47
- self.debug_color = color
48
- return self
41
+ def set_debug_color(self, color):
42
+ self._debug_color = color
49
43
 
50
- def set_visible(self, value: bool) -> Self:
44
+ def set_visible(self, value: bool):
51
45
  self.visible = value
52
- return self
53
46
 
54
- def set_parent_scene(self, scene) -> Self:
47
+ def set_parent_scene(self, scene):
55
48
  self.parent_scene = scene
56
- return self
57
49
 
58
50
  def do_when_added(self):
59
51
  pass
@@ -61,100 +53,71 @@ class Entity:
61
53
  def do_when_removed(self):
62
54
  pass
63
55
 
64
- def set_position(self, x, y) -> Self:
56
+ def set_position(self, x, y):
65
57
  self.rect.topleft = (x, y)
66
58
  return self
67
59
 
68
- def get_position(self) -> tuple:
69
- return self.rect.topleft
70
-
71
- def get_center(self) -> tuple:
72
- return self.rect.center
73
-
74
- def set_x(self, x) -> Self:
60
+ def set_x(self,x):
75
61
  self.rect.x = x
76
62
  return self
77
63
 
78
- def set_y(self, y) -> Self:
64
+ def set_y(self,y):
79
65
  self.rect.y = y
80
66
  return self
81
67
 
82
- def set_center(self, x, y) -> Self:
68
+ def set_center(self, x, y):
83
69
  self.rect.center = (x, y)
84
70
  return self
85
71
 
86
- def set_uid(self, uid) -> Self:
72
+ def set_uid(self, uid):
87
73
  self.uid = uid
88
74
  return self
89
75
 
90
- def add_tags(self, *tags) -> Self:
76
+ def add_tag(self, *tags):
91
77
  for tag in tags:
92
78
  if tag not in self.tags:
93
79
  self.tags.append(tag)
94
80
  self.tags.sort()
95
81
  return self
96
82
 
97
- def remove_tags(self, *tags):
83
+ def remove_tag(self, *tags):
98
84
  self.tags = [tag for tag in self.tags if tag not in tags]
85
+ self.tags.sort()
99
86
 
100
- def has_tags(self, *tags) -> bool:
101
- return all(tag in self.tags for tag in tags)
102
-
103
- def get_tags(self) -> list[str]:
104
- return self.tags
87
+ def has_tag(self, tag) -> bool:
88
+ return tag in self.tags
105
89
 
106
- def process_event(self, event: pygame.Event) -> bool:
90
+ def process_event(self, event: pygame.Event)->bool:
107
91
  """
108
92
  Returns bool : True if the method is blocking (no propagation to next children of the scene)
109
93
  """
110
94
  self.do_process_actions(event)
111
- res = self.do_handle_actions()
112
- res = res or self.do_handle_event(event)
95
+ res = self.do_handle_event(event)
113
96
  self.do_reset_actions()
114
97
  return res
115
98
 
99
+ def do_process_actions(self,event : pygame.Event)->None:
100
+ pass
116
101
 
117
-
118
- def do_process_actions(self, event: pygame.Event) -> None:
119
- """
120
- Process entity actions you may have set
121
- """
122
-
123
- def do_reset_actions(self) -> None:
124
- """
125
- Reset entity actions you may have set
126
- """
127
-
128
- def do_handle_actions(self) ->None:
129
- """
130
- Handle entity actions
131
- """
132
-
102
+ def do_reset_actions(self)->None:
103
+ pass
104
+
133
105
  def do_handle_event(self, event: pygame.Event) -> bool:
134
- """
135
- Handle specific
136
- """
137
-
138
106
  return False
139
107
 
140
108
  def update(self, dt: float):
141
- """
142
- Update method to be overriden by subclasses of widget
143
- """
144
109
  self.do_update(dt)
145
110
 
146
- def do_update(self, dt: float):
147
- """
148
- Update method to be overriden for specific behavior by the end user
149
- """
111
+ def do_update(self,dt:float):
112
+ pass
150
113
 
151
114
  def draw(self, camera: bf.Camera) -> int:
152
- """
153
- Draw the entity onto the camera with coordinate transposing
154
- """
155
- should_not_draw = not self.visible or not self.surface or not camera.intersects(self.rect)
156
- if should_not_draw:
157
- return 0
158
- camera.surface.blit(self.surface, camera.transpose(self.rect))
159
-
160
- return 1
115
+ if not self.visible:
116
+ return False
117
+ if not self.surface or not camera.intersects(self.rect):
118
+ return False
119
+ camera.surface.blit(
120
+ self.surface,
121
+ tuple(round(i * self.z_depth) for i in camera.transpose(self.rect).topleft),
122
+ )
123
+ return True
@@ -6,10 +6,8 @@ from .root import Root
6
6
  from .shape import Shape
7
7
  from .frame import Frame
8
8
  from .label import Label
9
- from .dialogueBox import DialogueBox
10
- from .textInput import TextInput
11
9
  from .button import Button
12
- from .debugger import *
10
+ from .debugger import Debugger
13
11
  from .layout import *
14
12
  from .container import Container
15
13
  from .indicator import *
@@ -1,61 +1,25 @@
1
1
  from .label import Label
2
2
  import batFramework as bf
3
- from typing import Self,Callable
3
+ from types import FunctionType
4
+ from typing import Self
4
5
  from .interactiveWidget import InteractiveWidget
5
6
  import pygame
6
7
 
7
-
8
- class Button(Label, InteractiveWidget):
9
- _cache :dict = {}
10
-
11
- def __init__(self, text: str, callback: None| Callable = None) -> None:
12
- # Label.__init__(self,text)
13
- self.callback = callback
14
- self.is_hovered: bool = False
15
- self.effect_max :float= 20
16
- self.effect_speed :float= 1.8
8
+ class Button(Label,InteractiveWidget):
9
+ _cache = {}
10
+
11
+ def __init__(self, text: str, callback : FunctionType =None) -> None:
12
+ # Label.__init__(self,text)
13
+ self.callback = callback
14
+ self.click_action = bf.Action("click").add_mouse_control(1)
15
+ self.hover_action = bf.Action("hover").add_mouse_control(pygame.MOUSEMOTION)
16
+ self.is_hovered : bool = False
17
17
  self.is_clicking : bool = False
18
- self.effect :float = 0
19
- self.enabled :bool = True
20
18
  super().__init__(text=text)
21
19
  self.set_debug_color("cyan")
22
- self.focusable = True
23
-
24
- def get_surface_filter(self) -> pygame.Surface | None:
25
- if not self.surface:
26
- return None
27
-
28
- size = self.surface.get_size()
29
- surface_filter = Button._cache.get(size, None)
30
-
31
- if surface_filter is None:
32
- # Create a mask from the original surface
33
- mask = pygame.mask.from_surface(self.surface,threshold=0)
34
-
35
- # Get the bounding box of the mask
36
- silhouette_surface = mask.to_surface(
37
- setcolor = (30,30,30),unsetcolor= (255,255,255)
38
- ).convert_alpha()
39
-
40
20
 
41
- Button._cache[size] = silhouette_surface
42
- surface_filter = silhouette_surface
43
21
 
44
- return surface_filter
45
- def enable(self)->Self:
46
- self.enabled = True
47
- self.build()
48
- return self
49
-
50
- def disable(self)->Self:
51
- self.enabled = False
52
- self.build()
53
- return self
54
-
55
- def is_enabled(self)->bool:
56
- return self.enabled
57
-
58
- def set_callback(self, callback: Callable) -> Self:
22
+ def set_callback(self,callback : FunctionType = None)->Self:
59
23
  self.callback = callback
60
24
  return self
61
25
 
@@ -67,84 +31,54 @@ class Button(Label, InteractiveWidget):
67
31
  super().on_lose_focus()
68
32
  self.build()
69
33
 
70
- def to_string_id(self) -> str:
71
- return f"Button({self._text}){'' if self.enabled else '[disabled]'}"
72
-
73
- def click(self) -> None:
74
- if self.callback is not None:
75
- self.callback()
76
- bf.Timer(duration=0.3,end_callback=self._safety_effect_end).start()
77
-
78
- def _safety_effect_end(self)->None:
79
- if self.effect > 0:
80
- self.effect = 0
81
- self.build()
82
-
83
- def start_effect(self):
84
- if self.effect <= 0 : self.effect = self.effect_max
34
+ def to_string_id(self)->str:
35
+ return f"Button({self._text})"
85
36
 
86
-
87
- def do_on_click_down(self,button)->None:
88
- if self.enabled and button == 1 and self.effect == 0:
89
- if not self.get_focus():return
37
+ def click(self)->None:
38
+ if self.callback and not self.is_clicking:
90
39
  self.is_clicking = True
91
- self.start_effect()
92
-
93
- def do_on_click_up(self,button)->None:
94
- if self.enabled and button == 1 and self.is_clicking:
95
- # self.effect = 0
40
+ self.callback()
96
41
  self.is_clicking = False
97
- self.build()
98
- self.click()
99
-
100
- def on_enter(self)->None:
101
- if not self.enabled : return
102
- super().on_enter()
103
- self.effect = 0
104
- self.build()
105
- pygame.mouse.set_cursor(*pygame.cursors.tri_left)
106
-
107
- def on_exit(self)->None:
108
- super().on_exit()
109
- # self.effect = 0
110
- self.is_clicking = False
111
- self.build()
112
- pygame.mouse.set_cursor(pygame.cursors.arrow)
113
-
114
-
115
-
116
- def update(self,dt):
117
- super().update(dt)
118
- if self.effect <= 0: return
119
- self.effect -= dt*60*self.effect_speed
120
- if self.is_clicking:
121
- if self.effect < 1 : self.effect = 1
122
- else:
123
- if self.effect < 0 : self.effect = 0
124
- self.build()
125
-
126
- def _build_effect(self)->None:
127
- if self.effect < 1 : return
128
- e = int(min(self.rect.w //3, self.rect.h//3,self.effect))
129
- pygame.draw.rect(
130
- self.surface,
131
- bf.color.CLOUD_WHITE,
132
- (0,0,*self.surface.get_size()),
133
- #int(self.effect),
134
- e,
135
- *self._border_radius
136
- )
137
- def _build_disabled(self)->None:
138
- self.surface.blit(self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_SUB)
42
+
43
+
44
+ def do_process_actions(self,event):
45
+ self.click_action.process_event(event)
46
+ self.hover_action.process_event(event)
47
+
48
+ def do_reset_actions(self):
49
+ self.click_action.reset()
50
+ self.hover_action.reset()
51
+
52
+ def do_handle_event(self,event)->None:
53
+ res = False
54
+ if self.click_action.is_active():
55
+ root = self.get_root()
56
+ if root.hovered == self:
57
+ if not self.is_focused : self.get_focus()
58
+ self.click()
59
+ elif self.hover_action.is_active():
60
+ root = self.get_root()
61
+ if root:
62
+ if self.is_hovered and root.hovered != self:
63
+ self.is_hovered = False
64
+ self.build()
65
+ if not self.is_hovered and root.hovered == self:
66
+ self.is_hovered = True
67
+ self.build()
68
+ return res
69
+
70
+
71
+
72
+ def build(self)->None:
73
+ super().build()
74
+ if self.is_hovered:
75
+ hover_surf = Button._cache.get(self.surface.get_size(),None)
76
+ if hover_surf is None:
77
+ hover_surf = pygame.Surface(self.surface.get_size()).convert_alpha()
78
+ hover_surf.fill((30,30,30,0))
79
+ Button._cache[self.surface.get_size()] = hover_surf
80
+ self.surface.blit(hover_surf,(0,0),special_flags = pygame.BLEND_ADD)
139
81
 
140
- def _build_hovered(self)->None:
141
- self.surface.blit(self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_ADD)
142
82
 
143
- def build(self) -> None:
144
- super().build()
145
- if not self.enabled:
146
- self._build_disabled()
147
- elif self.is_hovered:
148
- self._build_hovered()
149
- if self.effect:
150
- self._build_effect()
83
+ def apply_contraints(self)->None:
84
+ super().apply_contraints()