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
@@ -1,138 +1,133 @@
1
1
  from __future__ import annotations
2
2
  from typing import TYPE_CHECKING
3
-
4
3
  if TYPE_CHECKING:
5
4
  from .constraints import Constraint
6
5
  from .root import Root
7
- from .interactiveWidget import InteractiveWidget
8
6
  from typing import Self
9
7
 
10
8
  import batFramework as bf
11
9
  import pygame
12
10
  from math import ceil
13
11
 
14
- MAX_CONSTRAINT_ITERATION = 10
12
+
15
13
 
16
14
  class Widget(bf.Entity):
17
- def __init__(self, convert_alpha=True) -> None:
15
+ def __init__(self,convert_alpha=True)->None:
18
16
  super().__init__(convert_alpha=convert_alpha)
19
17
  self.autoresize = False
20
- self.parent: None | Self = None
21
- self.is_root: bool = False
22
- self.children: list["Widget"] = []
23
- self.focusable: bool = False
24
- self.constraints: list[Constraint] = []
25
- self.gui_depth: int = 0
26
- if self.surface:
27
- self.surface.fill("white")
18
+ self.parent : None|Self = None
19
+ self.is_root :bool = False
20
+ self.children : list["Widget"] = []
21
+ self.focusable :bool= False
22
+ self.constraints : list[Constraint] = []
23
+ self.gui_depth : int = 0
24
+ if self.surface : self.surface.fill("white")
28
25
  self.set_debug_color("red")
29
- self.padding: tuple[float | int, ...] = (0, 0, 0, 0)
26
+ self.padding :tuple[float|int,...]= (0,0,0,0)
30
27
 
31
- def set_padding(self, value: float | int | tuple | list) -> Self:
28
+ def set_padding(self,value : float|int|tuple|list)->Self:
32
29
  old_raw_size = (
33
30
  self.rect.w - self.padding[0] - self.padding[2],
34
- self.rect.h - self.padding[1] - self.padding[3],
31
+ self.rect.h - self.padding[1] - self.padding[3]
35
32
  )
36
- if isinstance(value, list) or isinstance(value, tuple):
37
- if len(value) > 4:
38
- pass
39
- elif any(v < 0 for v in value):
40
- pass
41
- elif len(value) == 2:
42
- self.padding = (value[0], value[1], value[0], value[1])
33
+ if isinstance(value,list) or isinstance(value,tuple):
34
+ if len(value) > 4 : return self
35
+ if any(v<0 for v in value) : return self
36
+ if len(value) == 2:
37
+ self.padding = (value[0],value[1],value[0],value[1])
43
38
  else:
44
- self.padding = (*value, *self.padding[len(value) :])
39
+ self.padding = (*value, *self.padding[len(value):])
45
40
  else:
46
- self.padding = (value,) * 4
41
+ self.padding = (value,)*4
47
42
 
48
43
  self.set_size(
49
- old_raw_size[0] + self.padding[0] + self.padding[2],
50
- old_raw_size[1] + self.padding[1] + self.padding[3],
44
+ old_raw_size[0] + self.padding[0] + self.padding[2],
45
+ old_raw_size[1] + self.padding[1] + self.padding[3],
51
46
  )
52
47
  return self
53
-
54
-
55
- def inflate_rect_by_padding(self, rect: pygame.FRect) -> pygame.FRect:
48
+
49
+ def inflate_rect_by_padding(self,rect:pygame.FRect)->pygame.FRect:
56
50
  return pygame.FRect(
57
51
  rect[0] - self.padding[0],
58
- rect[1] - self.padding[1],
59
- rect[2] + self.padding[0] + self.padding[2],
60
- rect[3] + self.padding[1] + self.padding[3],
52
+ rect[1] - self.padding[1],
53
+ rect[2] + self.padding[0]+self.padding[2],
54
+ rect[3] + self.padding[1]+self.padding[3]
61
55
  )
62
- def get_min_required_size(self)->tuple[float,float]:
63
- return self.rect.size
64
-
65
- def get_content_left(self) -> float:
56
+ def get_content_left(self)->float:
66
57
  return self.rect.left + self.padding[0]
67
58
 
68
- def get_content_top(self) -> float:
59
+ def get_content_top(self)->float:
69
60
  return self.rect.top + self.padding[1]
