batframework 1.0.9a11__py3-none-any.whl → 1.1.0__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 (76) hide show
  1. batFramework/__init__.py +52 -76
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +114 -56
  5. batFramework/audioManager.py +36 -82
  6. batFramework/camera.py +69 -263
  7. batFramework/constants.py +53 -29
  8. batFramework/cutscene.py +109 -243
  9. batFramework/cutsceneBlocks.py +176 -0
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -16
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +85 -92
  14. batFramework/gui/__init__.py +3 -14
  15. batFramework/gui/button.py +78 -12
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +31 -188
  18. batFramework/gui/debugger.py +43 -126
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -55
  21. batFramework/gui/indicator.py +22 -95
  22. batFramework/gui/interactiveWidget.py +12 -229
  23. batFramework/gui/label.py +77 -311
  24. batFramework/gui/layout.py +66 -414
  25. batFramework/gui/root.py +35 -203
  26. batFramework/gui/shape.py +57 -247
  27. batFramework/gui/toggle.py +48 -114
  28. batFramework/gui/widget.py +243 -457
  29. batFramework/manager.py +29 -113
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +217 -22
  32. batFramework/sceneManager.py +129 -161
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +75 -0
  35. batFramework/transition.py +124 -129
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +4 -4
  38. batFramework/utils.py +144 -266
  39. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/METADATA +24 -22
  40. batframework-1.1.0.dist-info/RECORD +43 -0
  41. batFramework/animation.py +0 -77
  42. batFramework/baseScene.py +0 -240
  43. batFramework/cutsceneManager.py +0 -34
  44. batFramework/drawable.py +0 -77
  45. batFramework/easingController.py +0 -58
  46. batFramework/enums.py +0 -135
  47. batFramework/fontManager.py +0 -65
  48. batFramework/gui/animatedLabel.py +0 -89
  49. batFramework/gui/clickableWidget.py +0 -244
  50. batFramework/gui/constraints/__init__.py +0 -1
  51. batFramework/gui/constraints/constraints.py +0 -980
  52. batFramework/gui/draggableWidget.py +0 -44
  53. batFramework/gui/meter.py +0 -96
  54. batFramework/gui/radioButton.py +0 -35
  55. batFramework/gui/selector.py +0 -250
  56. batFramework/gui/slider.py +0 -397
  57. batFramework/gui/style.py +0 -10
  58. batFramework/gui/styleManager.py +0 -54
  59. batFramework/gui/syncedVar.py +0 -49
  60. batFramework/gui/textInput.py +0 -306
  61. batFramework/gui/tooltip.py +0 -30
  62. batFramework/particle.py +0 -118
  63. batFramework/propertyEaser.py +0 -79
  64. batFramework/renderGroup.py +0 -34
  65. batFramework/resourceManager.py +0 -130
  66. batFramework/sceneLayer.py +0 -138
  67. batFramework/scrollingSprite.py +0 -115
  68. batFramework/sprite.py +0 -51
  69. batFramework/templates/__init__.py +0 -1
  70. batFramework/templates/controller.py +0 -97
  71. batFramework/tileset.py +0 -46
  72. batFramework/timeManager.py +0 -213
  73. batframework-1.0.9a11.dist-info/RECORD +0 -67
  74. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/LICENSE +0 -0
  75. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/WHEEL +0 -0
  76. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/top_level.txt +0 -0
batFramework/manager.py CHANGED
@@ -1,134 +1,50 @@
1
1
  import batFramework as bf
2
2
  import pygame
3
- import asyncio
3
+ import random
4
4
 
5
5
  class Manager(bf.SceneManager):
