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