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/cutscene.py CHANGED
@@ -1,253 +1,119 @@
1
1
  import batFramework as bf
2
- from .transition import Transition
3
- from typing import Callable,Any
2
+
3
+
4
+ class CutsceneBlock:
5
+ ...
6
+
4
7
 
5
8
  class Cutscene:
6
- def __init__(self):
7
- """
8
- Create a base Cutscene (ends immediately)
9
- """
10
-
11
- def start(self):
12
- """
13
- Called by the manager or the parent cutscene
14
- Has to return to blank init state
15
- """
16
- self.end()
17
-
18
- def process_event(self,event):
19
- pass
9
+ ...
10
+
11
+
12
+ class CutsceneManager(metaclass=bf.Singleton):
13
+ def __init__(self, manager) -> None:
14
+ self.current_cutscene: Cutscene = None
15
+ self.cutscenes : list[bf.Cutscene] = []
16
+ self.manager: bf.Manager = manager
17
+
18
+ def get_flag(self, flag):
19
+ return None
20
+
21
+ def process_event(self, event):
22
+ if self.current_cutscene:
23
+ self.current_cutscene.process_event(event)
24
+
25
+ def queue(self,*cutscenes):
26
+ self.cutscenes.extend(cutscenes)
27
+ if self.current_cutscene is None:
28
+ self.play(self.cutscenes.pop(0))
20
29
 
21
- def update(self,dt):
30
+ def play(self, cutscene: Cutscene):
31
+ if self.current_cutscene is None:
32
+ self.current_cutscene = cutscene
33
+ self.current_cutscene.on_enter()
34
+ self.current_cutscene.init_blocks()
35
+ self.current_cutscene.play()
36
+ self.manager.set_sharedVar("in_cutscene", True)
37
+
38
+ def update(self, dt):
39
+ if not self.current_cutscene is None:
40
+ self.current_cutscene.update(dt)
41
+ # print("cutscene manager update")
42
+ if self.current_cutscene.has_ended():
43
+ self.current_cutscene.on_exit()
44
+ self.current_cutscene =None
45
+ if self.cutscenes:
46
+ self.play(self.cutscenes.pop(0))
47
+ else:
48
+ self.current_cutscene = None
49
+ self.manager.set_sharedVar("in_cutscene", False)
50
+
51
+ class Cutscene:
52
+ def __init__(self,*blocks) -> None:
53
+ self.cutscene_blocks: list[CutsceneBlock] = list(blocks)
54
+ self.block_index = 0
55
+ self.end_blocks : list[CutsceneBlock] = []
56
+ self.ended = False
57
+ def on_enter(self):
58
+ pass
59
+
60
+ def on_exit(self):
22
61
  pass
23
62
 
63
+ def init_blocks(self):
64
+ pass
24
65
 
25
- def end(self):
26
- """
27
- Mark self as over
28
- """
29
- self.is_over = True
30
-
31
- class Sequence(Cutscene):
32
- def __init__(self,*cutscenes):
33
- self.sub_cutscenes :list[Cutscene] = list(cutscenes)
34
- self.index = 0
35
-
36
- def start(self):
37
- self.is_over = False
38
- self.index = 0
39
- if self.sub_cutscenes:
40
- self.sub_cutscenes[0].start()
41
-
42
- def process_event(self,event):
43
- """
44
- propagate process event for current sub cutscene
45
- """
46
- if self.index >0 and not self.is_over:
47
- self.sub_cutscenes[self.index].process_event(event)
48
-
49
-
50
-
51
- def update(self,dt):
52
- """
53
- Update current sub cutscene (if any)
54
- if current is over, start next one
55
- if current was last, then end self
56
- """
57
- if self.index < len(self.sub_cutscenes):
58
- self.sub_cutscenes[self.index].update(dt)
59
- if self.sub_cutscenes[self.index].is_over:
60
- self.index += 1
61
- if self.index == len(self.sub_cutscenes):
62
- self.end()
66
+ def add_end_block(self,block):
67
+ block.set_parent_cutscene(self)
68
+ self.end_blocks.append(block)
69
+
70
+ def get_scene_at(self,index):
71
+ return bf.CutsceneManager().manager._scenes[index]
72
+
73
+ def get_current_scene(self):
74
+ return bf.CutsceneManager().manager.get_current_scene()
75
+
76
+ def set_scene(self,name,index=0):
77
+ return bf.CutsceneManager().manager.set_scene(name,index)
78
+
79
+ def get_scene(self,name):
80
+ return bf.CutsceneManager().manager.get_scene(name)
81
+
82
+ def add_block(self, *blocks: list[CutsceneBlock]):
83
+ for block in blocks:
84
+ block.set_parent_cutscene(self)
85
+ self.cutscene_blocks.append(block)
86
+
87
+ def process_event(self, event):
88
+ if not self.ended and self.block_index < len(self.cutscene_blocks):
89
+ self.cutscene_blocks[self.block_index].process_event(event)
90
+
91
+ def play(self):
92
+ self.block_index = 0
93
+ if self.cutscene_blocks:
94
+ self.cutscene_blocks[self.block_index].start()
95
+ else:
96
+ self.ended
97
+
98
+ def update(self, dt):
99
+ if self.ended:
100
+ return
101
+ # print("cutscene update",self.cutscene_blocks[self.block_index])
102
+ self.cutscene_blocks[self.block_index].update(dt)
103
+ if self.cutscene_blocks[self.block_index].has_ended():
104
+ self.block_index += 1
105
+ if self.block_index == len(self.cutscene_blocks):
106
+ if not self.end_blocks:
107
+ self.ended = True
63
108
  return