6
- def __init__(self, *initial_scenes) -> None:
7
- super().__init__()
8
- self.debug_mode: bf.enums.debugMode = bf.debugMode.HIDDEN
9
- self.screen: pygame.Surface | None = bf.const.SCREEN
10
- self.timeManager = bf.TimeManager()
11
- self.cutsceneManager = bf.CutsceneManager()
12
- self.cutsceneManager.set_manager(self)
13
- self.clock: pygame.Clock = pygame.Clock()
14
- self.is_async_running : bool = False
15
- self.running = False
16
- pygame.mouse.set_cursor(bf.const.DEFAULT_CURSOR)
17
- bf.ResourceManager().set_sharedVar("clock", self.clock)
18
- bf.ResourceManager().set_sharedVar("debug_mode", self.debug_mode)
19
-
20
- self.do_pre_init()
21
- if initial_scenes:
22
- self.init_scenes(*initial_scenes)
6
+ def __init__(self, *initial_scene_list) -> None:
7
+ random.seed("random")
8
+ self._screen: pygame.Surface = bf.const.SCREEN
9
+ self._timeManager = bf.Time()
10
+ self._cutsceneManager = bf.CutsceneManager(self)
11
+ self._clock: pygame.Clock = pygame.Clock()
12
+ super().__init__(*initial_scene_list)
13
+ self.set_sharedVar("clock", self._clock)
23
14
  self.do_init()
24
15
 
25
16
  @staticmethod
26
- def set_icon(path: str) -> None:
27
- surf = pygame.image.load(bf.ResourceManager().get_path(path)).convert_alpha()
17
+ def set_icon(path: str):
18
+ surf = pygame.image.load(bf.utils.get_path(path)).convert_alpha()
28
19
  pygame.display.set_icon(surf)
29
20
 
30
- def print_status(self):
31
- """
32
- Print detailed information about the current state of the scenes, shared variables,
33
- and additional timers managed by the subclass.
34
- """
35
- # Call the parent class's print_status method to include its information
36
- super().print_status()
37
-
38
- # Add the timers information in a cohesive manner
39
- print("\n" + "=" * 50)
40
- print(" TIMERS".center(50))
41
- print("=" * 50)
42
-
43
- # Print the timers information
44
- print(self.timeManager)
45
-
46
- # End with a visual separator
47
- print("=" * 50 + "\n")
21
+ def get_fps(self):
22
+ return self._clock.get_fps()
48
23
 
49
-
50
- def get_fps(self) -> float:
51
- return self.clock.get_fps()
52
-
53
- def do_init(self) -> None:
24
+ def do_init(self):
54
25
  pass
55
26
 
56
- def do_pre_init(self) -> None:
57
- pass
58
-
59
- def stop(self) -> None:
60
- self.running = False
61
-
62
- def process_event(self, event: pygame.Event):
63
- event.consumed = False
64
- keys = pygame.key.get_pressed()
65
- if (
66
- bf.const.ALLOW_DEBUG and
67
- keys[pygame.K_LCTRL]
68
- and keys[pygame.K_LSHIFT]
69
- and event.type == pygame.KEYDOWN
70
- ):
71
- if event.key == pygame.K_d:
72
- self.cycle_debug_mode()
73
- return
74
- if event.key == pygame.K_p:
75
- self.print_status()
76
- return
77
- self.cutsceneManager.process_event(event)
78
- if event.type == pygame.VIDEORESIZE and not (bf.const.FLAGS & pygame.SCALED):
79
- bf.const.set_resolution((event.w, event.h))
80
-
81
- if event.consumed: return
82
-
83
- super().process_event(event)
84
- if not event.consumed:
85
- if event.type == pygame.QUIT:
86
- self.running = False
87
-
88
- def update(self, dt: float) -> None:
89
- self.timeManager.update(dt)
90
- self.cutsceneManager.update(dt)
91
- super().update(dt)
92
-
93
-
94
- async def run_async(self):
95
- if len(self.scenes) == 0:
96
- raise Exception("Manager can't start without scenes")
97
- if self.running:
98
- raise Exception("Error : Already running")
99
- self.is_async_running = True
100
- self.running = True
101
- dt: float = 0
102
- while self.running:
103
- for event in pygame.event.get():
104
- self.process_event(event)
105
- # update
106
- self.update(dt)
107
- # render
108
- self.draw(self.screen)
109
- pygame.display.flip()
110
- dt = self.clock.tick(bf.const.FPS) / 1000
111
- dt = min(dt, 0.02) # dirty fix for dt being too high when window not focused for a long time
112
- await asyncio.sleep(0)
113
- pygame.quit()
114
-
27
+ def stop(self)->None:
28
+ self._running = False
115
29
 
116
- def run(self) -> None:
117
- if len(self.scenes) == 0:
118
- raise Exception("Manager can't start without scenes")
119
- if self.running:
120
- raise Exception("Error : Already running")
121
- return
122
- self.running = True
30
+ def run(self):
31
+ self._running = True
123
32
  dt: float = 0