70
61
 
71
- def get_content_right(self) -> float:
62
+ def get_content_right(self)->float:
72
63
  return self.rect.right - self.padding[2]
73
64
 
74
- def get_content_bottom(self) -> float:
65
+ def get_content_bottom(self)->float:
75
66
  return self.rect.bottom - self.padding[3]
76
67
 
77
- def get_content_width(self) -> float:
68
+ def get_content_width(self)->float:
78
69
  return self.rect.w - self.padding[0] - self.padding[2]
79
70
 
80
- def get_content_height(self) -> float:
71
+ def get_content_height(self)->float:
81
72
  return self.rect.h - self.padding[1] - self.padding[3]
82
73
 
83
- def get_content_rect(self) -> pygame.FRect:
74
+ def get_content_rect(self)->pygame.FRect:
84
75
  return pygame.FRect(
85
- self.rect.left + self.padding[0],
86
- self.rect.top + self.padding[1],
76
+ self.rect.left + self.padding[0],
77
+ self.rect.top + self.padding[1],
87
78
  self.get_content_width(),
88
- self.get_content_height(),
79
+ self.get_content_height()
89
80
  )
90
81
 
91
- def get_content_rect_rel(self) -> pygame.FRect:
92
- return self.get_content_rect().move(-self.rect.left, -self.rect.top)
82
+ def get_content_rect_rel(self)->pygame.FRect:
83
+ return self.get_content_rect().move(-self.rect.left,-self.rect.top)
93
84
 
94
- def get_content_center(self) -> tuple[float, float]:
85
+ def get_content_center(self)->tuple[float,float]:
95
86
  return self.get_content_rect().center
96
87
 
97
- def get_depth(self) -> int:
98
- if self.is_root or self.parent is None:
88
+ def get_depth(self)->int:
89
+ if self.is_root or self.parent is None :
99
90
  self.gui_depth = 0
100
91
  else:
101
- self.gui_depth = self.parent.get_depth() + 1
92
+ self.gui_depth = self.parent.get_depth() + 1
102
93
  return self.gui_depth
103
-
104
- def top_at(self, x: float|int, y: float|int) -> "None|Widget":
105
- if self.visible and self.rect.collidepoint(x, y):
106
- if self.children:
107
- for child in reversed(self.children):
108
- r = child.top_at(x, y)
109
- if r is not None:
110
- return r
111
- return self
112
94
 
95
+ def top_at(self, x: float, y: float) -> "None|Widget":
96
+ if self.children:
97
+ for child in reversed(self.children):
98
+ r = child.top_at(x,y)
99
+ if r is not None:
100
+ return r
101
+ if self.rect.collidepoint(x,y) and self.visible:
102
+ return self
113
103
  return None
114
-
115
- def get_constraint(self, name: str) -> Constraint | None:
104
+
105
+ def get_constraint(self,name:str)->Constraint|None:
116
106
  return next((c for c in self.constraints if c.name == name), None)
117
107
 
118
- def add_constraints(self, *constraints: Constraint) -> Self:
119
- for constraint in constraints:
120
- c = self.get_constraint(constraint.name)
121
- if c is not None:
122
- self.constraints.remove(c)
123
- self.constraints.append(constraint)
108
+ def add_constraints(self,*constraints:Constraint)->Self:
109
+ for c in constraints:
110
+ self.add_constraint(c,False)
111
+ self.apply_constraints()
112
+ return self
113
+
114
+ def add_constraint(self,constraint:Constraint,apply:bool=True)->Self:
115
+ c = self.get_constraint(constraint.name)
116
+ if c is not None:
117
+ self.constraints.remove(c)
118
+ self.constraints.append(constraint)
124
119
  self.apply_constraints()
125
120
  return self
126
121
 
127
- def has_constraint(self, name: str) -> bool:
122
+ def has_constraint(self,name:str)->bool:
128
123
  return any(c.name == name for c in self.constraints)
129
124
 
130
- def apply_all_constraints(self) -> None:
131
- for child in self.children:
132
- child.apply_all_constraints()
125
+ def apply_all_constraints(self)->None:
126
+ # print("APPLY ALL CONSTRAINTS IN ",self.to_string())
133
127
  self.apply_constraints()