64
- self.sub_cutscenes[self.index].start()
109
+ else:
110
+ self.cutscene_blocks.extend(self.end_blocks)
111
+ self.end_blocks = []
112
+ self.cutscene_blocks[self.block_index].start()
113
+
114
+ # print("NEXT BLOCK")
115
+
116
+ def has_ended(self):
117
+ return self.ended
65
118
 
66
119
 
67
- class Parallel(Cutscene):
68
- def __init__(self,*cutscenes:Cutscene):
69
- self.sub_cutscenes : list[Cutscene] = list(cutscenes)
70
-
71
- def start(self):
72
- self.is_over = False
73
- if not self.sub_cutscenes:
74
- self.end()
75
- for s in self.sub_cutscenes:
76
- s.start()
77
-
78
- def update(self,dt):
79
- for s in self.sub_cutscenes:
80
- s.update(dt)
81
- if all(s.is_over for s in self.sub_cutscenes):
82
- self.end()
83
-
84
- class Wait(Cutscene):
85
- def __init__(self,duration:float,scene_name:str="global"):
86
- self.duration = duration
87
- self.scene_name = scene_name
88
- def start(self):
89
- self.is_over = False
90
- self.timer = bf.SceneTimer(duration=self.duration,end_callback=self.end,scene_name=self.scene_name)
91
- self.timer.start()
92
-
93
-
94
-
95
- class TransitionToScene(Cutscene):
96
- def __init__(self,scene_name:str,transition:Transition):
97
- self.scene_name = scene_name
98
- self.transition: Transition = transition
99
-
100
- def start(self):
101
- self.is_over = False
102
- bf.CutsceneManager().manager.transition_to_scene(self.scene_name,self.transition)
103
- bf.Timer(self.transition.duration,end_callback=self.end).start()
104
-
105
-
106
-
107
-
108
-
109
-
110
- class GlideWorldCameraFromTo(Cutscene):
111
- def __init__(self,start:tuple[float,float], stop:tuple[float,float],duration:float=1,easing:bf.easing=bf.easing.EASE_IN_OUT,scene_name:str=None):
112
- super().__init__()
113
- self.scene = None
114
- self.scene_name = scene_name
115
- self.start_pos = start
116
- self.stop_pos = stop
117
- self.controller = bf.EasingController(duration,easing,update_callback=self.internal,end_callback=self.end)
118
-
119
-
120
- def start(self):
121
- self.is_over = False
122
- if self.scene_name is None:
123
- self.scene_name = bf.CutsceneManager().manager.get_scene_at(0).name
124
-
125
- self.scene = bf.CutsceneManager().manager.get_scene(self.scene_name)
126
- self.controller.start()
127
-
128
-
129
- def internal(self,progression:float):
130
- self.scene.camera.set_center(
131
- self.start_pos[0]+progression*(self.stop_pos[0]-self.start_pos[0]),
132
- self.start_pos[1]+progression*(self.stop_pos[1]-self.start_pos[1])
133
- )
134
-
135
- def end(self):
136
- if self.scene:
137
- self.scene.camera.set_center(self.stop_pos[0],self.stop_pos[1])
138
-
139
- super().end()
140
-
141
-
142
-
143
- class Function(Cutscene):
144
- def __init__(self, function:Callable[[],Any],*args,**kwargs):
145
- super().__init__()
146
- self.function:Callable[[],Any] = function
147
- self.args = args
148
- self.kwargs = kwargs
149
-
150
- def start(self):
151
- self.is_over = False
152
- self.function(*self.args,**self.kwargs)
153
- self.end()
154
-
155
- class GlideCamera(Cutscene):
156
- def __init__(
157
- self,
158
- start: tuple[float, float] | None = None,
159
- stop: tuple[float, float] | None = None,
160
- delta: tuple[float, float] | None = None,
161
- duration: float = 1,
162
- easing: bf.easing = bf.easing.EASE_IN_OUT,
163
- scene_name: str | None = None,
164
- layer_name: str = "world",
165
- ):
166
- super().__init__()
167
- self.scene = None
168
- self.layer = None
169
- self.scene_name = scene_name
170
- self.layer_name = layer_name
171
- self.start_pos = start
172
- self.stop_pos = stop
173
- self.delta = delta
174
- self.controller = bf.EasingController(
175
- duration, easing, update_callback=self.internal, end_callback=self.end
176
- )
177
-
178
- def start(self):
179
- self.is_over = False
180
-
181
- if self.scene_name is None:
182
- self.scene_name = bf.CutsceneManager().manager.get_scene_at(0).name
183
-
184
- self.scene = bf.CutsceneManager().manager.get_scene(self.scene_name)
185
- self.layer = self.scene.get_layer(self.layer_name)
186
-
187
- if not self.layer:
188
- raise ValueError(f"Layer '{self.layer_name}' not found in scene '{self.scene_name}'.")
189
-
190
- # Fallback to current camera position
191
- if self.start_pos is None:
192
- self.start_pos = self.layer.camera.get_center()
193
-
194
- # Compute stop_pos if not set
195
- if self.stop_pos is None:
196
- if self.delta is not None:
197
- self.stop_pos = (
198
- self.start_pos[0] + self.delta[0],
199
- self.start_pos[1] + self.delta[1],
200
- )
201
- else:
202
- raise ValueError("Must specify either stop or delta position")
203
-
204
- self.controller.start()
205
-
206
- def internal(self, progression: float):
207
- self.layer.camera.set_center(
208
- self.start_pos[0] + progression * (self.stop_pos[0] - self.start_pos[0]),
209
- self.start_pos[1] + progression * (self.stop_pos[1] - self.start_pos[1]),
210
- )
211
-
212
- def end(self):
213
- if self.layer:
214
- self.layer.camera.set_center(*self.stop_pos)
215
- super().end()
216
-
217
- class GlideCameraTo(GlideCamera):
218
- def __init__(
219
- self,
220
- stop: tuple[float, float],
221
- duration: float = 1,
222
- easing: bf.easing = bf.easing.EASE_IN_OUT,
223
- scene_name: str | None = None,
224
- layer_name: str = "world",
225
- ):
226
- super().__init__(
227
- start=None,
228
- stop=stop,
229
- delta=None,
230
- duration=duration,
231
- easing=easing,
232
- scene_name=scene_name,
233
- layer_name=layer_name,
234
- )
235
-
236
- class GlideCameraBy(GlideCamera):
237
- def __init__(
238
- self,
239
- delta: tuple[float, float],
240
- duration: float = 1,
241
- easing: bf.easing = bf.easing.EASE_IN_OUT,
242
- scene_name: str | None = None,
243
- layer_name: str = "world",
244
- ):
245
- super().__init__(
246
- start=None,
247
- stop=None,
248
- delta=delta,
249
- duration=duration,
250
- easing=easing,
251
- scene_name=scene_name,
252
- layer_name=layer_name,
253
- )
@@ -0,0 +1,176 @@
1
+ import batFramework as bf
2
+ from .cutscene import Cutscene,CutsceneManager
3
+
4
+
5
+ # Define the base CutsceneBlock class
6
+ class CutsceneBlock:
7
+ """
8
+ Base class for cutscene blocks. Represents a unit of action in a cutscene.
9
+ """
10
+
11
+ # Constructor for the CutsceneBlock
12
+ def __init__(self) -> None:
13
+ # Callback function, parent cutscene, and state variables
14
+ self.callback = None
15
+ self.parent_cutscene: Cutscene = None
16
+ self.get_flag = CutsceneManager().get_flag
17
+ self.ended = False
18
+ self.started = False
19
+
20
+ def get_scene_at(self,index):
21
+ return bf.CutsceneManager().manager._scenes[index]
22
+
23
+ def set_scene(self,name,index=0):
24
+ return CutsceneManager().manager.set_scene(name,index)
25
+
26
+ def get_current_scene(self):
27
+ return CutsceneManager().manager.get_current_scene()
28
+
29
+ def get_scene(self,name):
30
+ return CutsceneManager().manager.get_scene(name)
31
+
32
+ # Set the parent cutscene for this block
33
+ def set_parent_cutscene(self, parent):
34
+ """
35
+ Set the parent cutscene for this block.
36
+
37
+ Args:
38
+ parent: The parent cutscene object.
39
+ """
40
+ self.parent_cutscene = parent
41
+
42
+ # Process an event (placeholder implementation, to be overridden in subclasses)
43
+ def process_event(self, event):
44
+ """
45
+ Process an event for this cutscene block.
46
+
47
+ Args:
48
+ event: The event to be processed.
49
+ """
50
+ pass
51
+
52
+ # Update the block (placeholder implementation, to be overridden in subclasses)
53
+ def update(self, dt):
54
+ """
55
+ Update the cutscene block.
56
+
57
+ Args:
58
+ dt: Time elapsed since the last update.
59
+ """
60
+ pass
61
+
62
+ # Start the block
63
+ def start(self):
64
+ """
65
+ Start the cutscene block.
66
+ """
67
+ self.started = True
68
+
69
+ # Mark the block as ended
70
+ def end(self):
71
+ """
72
+ Mark the cutscene block as ended.
73
+ """
74
+ self.ended = True
75
+
76
+ # Check if the block has ended
77
+ def has_ended(self):
78
+ """
79
+ Check if the cutscene block has ended.
80
+
81
+ Returns:
82
+ bool: True if the block has ended, False otherwise.
83
+ """
84
+ return self.ended
85
+
86
+
87
+ # Define the ParallelBlock class, a type of CutsceneBlock
88
+ class ParallelBlock(CutsceneBlock):
89
+ """
90
+ Represents a parallel execution block for multiple Cutscene blocks.
91
+ """
92
+
93
+ # Constructor for ParallelBlock, taking a variable number of blocks as arguments
94
+ def __init__(self, *blocks) -> None:
95
+ super().__init__()
96
+ # List of blocks to run in parallel
97
+ self.blocks: list[CutsceneBlock] = blocks
98
+
99
+ # Start the parallel block (override the base class method)
100
+ def start(self):
101
+ """
102
+ Start the parallel execution block.
103
+ """
104
+ super().start()
105
+ # Start each block in parallel
106
+ for block in self.blocks:
107
+ block.start()
108
+
109
+ # Process an event for each block in parallel
110
+ def process_event(self, event):
111
+ """
112
+ Process an event for each block in the parallel execution block.
113
+
114
+ Args:
115
+ event: The event to be processed.
116
+ """
117
+ _ = [b.process_event(event) for b in self.blocks]
118
+
119
+ # Update each block in parallel
120
+ def update(self, dt):
121
+ """
122
+ Update each block in the parallel execution block.
123
+
124
+ Args:
125
+ dt: Time elapsed since the last update.
126
+ """
127
+ _ = [b.update(dt) for b in self.blocks]
128
+
129
+ # Check if all blocks have ended
130
+ def has_ended(self):
131
+ """
132
+ Check if all blocks in the parallel execution block have ended.
133
+
134
+ Returns:
135
+ bool: True if all blocks have ended, False otherwise.
136
+ """
137
+ return all(b.has_ended() for b in self.blocks)
138
+
139
+
140
+ # Define the SceneTransitionBlock class, a type of CutsceneBlock
141
+ class SceneTransitionBlock(CutsceneBlock):
142
+ """
143
+ Represents a scene transition Cutscene block.
144
+ """
145
+
146
+ # Constructor for SceneTransitionBlock
147
+ def __init__(self, scene, transition, duration, **kwargs) -> None:
148
+ super().__init__()
149
+ # Target scene, transition type, duration, and additional keyword arguments
150
+ self.target_scene = scene
151
+ self.transition = transition
152
+ self.duration = duration
153
+ self.kwargs = kwargs
154
+ # Timer to handle the end of the transition
155
+ self.timer = bf.Timer(name = "scene_transition_block",duration=duration, end_callback=self.end)
156
+
157
+ # Start the scene transition block
158
+ def start(self):
159
+ """
160
+ Start the scene transition block.
161
+ """
162
+ super().start()
163
+ print(f"transition to {scene}")
164
+
165
+ # Initiate the scene transition
166
+ if self.get_current_scene()._name == self.target_scene:
167
+ self.end()
168
+ return
169
+ CutsceneManager().manager.transition_to_scene(
170
+ self.target_scene, self.transition, duration=self.duration, **self.kwargs
171
+ )
172
+ # Start the timer to handle the end of the transition
173
+ self.timer.start()
174
+
175
+ def end(self):
176
+ return super().end()
@@ -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,29 +2,22 @@ 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
- *args,**kwargs
8
+ size : None|tuple[int,int]=None,
9
+ no_surface : bool =False,
10
+ surface_flags : int =0,
11
+ convert_alpha : bool=False
10
12
  ) -> None:
11
- super().__init__(*args,**kwargs)
13
+ super().__init__(size,no_surface,surface_flags,convert_alpha)
12
14
  self.velocity = pygame.math.Vector2(0, 0)
13
- self.ignore_collisions : bool = False
14
15
 
15
- def on_collideX(self, collider: "DynamicEntity"):
16
- """
17
- Return true if collision
18
- """
16
+ def on_collideX(self, collider: Self):
19
17
  return False
20
18
 
21
- def on_collideY(self, collider: "DynamicEntity"):
22
- """
23
- Return true if collision
24
- """
19
+ def on_collideY(self, collider: Self):
25
20
  return False
26
21
 
27
- def move_by_velocity(self, dt) -> None:
28
- self.set_position(
29
- self.rect.x + self.velocity.x * dt, self.rect.y + self.velocity.y * dt
30
- )
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 ADDED
@@ -0,0 +1,71 @@
1
+ from enum import Enum
2
+ import pygame
3
+ import batFramework as bf
4
+
5
+ class Easing(Enum):
6
+ EASE_IN = (0.12, 0, 0.39, 0)
7
+ EASE_OUT = (0.61, 1, 0.88, 1)
8
+ EASE_IN_OUT = (0.37, 0, 0.63, 1)
9
+ EASE_IN_OUT_ELASTIC = (.7,-0.5,.3,1.5)
10
+ LINEAR = (1, 1, 0, 0)
11
+ # Add more easing functions as needed
12
+
13
+ def __init__(self, *control_points):
14
+ self.control_points = control_points
15
+
16
+ class EasingAnimation(bf.Timer):
17
+ _cache = {}
18
+ def __init__(
19
+ self,
20
+ name:str=None,
21
+ easing_function:Easing=Easing.LINEAR,
22
+ duration:int=100,
23
+ update_callback=None,
24
+ end_callback=None,
25
+ loop:bool=False,
26
+ reusable:bool=False
27
+ ):
28
+ self.easing_function = easing_function
29
+ self.update_callback = update_callback
30
+ self.value = 0.0
31
+ super().__init__(name,duration,loop,end_callback,reusable)
32
+
33
+ def get_value(self):
34
+ return self.value
35
+
36
+ def start(self):
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.
43
+ self._process_value()
44
+ # if self.name == 0: print("UPDATING (callback) in easing")
45
+ if self.update_callback: self.update_callback(self.value)
46
+ return False
47
+
48
+ def end(self):
49
+ # Call update 1 last time with the last value
50
+
51
+ self.elapsed_progress = 1
52
+ self._process_value()
53
+ if self.update_callback: self.update_callback(self.value)
54
+ self.value = 0
55
+ super().end() # sets elapsed_progress to 0
56
+
57
+ def _process_value(self):
58
+ p0, p1, p2, p3 = self.easing_function.control_points
59
+ cache_key = (self.elapsed_progress, p0, p1, p2, p3)
60
+ if cache_key in EasingAnimation._cache:
61
+ y = EasingAnimation._cache[cache_key]
62
+ else:
63
+ t = self.elapsed_progress
64
+ t_inv = 1.0 - t
65
+ t2 = t * t
66
+ t3 = t * t2
67
+ t_inv2 = t_inv * t_inv
68
+
69
+ y = 3 * t_inv2 * t * p1 + 3 * t_inv * t2 * p3 + t3
70
+ EasingAnimation._cache[cache_key] = y
71
+ self.value = y