124
- while self.running:
33
+ while self._running:
125
34
  for event in pygame.event.get():
35
+ if event.type == pygame.QUIT:
36
+ self._running = False
37
+ break
38
+ if event.type == pygame.VIDEORESIZE:
39
+ bf.const.set_resolution((event.w,event.h))
126
40
  self.process_event(event)
127
41
  # update
42
+ dt = self._clock.tick(bf.const.FPS if not bf.const.VSYNC else 0) / 1000
43
+ dt = min(dt, 0.02)
44
+ self._cutsceneManager.update(dt)
45
+ self._timeManager.update()
128
46
  self.update(dt)
129
47
  # render
130
- self.draw(self.screen)
48
+ self.draw(self._screen)
131
49
  pygame.display.flip()
132
- dt = self.clock.tick(bf.const.FPS) / 1000
133
- dt = min(dt, 0.02) # dirty fix for dt being too high when window not focused for a long time
134
50
  pygame.quit()
@@ -0,0 +1,77 @@
1
+ import batFramework as bf
2
+ import pygame
3
+ from pygame.math import Vector2
4
+
5
+
6
+ class Particle:
7
+ def __init__(
8
+ self,
9
+ start_pos: tuple[float, float],
10
+ start_vel: tuple[float, float],
11
+ duration=1000,
12
+ color=None,
13
+ size = (4,4)
14
+ ):
15
+ self.rect = pygame.FRect(*start_pos, 0, 0)
16
+ self.surface = pygame.Surface(size).convert()
17
+ if color:
18
+ self.surface.fill(color)
19
+ self.velocity = Vector2(*start_vel)
20
+ self.start_time = pygame.time.get_ticks()
21
+ self.duration = duration
22
+ self.dead = False
23
+ self.progression = 0
24
+ self.z_depth = 1
25
+
26
+ def update(self, dt):
27
+ if self.dead:
28
+ return
29
+ elapsed_time = pygame.time.get_ticks() - self.start_time
30
+ self.progression = elapsed_time / self.duration
31
+ self.dead = elapsed_time >= self.duration
32
+ self.rect.center += self.velocity * dt
33
+ self.update_surface()
34
+
35
+ def kill(self):
36
+ self.dead = True
37
+
38
+ def update_surface(self):
39
+ self.surface.set_alpha(255 - int(self.progression * 255))
40
+
41
+
42
+ class ParticleManager(bf.Entity):
43
+ def __init__(self) -> None:
44
+ super().__init__(size=bf.const.RESOLUTION)
45
+ self.particles: list[Particle] = []
46
+
47
+ def get_bounding_box(self):
48
+ for particle in self.particles:
49
+ yield particle.rect
50
+
51
+ def add_particle(self, particle_class=Particle, **kwargs):
52
+ self.particles.append(particle_class(**kwargs))
53
+
54
+
55
+ def clear(self):
56
+ self.particles = []
57
+
58
+
59
+ def update(self, dt: float):
60
+ particles_to_remove = []
61
+ for particle in self.particles:
62
+ particle.update(dt)
63
+ if particle.dead:
64
+ particles_to_remove.append(particle)
65
+ for p in particles_to_remove:
66
+ self.particles.remove(p)
67
+
68
+ def draw(self, camera) -> bool:
69
+ camera.surface.fblits(
70
+ [
71
+ (
72
+ p.surface,
73
+ tuple(round(i * self.z_depth) for i in camera.transpose(self.rect).topleft)
74
+ ) for p in self.particles
75
+ ]
76
+ )
77
+ return len(self.particles)
batFramework/scene.py CHANGED
@@ -1,31 +1,226 @@
1
- from .baseScene import BaseScene
1
+ from __future__ import annotations
2
+ import re
3
+ from typing import TYPE_CHECKING,Any
4
+ if TYPE_CHECKING:
5
+ from .manager import Manager
6
+ import pygame
2
7
  import batFramework as bf
3
8
 
4
9
 