134
-
135
- def apply_constraints(self) -> None:
128
+ for child in self.children : child.apply_all_constraints()
129
+
130
+ def apply_constraints(self, max_iterations: int = 10) -> None:
136
131
  if not self.parent:
137
132
  # print(f"Warning : can't apply constraints on {self.to_string()} without parent widget")
138
133
  return
@@ -141,7 +136,7 @@ class Widget(bf.Entity):
141
136
  # Sort constraints based on priority
142
137
  self.constraints.sort(key=lambda c: c.priority)
143
138
 
144
- for iteration in range(MAX_CONSTRAINT_ITERATION):
139
+ for iteration in range(max_iterations):
145
140
  unsatisfied = [] # Initialize a flag
146
141
 
147
142
  for constraint in self.constraints:
@@ -149,74 +144,55 @@ class Widget(bf.Entity):
149
144
  unsatisfied.append(constraint)
150
145
  constraint.apply(self.parent, self)
151
146
  if not unsatisfied:
152
- # data = ''.join(f"\n\t->{c.to_string()}" for c in self.constraints)
153
- # print(self.get_depth()*'\t'+f"Following constraints of {self.to_string()} were all satisfied :{data}")
147
+ # data = ''.join(f"\n\t->{c.to_string()}" for c in self.constraints)
148
+ # print(self.get_depth()*'\t'+f"Following constraints of {self.to_string()} were all satisfied :{data}")
154
149
  break
155
150
  # print(f"pass {iteration}/{max_iterations} : unsatisfied = {';'.join(c.to_string() for c in unsatisfied)}")
156
- if iteration == MAX_CONSTRAINT_ITERATION - 1:
157
- unsatisfied_constraints = '\n\t'.join([c.to_string() for c in unsatisfied])
158
- raise ValueError(
159
- f"[WARNING] Following constraints for {self.to_string()} were not satisfied : \n{unsatisfied_constraints}"
160
- )
151
+ if iteration == max_iterations - 1:
152
+ raise ValueError(f"[WARNING] Following constraints for {self.to_string()} were not satisfied : \n\t{';'.join([c.to_string() for c in unsatisfied])}")
161
153
 
162
154
  # GETTERS
163
- def get_by_tags(self, *tags :str):
164
- for c in self.children:
165
- yield from c.get_by_tags(*tags)
166
- if any(self.has_tags(t) for t in tags):
167
- yield self
168
-
169
- def count_children_recursive(self):
170
- return 1 + sum(child.count_children_recursive() for child in self.children)
171
-
172
-
173
- def propagate_function(self,function):
174
- function(self)
175
- for child in self.children:
176
- child.propagate_function(function)
177
-
178
- def get_root(self) -> Root | None:
179
- if self.parent_scene is not None:
180
- return self.parent_scene.root
155
+ def get_root(self)-> Self|Root|None:
156
+ if self.is_root: return self
157
+ if self.parent_scene is not None : return self.parent_scene.root
181
158
  return None if self.parent is None else self.parent.get_root()
182
159
 
183
- def get_size_int(self) -> tuple[int, int]:
184
- return (ceil(self.rect.width), ceil(self.rect.height))
160
+ def get_size_int(self)->tuple[int,int]:
161
+ return (ceil(self.rect.width),ceil(self.rect.height))
162
+
185
163
 
186
- def get_center(self) -> tuple[float, float]:
164
+ def get_center(self)->tuple[float,float]:
187
165
  return self.rect.center
188
166
 
167
+
189
168
  def get_bounding_box(self):
190
- yield (self.rect, self.debug_color)
191
- yield (self.get_content_rect(), "yellow")
169
+ yield (self.rect,self._debug_color)
170
+ yield (self.get_content_rect(),"yellow")
192
171
  for child in self.children:
193
172
  yield from child.get_bounding_box()
194
173
 
195
- def set_autoresize(self, value: bool) -> Self:
174
+ def set_autoresize(self,value:bool)-> Self:
196
175
  self.autoresize = value
197
176
  self.build()
198
177
  return self
199
178
 
200
- def set_parent(self, parent: Self | None) -> Self:
179
+ def set_parent(self,parent:Self|None)->None:
201
180
  if self.parent:
202
181
  self.parent.remove_child(self)
203
182
  self.parent = parent
204
183
  self.apply_all_constraints()
205
- return self
206
-
207
184
  # SETTERS
