batframework 1.0.9a7__py3-none-any.whl → 1.0.9a9__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 (62) hide show
  1. batFramework/__init__.py +20 -11
  2. batFramework/action.py +1 -1
  3. batFramework/animatedSprite.py +47 -116
  4. batFramework/animation.py +30 -5
  5. batFramework/audioManager.py +8 -5
  6. batFramework/baseScene.py +240 -0
  7. batFramework/camera.py +4 -0
  8. batFramework/constants.py +6 -2
  9. batFramework/cutscene.py +221 -21
  10. batFramework/cutsceneManager.py +5 -2
  11. batFramework/drawable.py +7 -5
  12. batFramework/easingController.py +10 -11
  13. batFramework/entity.py +21 -2
  14. batFramework/enums.py +48 -33
  15. batFramework/gui/__init__.py +6 -3
  16. batFramework/gui/animatedLabel.py +10 -2
  17. batFramework/gui/button.py +4 -31
  18. batFramework/gui/clickableWidget.py +63 -50
  19. batFramework/gui/constraints/constraints.py +212 -136
  20. batFramework/gui/container.py +77 -58
  21. batFramework/gui/debugger.py +12 -17
  22. batFramework/gui/draggableWidget.py +21 -17
  23. batFramework/gui/image.py +3 -10
  24. batFramework/gui/indicator.py +56 -1
  25. batFramework/gui/interactiveWidget.py +127 -108
  26. batFramework/gui/label.py +73 -64
  27. batFramework/gui/layout.py +286 -445
  28. batFramework/gui/meter.py +42 -20
  29. batFramework/gui/radioButton.py +20 -69
  30. batFramework/gui/root.py +99 -29
  31. batFramework/gui/selector.py +250 -0
  32. batFramework/gui/shape.py +13 -5
  33. batFramework/gui/slider.py +262 -107
  34. batFramework/gui/syncedVar.py +49 -0
  35. batFramework/gui/textInput.py +46 -22
  36. batFramework/gui/toggle.py +70 -52
  37. batFramework/gui/tooltip.py +30 -0
  38. batFramework/gui/widget.py +222 -135
  39. batFramework/manager.py +7 -8
  40. batFramework/particle.py +4 -1
  41. batFramework/propertyEaser.py +79 -0
  42. batFramework/renderGroup.py +17 -50
  43. batFramework/resourceManager.py +43 -13
  44. batFramework/scene.py +15 -335
  45. batFramework/sceneLayer.py +138 -0
  46. batFramework/sceneManager.py +31 -36
  47. batFramework/scrollingSprite.py +8 -3
  48. batFramework/sprite.py +1 -1
  49. batFramework/templates/__init__.py +1 -2
  50. batFramework/templates/controller.py +97 -0
  51. batFramework/timeManager.py +76 -22
  52. batFramework/transition.py +37 -103
  53. batFramework/utils.py +125 -66
  54. {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/METADATA +24 -3
  55. batframework-1.0.9a9.dist-info/RECORD +67 -0
  56. {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/WHEEL +1 -1
  57. batFramework/character.py +0 -27
  58. batFramework/templates/character.py +0 -43
  59. batFramework/templates/states.py +0 -166
  60. batframework-1.0.9a7.dist-info/RECORD +0 -63
  61. /batframework-1.0.9a7.dist-info/LICENCE → /batframework-1.0.9a9.dist-info/LICENSE +0 -0
  62. {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/top_level.txt +0 -0
batFramework/__init__.py CHANGED
@@ -1,4 +1,6 @@
1
+ import os
1
2
  import pygame
3
+ import json
2
4
  import batFramework as bf
3
5
  from .constants import Constants as const
4
6
  from .utils import Singleton
@@ -9,8 +11,9 @@ from .utils import Utils as utils
9
11
  from .tileset import Tileset
10
12
  from .timeManager import TimeManager,Timer,SceneTimer
11
13
  from .easingController import EasingController
14
+ from .propertyEaser import PropertyEaser
12
15
  from .cutsceneManager import CutsceneManager
13
- from .cutscene import *
16
+ import batFramework.cutscene as cutscene
14
17
  from .audioManager import AudioManager
15
18
  import batFramework.transition as transition
16
19
  from .action import Action
@@ -25,18 +28,18 @@ from .scrollingSprite import ScrollingSprite
25
28
  from .particle import *
26
29
  from .animation import Animation
27
30
  from .animatedSprite import AnimatedSprite
28
- from .character import Character
29
31
  from .stateMachine import State, StateMachine
32
+ from .sceneLayer import SceneLayer
30
33
  from .scene import Scene
31
- from .gui import *
34
+ from .baseScene import BaseScene
35
+ import batFramework.gui as gui
32
36
  from .sceneManager import SceneManager
33
37
  from .manager import Manager
34
38
  from .templates import *
35
- import importlib.metadata
36
39
 
37
40
 
38
41
  def init_screen(resolution: tuple[int, int], flags: int = 0, vsync: int = 0):
39
- const.RESOLUTION = resolution
42
+ const.set_resolution(resolution)
40
43
  const.FLAGS = flags
41
44
  const.VSYNC = vsync
42
45
  const.SCREEN = pygame.display.set_mode(
@@ -46,13 +49,19 @@ def init_screen(resolution: tuple[int, int], flags: int = 0, vsync: int = 0):
46
49
  f"Window : {resolution[0]}x{resolution[1]}"
47
50
  )
48
51
 
52
+
49
53
  def print_version():
50
- package_name = "batFramework"
54
+ # Dynamically construct the path to version.json
55
+ version_file = os.path.join(os.path.dirname(__file__), "version.json")
51
56
  try:
52
- version = importlib.metadata.version(package_name)
53
- print(f"{package_name} version: {version}")
54
- except importlib.metadata.PackageNotFoundError:
55
- print(f"{package_name} is not installed")
57
+ with open(version_file, "r") as f:
58
+ version_data = json.load(f)
59
+ version = version_data.get("version", "unknown")
60
+ print(f"BatFramework version: {version}")
61
+ except FileNotFoundError:
62
+ print(f"Version file not found: {version_file}")
63
+ except json.JSONDecodeError:
64
+ print(f"Error decoding version file: {version_file}")
56
65
 
57
66
  def init(
58
67
  resolution: tuple[int, int],
@@ -73,7 +82,7 @@ def init(
73
82
  resource_path if resource_path is not None else "."
74
83
  )
75
84
  if resource_path is not None:
76
- ResourceManager().load_dir(ResourceManager().RESOURCE_PATH)
85
+ ResourceManager().load_resources(ResourceManager().RESOURCE_PATH)
77
86
  if default_font_size is not None:
78
87
  FontManager().set_default_text_size(default_font_size)
79
88
  FontManager().init_font(default_font)
batFramework/action.py CHANGED
@@ -43,7 +43,7 @@ class Action:
43
43
  value (bool): True to activate the action, False to deactivate it.
44
44
  """
45
45
  self.active = value
46
- # self._holding = set()
46
+
47
47
 
48
48
  def add_event_control(self, *events) -> Self:
49
49
  self._event_control.update(events)
@@ -1,128 +1,59 @@
1
1
  import batFramework as bf
2
2
  import pygame
3
- from typing import List, Dict, Tuple, Union, Optional, Self
3
+ from typing import List, Dict, Tuple, Union, Optional, Self, Callable, Any
4
4
  from .animation import Animation
5
5
 
6
6
  class AnimatedSprite(bf.Drawable):
7
- def __init__(self, size: Optional[Tuple[int, int]] = None,*args,**kwargs) -> None:
8
- super().__init__(size, no_surface=True,*args,**kwargs)
9
- self.float_counter: float = 0
10
- self.animations: Dict[str, Animation] = {}
11
- self.current_state: Optional[Animation] = None
12
- self.flipX: bool = False
13
- self._locked: bool = False
14
- self._paused: bool = False
15
- self.animation_end_callback = None
16
- self.transition_end_animation = None
17
-
18
- def set_animation_end_callback(self,callback)->Self:
19
- self.animation_end_callback = callback
20
- return self
7
+ def __init__(self,*args,**kwargs) -> None:
8
+ super().__init__(None, no_surface=True,*args,**kwargs)
9
+ self.animations : dict[str,Animation] = {}
10
+ self.counter = 0 # int counter
11
+ self._fcounter = 0.0 # counter
12
+ self.current_animation : str = None
13
+ self.end_callback : Callable[[],Any] = None
14
+ self._flipX : bool = False
21
15
 
22
16
  @property
23
- def paused(self) -> bool:
24
- return self._paused
25
-
26
- @paused.setter
27
- def paused(self, value: bool) -> None:
28
- self._paused = value
29
-
30
- def toggle_pause(self) -> None:
31
- self.paused = not self.paused
32
-
33
- def set_counter(self, value: float) -> None:
34
- self.float_counter = value
35
-
36
- def set_frame(self, frame_index: int) -> None:
37
- if not self.current_state:
38
- return
39
- self.set_counter(sum(self.current_state.duration_list[:frame_index]))
40
-
41
- def lock(self) -> None:
42
- self._locked = True
43
-
44
- def unlock(self) -> None:
45
- self._locked = False
46
-
47
- def set_flipX(self, value: bool) -> None:
48
- self.flipX = value
49
-
50
- def remove_animation(self, name: str) -> bool:
51
- if name not in self.animations:
52
- return False
53
- self.animations.pop(name)
54
- if self.current_state and self.current_state.name == name:
55
- self.current_state = (
56
- list(self.animations.values())[0] if self.animations else None
57
- )
58
- return True
59
-
60
- def add_animation(
61
- self,
62
- animation:Animation
63
- ) -> bool:
64
- if animation.name in self.animations:
65
- return False
66
- self.animations[animation.name] = animation
67
- return True
68
-
69
- def set_animation(
70
- self, state: str, reset_counter: bool = True, lock: bool = False
71
- ) -> bool:
72
- if state not in self.animations or self._locked:
73
- return False
74
-
75
- animation = self.animations[state]
76
- self.current_state = animation
77
-
78
- if self.current_state.frames:
79
- self.rect = self.current_state.frames[0].get_frect(center=self.rect.center)
17
+ def flipX(self)->bool:
18
+ return self._flipX
19
+
20
+ @flipX.setter
21
+ def flipX(self,value:bool):
22
+ self._flipX = value
80
23
 
81
- if reset_counter or (self.float_counter > animation.duration_list_length):
82
- self.float_counter = 0
24
+ def set_end_callback(self,callback : Callable[[],Any]):
25
+ self.end_callback = callback
83
26
 
84
- if lock:
85
- self.lock()
86
-
87
- if self.transition_end_animation is not None:
88
- self.transition_end_animation = None
89
- return True
90
-
91
- def transition_to_animation(self,transition:str,animation:str)->Self:
92
- self.set_animation(transition)
93
- self.transition_end_animation = animation
27
+ def add_animation(self,name:str,animation:Animation)->Self:
28
+ self.animations[name] = animation
29
+ if self.rect.size == (0,0):
30
+ self.rect.size = animation.frames[0].get_size()
94
31
  return self
95
32
 
96
- def get_current_animation(self) -> Optional[Animation]:
97
- return self.current_state
98
-
99
- def update(self, dt: float) -> None:
100
- s = self.get_current_animation()
101
- if self.animations and s is not None:
102
- if not self.paused:
103
- self.float_counter += 60 * dt
104
- if self.float_counter > s.duration_list_length:
105
- if self.transition_end_animation is not None:
106
- # print(f"{self.transition_end_animation=}, {self.get_current_animation()=}")
107
- self.set_animation(self.transition_end_animation)
108
- if self.animation_end_callback is not None:
109
- self.animation_end_callback()
110
- self.float_counter = 0
111
- super().update(dt)
112
-
113
-
114
- def get_current_frame(self)->pygame.Surface:
115
- return self.current_state.get_frame(self.float_counter, self.flipX)
116
-
117
- def draw(self, camera: bf.Camera) -> None:
118
- if (
119
- not self.visible
120
- or not camera.rect.colliderect(self.rect)
121
- or not self.current_state
122
- ):
33
+ def set_animation(self,name:str,reset_counter:bool=True):
34
+ if name not in self.animations :
35
+ raise ValueError
36
+ self.current_animation = name
37
+ if reset_counter:
38
+ self._fcounter = 0
39
+
40
+ def get_current_frame(self)->int|None:
41
+ if not self.current_animation:
42
+ return None
43
+ return self.animations[self.current_animation].counter_to_frame(self._fcounter)
44
+
45
+ def update(self, dt):
46
+ super().update(dt)
47
+ if not self.current_animation:
123
48
  return
124
- camera.surface.blit(
125
- self.get_current_frame(),
126
- camera.world_to_screen(self.rect),
127
- )
128
- return
49
+ self._fcounter += dt
50
+ self.counter = int(self._fcounter)
51
+ if self.counter >= self.animations[self.current_animation].numFrames:
52
+ if self.end_callback:
53
+ self.end_callback()
54
+
55
+
56
+ def draw(self, camera):
57
+ self.surface.blit(self.animations[self.current_animation].get_frame(self.counter,self.flipX),(0,0))
58
+ super().draw(camera)
59
+
batFramework/animation.py CHANGED
@@ -17,15 +17,40 @@ class Animation:
17
17
  self,
18
18
  name: str
19
19
  ) -> None:
20
+ """
21
+ Class to hold 2D animation data.
22
+ All frames are expected to have the same size.
23
+ This class does not do anything on its own, but can be used to easily manage
24
+ multiple animations using a simple counter.
25
+ The duration list provides a entry point for tweaking the timings,
26
+ so image data can be saved (no need for contiguous duplicate frames)
27
+ """
20
28
  self.name = name
21
29
  self.frames: list[pygame.Surface] = []
22
30
  self.frames_flipX : list[pygame.Surface] = []
23
31
  self.duration_list = []
24
- self.duration_list_length = 1
32
+ self.duration_list_length = 0 # prevents calling len() each frame
33
+ self.numFrames : int = 0
25
34
 
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())
35
+ def from_surface(self,surface:pygame.Surface,frame_size : Tuple[int,int])->Self:
36
+ """
37
+ Loads frames from a spritesheet containing all animation frames aligned horizontally, left to right
38
+ Frames are cut and stored in 2 versions, original and flipped on the horizontal axis.
39
+ Flipping sprites being pretty common, this serves as a builtin cache.
40
+ """
41
+ self.frames : List[pygame.Surface] = list(
42
+ bf.utils.split_surface(surface, frame_size).values()
43
+ )
44
+ self.frames_flipX : List[pygame.Surface] = list(
45
+ bf.utils.split_surface(
46
+ surface, frame_size,
47
+ func=lambda s : pygame.transform.flip(s,True,False)
48
+ ).values()
49
+ )
50
+ self.duration_list_length = len(self.frames)
51
+ self.numFrames = self.duration_list_length
52
+ if not self.duration_list:
53
+ self.duration_list = [1]*self.duration_list_length
29
54
  return self
30
55
 
31
56
  def __repr__(self):
@@ -45,7 +70,7 @@ class Animation:
45
70
  def set_duration_list(self, duration_list: Union[List[int], int]) -> Self:
46
71
  if isinstance(duration_list, int):
47
72
  duration_list = [duration_list] * len(self.frames)
48
- if len(duration_list) != len(self.frames):
73
+ if len(duration_list) != self.numFrames:
49
74
  raise ValueError("duration_list should have values for all frames")
50
75
  self.duration_list = duration_list
51
76
  self.duration_list_length = sum(self.duration_list)
@@ -42,6 +42,9 @@ class AudioManager(metaclass=bf.Singleton):
42
42
  return name in self.sounds
43
43
 
44
44
  def load_sound(self, name, path, persistent=False) -> pygame.mixer.Sound:
45
+ """
46
+ if persistent==True the sound won't be unloaded when sounds are freed (unless force is used)
47
+ """
45
48
  if name in self.sounds:
46
49
  return self.sounds[name]["sound"]
47
50
  path = bf.ResourceManager().get_path(path)
@@ -52,8 +55,8 @@ class AudioManager(metaclass=bf.Singleton):
52
55
  }
53
56
  return self.sounds[name]["sound"]
54
57
 
55
- def load_sounds(self, sound_data_list: list[tuple[str, str, bool]]) -> None:
56
- for data in sound_data_list:
58
+ def load_sounds(self, sound_data: tuple[str, str, bool]) -> None:
59
+ for data in sound_data:
57
60
  self.load_sound(*data)
58
61
  return
59
62
 
@@ -83,8 +86,8 @@ class AudioManager(metaclass=bf.Singleton):
83
86
  self.musics[name] = bf.ResourceManager().get_path(path)
84
87
  return
85
88
 
86
- def load_musics(self, music_data_list: list[tuple[str, str]]):
87
- for data in music_data_list:
89
+ def load_musics(self, *music_data:tuple[str, str]):
90
+ for data in music_data:
88
91
  self.load_music(*data)
89
92
  return
90
93
 
@@ -101,8 +104,8 @@ class AudioManager(metaclass=bf.Singleton):
101
104
  self.current_music = name
102
105
  return True
103
106
  except KeyError:
107
+ print(f"Music '{name}' not loaded in AudioManager.")
104
108
  return False
105
- # print(f"Music '{name}' not loaded in AudioManager.")
106
109
 
107
110
  def stop_music(self):
108
111
  if not self.current_music:
@@ -0,0 +1,240 @@
1
+ from __future__ import annotations
2
+ from typing import TYPE_CHECKING, Any
3
+ if TYPE_CHECKING:
4
+ from .manager import Manager
5
+ from .sceneManager import SceneManager
6
+
7
+ import pygame
8
+ import itertools
9
+ import batFramework as bf
10
+ from .sceneLayer import SceneLayer
11
+
12
+ class BaseScene:
13
+ def __init__(self,name: str) -> None:
14
+ """
15
+ Base Scene object.
16
+ Empty scene with no layers or gui setup
17
+ Args:
18
+ name: Name of the scene.
19
+ """
20
+ bf.TimeManager().add_register(name,False)
21
+ self.scene_index = 0
22
+ self.name = name
23
+ self.manager: Manager | None = None
24
+ self.active = False
25
+ self.visible = False
26
+ self.clear_color = bf.color.BLACK
27
+ self.actions: bf.ActionContainer = bf.ActionContainer()
28
+ self.early_actions: bf.ActionContainer = bf.ActionContainer()
29
+ self.scene_layers : list[SceneLayer] = []
30
+
31
+ def set_clear_color(self,color):
32
+ """
33
+ Sets the clear color of the entire scene.
34
+ This color will fill the scene before all layers are drawn.
35
+ Results will not show if a layer has an opaque fill color on top.
36
+ Set to None to skip.
37
+ """
38
+ self.clear_color = color
39
+
40
+ def add_layer(self,layer:SceneLayer,index:int=0):
41
+ layer.set_scene(self)
42
+ self.scene_layers.insert(index,layer)
43
+
44
+ def remove_layer(self,index=0):
45
+ self.scene_layers.pop(index)
46
+
47
+ def set_layer(self,layername,layer):
48
+ for i,l in enumerate(self.scene_layers[::]):
49
+ if l.name == layername:
50
+ self.scene_layers[i] = layer
51
+ layer.set_scene(self)
52
+
53
+ def get_layer(self,name:str)->bf.SceneLayer:
54
+ for s in self.scene_layers:
55
+ if s.name == name:
56
+ return s
57
+ return None
58
+
59
+ def add(self,layer:str,*entities):
60
+ l = self.get_layer(layer)
61
+ if l is None : return
62
+ l.add(*entities)
63
+
64
+ def remove(self,layer:str,*entities):
65
+ l = self.get_layer(layer)
66
+ if l is None : return
67
+ l.remove(*entities)
68
+
69
+ def __str__(self)->str:
70
+ return f"Scene({self.name})"
71
+
72
+ def set_scene_index(self, index: int):
73
+ """Set the scene index."""
74
+ self.scene_index = index
75
+
76
+ def get_scene_index(self) -> int:
77
+ """Get the scene index."""
78
+ return self.scene_index
79
+
80
+ def when_added(self):
81
+ for s in self.scene_layers:
82
+ s.flush_entity_changes()
83
+ self.do_when_added()
84
+
85
+ def do_when_added(self):
86
+ pass
87
+
88
+ def set_manager(self, manager_link: Manager):
89
+ """Set the manager link for the scene."""
90
+ self.manager = manager_link
91
+ self.manager.update_scene_states()
92
+
93
+ def set_visible(self, value: bool):
94
+ """Set the visibility of the scene."""
95
+ self.visible = value
96
+ if self.manager:
97
+ self.manager.update_scene_states()
98
+
99
+ def set_active(self, value):
100
+ """Set the activity of the scene."""
101
+ self.active = value
102
+ if self.manager:
103
+ self.manager.update_scene_states()
104
+
105
+ def is_active(self) -> bool:
106
+ """Check if the scene is active."""
107
+ return self.active
108
+
109
+ def is_visible(self) -> bool:
110
+ """Check if the scene is visible."""
111
+ return self.visible
112
+
113
+ def get_name(self) -> str:
114
+ """Get the name of the scene."""
115
+ return self.name
116
+
117
+ def get_by_tags(self, *tags):
118
+ """Get entities by their tags."""
119
+ return itertools.chain.from_iterable(l.get_by_tags(*tags) for l in self.scene_layers)
120
+
121
+ def get_by_uid(self, uid) -> bf.Entity | None:
122
+ """Get an entity by its unique identifier."""
123
+ for l in self.scene_layers:
124
+ r = l.get_by_uid(uid)
125
+ if r is not None:
126
+ return r
127
+ return None
128
+
129
+ def add_actions(self, *action):
130
+ """Add actions to the scene."""
131
+ self.actions.add_actions(*action)
132
+
133
+ def add_early_actions(self, *action):
134
+ """Add actions to the scene."""
135
+ self.early_actions.add_actions(*action)
136
+
137
+ def process_event(self, event: pygame.Event):
138
+ """
139
+ Propagates event while it is not consumed.
140
+ In order : do_early_handle_event
141
+ -> scene early_actions
142
+ -> propagate to all layers
143
+ -> do_handle_event
144
+ -> scene actions.
145
+ at each step, if the event is consumed the propagation stops
146
+ """
147
+ self.do_early_handle_event(event)
148
+ if event.consumed: return
149
+ self.early_actions.process_event(event)
150
+ if event.consumed: return
151
+
152
+ if self.manager.current_transition and event.type in bf.enums.playerInput:
153
+ return
154
+
155
+ for l in self.scene_layers:
156
+ l.process_event(event)
157
+ if event.consumed : return
158
+
159
+ self.do_handle_event(event)
160
+
161
+ if event.consumed:return
162
+ self.actions.process_event(event)
163
+
164
+ # called before process event
165
+ def do_early_handle_event(self, event: pygame.Event):
166
+ """Called early in event propagation"""
167
+ pass
168
+
169
+ def do_handle_event(self, event: pygame.Event):
170
+ """called inside process_event but before resetting the scene's action container and propagating event to scene layers"""
171
+ pass
172
+
173
+ def update(self, dt):
174
+ """Update the scene. Do NOT override"""
175
+
176
+ #update all scene layers
177
+ for l in self.scene_layers:
178
+ l.update(dt)
179
+ self.do_update(dt)
180
+ self.actions.reset()
181
+ self.early_actions.reset()
182
+
183
+
184
+ def do_update(self, dt):
185
+ """Specific update within the scene."""
186
+ pass
187
+
188
+
189
+ def draw(self, surface: pygame.Surface):
190
+ if self.clear_color is not None:
191
+ surface.fill(self.clear_color)
192
+
193
+ self.do_early_draw(surface)
194
+
195
+ # Draw all layers back to front
196
+ for i,l in enumerate(reversed(self.scene_layers)):
197
+ #blit all layers onto surface
198
+ l.draw(surface)
199
+ if i < len(self.scene_layers)-1:
200
+ self.do_between_layer_draw(surface,l)
201
+ self.do_final_draw(surface)
202
+
203
+
204
+ def do_early_draw(self, surface: pygame.Surface):
205
+ """Called before any layer draw"""
206
+ pass
207
+
208
+ def do_between_layer_draw(self, surface: pygame.Surface,layer:SceneLayer):
209
+ """Called after drawing the argument layer (except the last layer)"""
210
+ pass
211
+
212
+ def do_final_draw(self, surface: pygame.Surface):
213
+ "Called after all layers"
214
+ pass
215
+
216
+ def on_enter(self):
217
+ self.set_active(True)
218
+ self.set_visible(True)
219
+ bf.TimeManager().activate_register(self.name)
220
+ self.do_on_enter()
221
+
222
+ def on_exit(self):
223
+ self.set_active(False)
224
+ self.set_visible(False)
225
+ self.actions.hard_reset()
226
+ self.early_actions.hard_reset()
227
+ bf.TimeManager().deactivate_register(self.name)
228
+ self.do_on_exit()
229
+
230
+ def do_on_enter(self) -> None:
231
+ pass
232
+
233
+ def do_on_exit(self) -> None:
234
+ pass
235
+
236
+ def do_on_enter_early(self) -> None:
237
+ pass
238
+
239
+ def do_on_exit_early(self) -> None:
240
+ pass
batFramework/camera.py CHANGED
@@ -41,6 +41,9 @@ class Camera:
41
41
  self.min_zoom = 0.1
42
42
  self.zoom(1)
43
43
 
44
+ def get_mouse_pos(self)->tuple[float,float]:
45
+ return self.screen_to_world(pygame.mouse.get_pos())
46
+
44
47
  def set_clear_color(self, color: pygame.Color | tuple | str) -> Self:
45
48
  """
46
49
  Set the clear color for the camera surface.
@@ -84,6 +87,7 @@ class Camera:
84
87
  """
85
88
  Clear the camera surface with the set clear color.
86
89
  """
90
+ if not self._clear_color: return
87
91
  self.surface.fill(self._clear_color)
88
92
 
89
93
  def get_center(self) -> tuple[float, float]:
batFramework/constants.py CHANGED
@@ -22,12 +22,17 @@ class Constants:
22
22
  def set_allow_debug(allow_debug:bool):
23
23
  Constants.ALLOW_DEBUG = allow_debug
24
24
 
25
-
26
25
  @staticmethod
27
26
  def set_resolution(resolution: tuple[int, int]):
28
27
  Constants.RESOLUTION = resolution
29
28
  Constants.WIDTH = resolution[0]
30
29
  Constants.HEIGHT = resolution[1]
30
+ Constants.update_screen()
31
+
32
+ @staticmethod
33
+ def update_screen():
34
+ if Constants.BF_INITIALIZED:
35
+ Constants.SCREEN = pygame.display.set_mode(Constants.RESOLUTION,Constants.FLAGS,vsync=Constants.VSYNC)
31
36
 
32
37
  @staticmethod
33
38
  def set_default_cursor(cursor: pygame.Cursor):
@@ -44,4 +49,3 @@ class Constants:
44
49
  @staticmethod
45
50
  def set_fps_limit(value: int):
46
51
  Constants.FPS = value
47
- print("FPS limit to : ", value)