5
- class Scene(BaseScene):
6
- def __init__(self,name: str) -> None:
10
+ class Scene:
11
+ def __init__(self, name, enable_alpha=True) -> None:
12
+ self._name = name
13
+ self._active = False
14
+ self._visible = False
15
+ self._world_entities: list[bf.Entity] = []
16
+ self._hud_entities: list[bf.Entity] = []
17
+ self.manager: Manager | None = None
18
+ self.actions: bf.ActionContainer = bf.ActionContainer()
19
+ self.camera: bf.Camera = bf.Camera()
20
+ self.scene_index = 0
21
+ self.hud_camera: bf.Camera = bf.Camera()
22
+ if enable_alpha:
23
+ self.camera.surface = self.camera.surface.convert_alpha()
24
+ self.hud_camera.surface = self.camera.surface.convert_alpha()
25
+
26
+ self.camera.set_clear_color((0, 0, 0))
27
+ self.hud_camera.set_clear_color((0, 0, 0, 0))
28
+
29
+ self.root : bf.Root = bf.Root()
30
+ self.root.set_center(*self.hud_camera.get_center())
31
+ self.add_hud_entity(self.root)
32
+ self.blit_calls = 0
33
+
34
+ def set_scene_index(self,index):
35
+ self.scene_index = index
36
+
37
+ def get_scene_index(self):
38
+ return self.scene_index
39
+
40
+ def set_sharedVar(self, name, value)->bool:
41
+ if not self.manager : return False
42
+ return self.manager.set_sharedVar(name, value)
43
+
44
+ def get_sharedVar(self, name)->Any:
45
+ if not self.manager : return False
46
+ return self.manager.get_sharedVar(name)
47
+
48
+ def do_when_added(self):
49
+ pass
50
+
51
+ def set_clear_color(self, color: pygame.Color|tuple):
52
+ self.camera.set_clear_color(color)
53
+ # self.hud_camera.set_clear_color(color)
54
+
55
+ def set_manager(self, manager_link: Manager):
56
+ self.manager = manager_link
57
+
58
+ def set_visible(self, value: bool):
59
+ self._visible = value
60
+ if self.manager : self.manager.update_scene_states()
61
+
62
+ def set_active(self, value):
63
+ self._active = value
64
+ if self.manager : self.manager.update_scene_states()
65
+
66
+ def is_active(self) -> bool:
67
+ return self._active
68
+
69
+ def is_visible(self) -> bool:
70
+ return self._visible
71
+
72
+ def get_name(self) -> str:
73
+ return self._name
74
+
75
+ def add_world_entity(self, *entity: bf.Entity):
76
+ for e in entity:
77
+ if e not in self._world_entities:
78
+
79
+ self._world_entities.append(e)
80
+ e.parent_scene = self
81
+ e.do_when_added()
82
+
83
+ def remove_world_entity(self, *entity: bf.Entity):
84
+ for e in entity:
85
+ if e not in self._world_entities:
86
+ return False
87
+ e.do_when_removed()
88
+ e.parent_scene = None
89
+ self._world_entities.remove(e)
90
+ return True
91
+
92
+ def add_hud_entity(self, *entity: bf.Entity):
93
+ for e in entity:
94
+ if e not in self._hud_entities:
95
+ self._hud_entities.append(e)
96
+ e.parent_scene = self
97
+ e.do_when_added()
98
+
99
+ def remove_hud_entity(self, *entity: bf.Entity):
100
+ for e in entity:
101
+ if e in self._hud_entities:
102
+ e.do_when_removed()
103
+ e.parent_scene = None
104
+ self._hud_entities.remove(e)
105
+
106
+ def add_action(self, *action):
107
+ self.actions.add_action(*action)
108
+
109
+ def get_by_tags(self, *tags):
110
+ return [
111
+ entity
112
+ for entity in self._world_entities + self._hud_entities
113
+ if any(entity.has_tag(t) for t in tags)
114
+ ]
115
+
116
+ def get_by_uid(self, uid) -> bf.Entity | None:
117
+ return next(
118
+ (
119
+ entity
120
+ for entity in self._world_entities + self._hud_entities
121
+ if entity.uid == uid
122
+ ),
123
+ None,
124
+ )
125
+
126
+ # called before process event
127
+ def do_early_process_event(self, event: pygame.Event) -> bool:
128
+ """return True if stop event propagation in child entities and scene's action container"""
129
+ return False
130
+
131
+ # propagates event to all entities
132
+ def process_event(self, event: pygame.Event):
7
133
  """
8
- Default Scene object.
9
- Has 2 layers (world and hud) by default
10
- Contains an exposed root gui object on the hud layer
11
- Args:
12
- name: Name of the scene.
134
+ Propagates event to child events. Calls early process event first, if returns False then stops. Processes scene's action_container, then custom do_handle_event function.
135
+ Finally resets the action_container, and propagates to all child entities. if any of them returns True, the propagation is stopped.
13
136
  """