208
-
185
+
209
186
  def set_root(self) -> Self:
210
187
  self.is_root = True
211
188
  return self
212
189
 
213
- def set_parent_scene(self, scene) -> Self:
190
+ def set_parent_scene(self,scene)->None:
214
191
  super().set_parent_scene(scene)
215
- for child in self.children:
192
+ for child in self.children :
216
193
  child.set_parent_scene(scene)
217
- return self
218
- def set_x(self, x: float) -> Self:
219
- if x == self.rect.x : return self
194
+
195
+ def set_x(self,x:float)->Self:
220
196
  delta = x - self.rect.x
221
197
  self.rect.x = x
222
198
  for child in self.children:
@@ -224,127 +200,108 @@ class Widget(bf.Entity):
224
200
  self.apply_constraints()
225
201
  return self
226
202
 
227
- def set_y(self, y: float) -> Self:
228
- if y == self.rect.y : return self
203
+ def set_y(self,y:float)->Self:
229
204
  delta = y - self.rect.y
230
205
  self.rect.y = y
231
206
  for child in self.children:
232
207
  child.set_y(child.rect.y + delta)
233
208
  self.apply_constraints()
209
+
234
210
  return self
235
211
 
236
- def set_position(self, x: float, y: float) -> Self:
237
- if self.rect.topleft == (x,y) : return self
212
+ def set_position(self,x:float,y:float)->Self:
238
213
  delta_x = x - self.rect.x
239
214
  delta_y = y - self.rect.y
240
- self.rect.topleft = x, y
215
+ self.rect.topleft = x,y
241
216
  for child in self.children:
242
- child.set_position(child.rect.x + delta_x, child.rect.y + delta_y)
217
+ child.set_position(child.rect.x + delta_x,child.rect.y+delta_y)
243
218
  self.apply_constraints()
244
219
  return self
245
-
246
- def set_center(self, x: float, y: float) -> Self:
247
- if self.rect.center == (x,y) : return self
220
+
221
+ def set_center(self,x:float,y:float)->Self:
248
222
  delta_x = x - self.rect.centerx
249
223
  delta_y = y - self.rect.centery
250
- self.rect.center = x, y
224
+ self.rect.center = x,y
251
225
  for child in self.children:
252
- child.set_position(child.rect.x + delta_x, child.rect.y + delta_y)
226
+ child.set_position(child.rect.x + delta_x,child.rect.y+delta_y)
253
227
  self.apply_constraints()
254
228
  return self
255
229
 
256
- def set_size(self, width: float, height: float) -> Self:
257
- if width is None : width = self.rect.w
258
- if height is None : height = self.rect.h
259
- if self.rect.size == (width,height) : return self
260
- self.rect.size = (width, height)
230
+
231
+ def set_size(self, width : float, height: float) -> Self:
232
+ self.rect.size = (width,height)
261
233
  self.build()
262
- self.apply_constraints()
263
- self.children_modified()
264
234
  return self
235
+
265
236
 
266
237
  # Other Methods
267
238
 
268
- def print_tree(self, ident: int = 0) -> None:
269
- print("\t" * ident + self.to_string() + (":" if self.children else ""))
270
- for child in self.children:
271
- child.print_tree(ident + 1)
239
+ def print_tree(self,ident:int=0)->None:
240
+ print('\t'*ident+self.to_string()+(':' if self.children else ''))
241
+ for child in self.children :
242
+ child.print_tree(ident+1)
272
243
 
273
- def to_string(self) -> str:
244
+ def to_string(self)->str:
245
+
274
246
  return f"{self.to_string_id()}@{*self.rect.topleft,* self.rect.size}"
275
247
 
276
- def to_string_id(self) -> str:
248
+
249
+ def to_string_id(self)->str:
277
250
  return "Widget"
278
251
 
279
- def do_when_removed(self) -> None:
252
+
253
+ def do_when_removed(self)->None:
280
254
  if self.parent_scene and self.parent == self.parent_scene.root:
281
255
  self.set_parent(None)
282
256
 
283
257
  # Methods on children
284
258
 
285
- def add_child(self, *child: "Widget") -> None:
286
- for c in child:
259
+ def add_child(self,*child:"Widget")->None:
260
+ for c in child :
287
261
  self.children.append(c)