14
- super().__init__(name)
15
- self.add_layer(bf.SceneLayer("world",True))
16
- hud_layer = bf.SceneLayer("hud",True)
17
- self.add_layer(hud_layer)
18
- self.root: bf.gui.Root = bf.gui.Root(hud_layer.camera)
19
- self.root.rect.center = hud_layer.camera.get_center()
20
- self.add("hud",self.root)
21
- self.entities_to_remove = []
22
- self.entities_to_add = []
137
+ if self.get_sharedVar("in_transition"):
138
+ return
139
+ if self.do_early_process_event(event):
140
+ return
141
+ self.actions.process_event(event)
142
+ self.do_handle_event(event)
143
+ for entity in self._world_entities + self._hud_entities:
144
+ if entity.process_event(event):
145
+ break
146
+ self.actions.reset()
147
+
148
+ def do_handle_event(self, event: pygame.Event):
149
+ """called inside process_event but before resetting the scene's action container and propagating event to child entities of the scene"""
150
+ pass
151
+
152
+ def update(self, dt):
153
+ for entity in self._world_entities + self._hud_entities:
154
+ entity.update(dt)
155
+ self.do_update(dt)
156
+ self.camera.update(dt)
157
+ self.hud_camera.update(dt)
158
+
159
+ def do_update(self, dt):
160
+ pass
161
+
162
+ def debug_entity(self, entity: bf.Entity, camera: bf.Camera):
163
+ # return
164
+ if not entity.visible:
165
+ return
166
+ for data in entity.get_bounding_box():
167
+ if isinstance(data,pygame.FRect):
168
+ rect = data
169
+ color = entity._debug_color
170
+ else:
171
+ rect = data[0]
172
+ color = data[1]
173
+ if not isinstance(color,pygame.Color): color = pygame.Color(color)
174
+
175
+ pygame.draw.rect(camera.surface, color , camera.transpose(rect), 1)
176
+
177
+ def draw(self, surface: pygame.Surface):
178
+ self._world_entities.sort(key=lambda e: (e.z_depth,e.render_order))
179
+ self._hud_entities.sort(key=lambda e: (e.z_depth,e.render_order))
180
+
181
+ total_blit_calls = 0
182
+ self.camera.clear()
183
+ self.hud_camera.clear()
184
+
185
+
186
+ total_blit_calls += sum(
187
+ entity.draw(self.camera) for entity in self._world_entities
188
+ )
189
+
190
+ if self.manager and self.manager._debugging == 2:
191
+ for entity in self._world_entities:
192
+ self.debug_entity(entity, self.camera)
193
+
194
+ total_blit_calls += sum(
195
+ entity.draw(self.hud_camera) for entity in self._hud_entities
196
+ )
197
+ if self.manager and self.manager._debugging == 2:
198
+ for entity in self._hud_entities:
199
+ self.debug_entity(entity, self.hud_camera)
200
+
201
+
202
+ self.do_early_draw(surface)
203
+ self.camera.draw(surface)
204
+ self.do_post_world_draw(surface)
205
+ self.hud_camera.draw(surface)
206
+ self.do_final_draw(surface)
207
+
208
+ self.blit_calls = total_blit_calls
209
+
210
+ def do_early_draw(self, surface: pygame.Surface):
211
+ pass
212
+
213
+ def do_post_world_draw(self, surface: pygame.Surface):
214
+ pass
215
+
216
+ def do_final_draw(self, surface: pygame.Surface):
217
+ pass
23
218
 
24
219
  def on_enter(self):
25
- self.root.clear_hovered()
26
- self.root.build()
27
- super().on_enter()
220
+ self.set_active(True)
221
+ self.set_visible(True)
28
222
 
29
223
  def on_exit(self):
30
- self.root.clear_hovered()
31
- super().on_exit()
224
+ self.set_active(False)
225
+ self.set_visible(False)
226
+ self.actions.hard_reset()