288
262
  c.set_parent(self)
289
263
  c.set_parent_scene(self.parent_scene)
290
- c.do_when_added()
291
- self._sort_children()
292
- self.apply_all_constraints()
264
+ c.apply_constraints()
293
265
  self.children_modified()
294
266
 
295
- def remove_child(self, child: "Widget") -> None:
296
- try :
297
- self.children.remove(child)
298
- except ValueError:
299
- return
267
+ def remove_child(self,child:Self)->None:
268
+ self.children.remove(child)
300
269
  child.set_parent(None)
301
- child.do_when_removed()
302
270
  child.set_parent_scene(None)
303
- self._sort_children()
304
- self.apply_all_constraints()
305
271
  self.children_modified()
306
272
 
307
- def _sort_children(self):
308
- self.children.sort(key=lambda child : child.render_order)
273
+
309
274
 
310
275
 
311
276
  # if return True -> don't propagate to siblings or parents
312
- def process_event(self, event: pygame.Event) -> bool:
277
+ def process_event(self, event: pygame.Event)->bool:
313
278
  # First propagate to children
314
279
  for child in self.children:
315
280
  if child.process_event(event):
316
281
  return True
317
- # return True if the method is blocking (no propagation to next children of the scene)
282
+ #return True if the method is blocking (no propagation to next children of the scene)
318
283
  return super().process_event(event)
319
284
 
320
- def update(self, dt: float):
285
+
286
+ def update(self,dt:float):
321
287
  for child in self.children:
322
288
  child.update(dt)
323
- self.do_update(dt)
324
289
 
325
290
  def draw(self, camera: bf.Camera) -> int:
326
- return super().draw(camera) + sum(
327
- [child.draw(camera) for child in self.children]
328
- )
291
+ self.children.sort(key=lambda e: (e.z_depth,e.render_order))
292
+ return super().draw(camera) + sum([child.draw(camera) for child in self.children])
329
293
 
330
- def build(self) -> None:
294
+ def build(self)->None:
331
295
  """
332
296
  This function is called each time the widget's surface has to be updated
333
297
  It usually has to be overriden if inherited to suit the needs of the new class
334
298
  """
335
- if not self.surface:
336
- return
299
+ if not self.surface: return
337
300
  if self.surface.get_size() != self.get_size_int():
338
301
  self.surface = pygame.Surface(self.get_size_int())
302
+ if self.parent : self.parent.children_modified()
339
303
 
340
-
341
- def build_all(self) -> None:
342
- self.build()
343
- for child in self.children:
344
- child.build_all()
345
-
346
- def children_modified(self) -> None:
304
+ def children_modified(self)->None:
305
+ self.apply_constraints()
347
306
  if self.parent and not self.is_root:
348
307
  self.parent.children_modified()
349
-
350
-
batFramework/manager.py CHANGED
@@ -2,37 +2,32 @@ import batFramework as bf
2
2
  import pygame
3
3
  import random
4
4
 
5
-
6
5
  class Manager(bf.SceneManager):
7
6
  def __init__(self, *initial_scene_list) -> None:
8
- # random.seed("random")
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)
7
+ random.seed("random")
8
+ self._screen: pygame.Surface = bf.const.SCREEN
9
+ self._timeManager = bf.Time()
10
+ self._cutsceneManager = bf.CutsceneManager(self)
13
11
  self._clock: pygame.Clock = pygame.Clock()
14
- self.do_pre_init()
15
12
  super().__init__(*initial_scene_list)
16
13
  self.set_sharedVar("clock", self._clock)
17
14
  self.do_init()
18
15
 
19
16
  @staticmethod
20
- def set_icon(path: str)->None:
21
- 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()
22
19
  pygame.display.set_icon(surf)
23
20
 
24
- def get_fps(self)->float:
21
+ def get_fps(self):
25
22
  return self._clock.get_fps()
26
23
 
27
- def do_init(self)->None:
24
+ def do_init(self):
28
25
  pass
29
26
 
30
- def do_pre_init(self)->None:
31
- pass
32
- def stop(self) -> None:
27
+ def stop(self)->None:
33
28
  self._running = False
34
29
 
35
- def run(self)->None:
30
+ def run(self):
36
31
  self._running = True
37
32
  dt: float = 0
38
33
  while self._running:
@@ -41,17 +36,15 @@ class Manager(bf.SceneManager):
41
36
  self._running = False
42
37
  break
43
38
  if event.type == pygame.VIDEORESIZE:
44
- bf.const.set_resolution((event.w, event.h))
39
+ bf.const.set_resolution((event.w,event.h))
45
40
  self.process_event(event)
46
41
  # update
47
- # dt = self._clock.tick(bf.const.FPS if not bf.const.VSYNC else 0) / 1000
48
- dt = self._clock.tick(0 if bf.const.VSYNC else bf.const.FPS) / 1000
49
- # dt = min(dt, 0.02) dirty fix for dt being too high when window not focused for a long time
42
+ dt = self._clock.tick(bf.const.FPS if not bf.const.VSYNC else 0) / 1000
43
+ dt = min(dt, 0.02)
50
44
  self._cutsceneManager.update(dt)
51
- self._timeManager.update(dt)
45
+ self._timeManager.update()
52
46
  self.update(dt)
53
47
  # render
54
- self._screen.fill((0,0,0))
55
48
  self.draw(self._screen)
56
49
  pygame.display.flip()
57
50
  pygame.quit()
batFramework/particles.py CHANGED
@@ -4,53 +4,37 @@ from pygame.math import Vector2
4
4
 
5
5
 
6
6
  class Particle:
7
- def __init__(self, *args, **kwargs):
8
- self.dead = False
9
- self.surface = None
10
-
11
- def kill(self):
12
- self.dead = True
13
-
14
- def update_surface(self):
15
- pass
16
-
17
-
18
- class TimedParticle(Particle):
19
- def __init__(self, duration):
20
- super().__init__()
21
- self.start_time = pygame.time.get_ticks()
22
- self.duration = duration
23
- self.progression = 0
24
-
25
- def update(self, dt):
26
- if self.dead:
27
- return
28
- elapsed_time = pygame.time.get_ticks() - self.start_time
29
- self.progression = elapsed_time / self.duration
30
- self.dead = elapsed_time >= self.duration
31
-
32
-
33
- class BasicParticle(TimedParticle):
34
7
  def __init__(
35
8
  self,
36
9
  start_pos: tuple[float, float],
37
10
  start_vel: tuple[float, float],
38
11
  duration=1000,
39
12
  color=None,
40
- size=(4, 4),
13
+ size = (4,4)
41
14
  ):
42
- super().__init__()
43
15
  self.rect = pygame.FRect(*start_pos, 0, 0)
44
16
  self.surface = pygame.Surface(size).convert()
45
17
  if color:
46
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
47
24
  self.z_depth = 1
48
25
 
49
26
  def update(self, dt):
50
- super().update(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
51
32
  self.rect.center += self.velocity * dt
52
33
  self.update_surface()
53
34
 
35
+ def kill(self):
36
+ self.dead = True
37
+
54
38
  def update_surface(self):
55
39
  self.surface.set_alpha(255 - int(self.progression * 255))
56
40
 
@@ -64,11 +48,13 @@ class ParticleManager(bf.Entity):
64
48
  for particle in self.particles:
65
49
  yield particle.rect
66
50
 
67
- def add_particle(self, particle=Particle):
68
- self.particles.append(particle)
51
+ def add_particle(self, particle_class=Particle, **kwargs):
52
+ self.particles.append(particle_class(**kwargs))
53
+
69
54
 
70
55
  def clear(self):
71
56
  self.particles = []
57
+
72
58
 
73
59
  def update(self, dt: float):
74
60
  particles_to_remove = []
@@ -80,19 +66,12 @@ class ParticleManager(bf.Entity):
80
66
  self.particles.remove(p)
81
67
 
82
68
  def draw(self, camera) -> bool:
83
- for p in self.particles:
84
- p.update_surface()
85
69
  camera.surface.fblits(
86
70
  [
87
71
  (
88
72
  p.surface,
89
- tuple(
90
- round(i * self.z_depth)
91
- for i in camera.transpose(self.rect).topleft
92
- ),
93
- )
94
- for p in self.particles
95
- if p.surface
73
+ tuple(round(i * self.z_depth) for i in camera.transpose(self.rect).topleft)
74
+ ) for p in self.particles
96
75
  ]
97
76
  )
98
77
  return len(self.particles)