batframework 1.0.10__py3-none-any.whl → 2.0.0a1__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 +83 -52
- batFramework/action.py +280 -252
- batFramework/actionContainer.py +105 -38
- batFramework/animatedSprite.py +81 -117
- batFramework/animation.py +91 -0
- batFramework/audioManager.py +156 -85
- batFramework/baseScene.py +249 -0
- batFramework/camera.py +245 -123
- batFramework/constants.py +57 -75
- batFramework/cutscene.py +239 -119
- batFramework/cutsceneManager.py +34 -0
- batFramework/drawable.py +107 -0
- batFramework/dynamicEntity.py +30 -23
- batFramework/easingController.py +58 -0
- batFramework/entity.py +130 -123
- batFramework/enums.py +171 -0
- batFramework/fontManager.py +65 -0
- batFramework/gui/__init__.py +28 -14
- batFramework/gui/animatedLabel.py +90 -0
- batFramework/gui/button.py +18 -84
- batFramework/gui/clickableWidget.py +244 -0
- batFramework/gui/collapseContainer.py +98 -0
- batFramework/gui/constraints/__init__.py +1 -0
- batFramework/gui/constraints/constraints.py +1066 -0
- batFramework/gui/container.py +220 -49
- batFramework/gui/debugger.py +140 -47
- batFramework/gui/draggableWidget.py +63 -0
- batFramework/gui/image.py +61 -23
- batFramework/gui/indicator.py +116 -40
- batFramework/gui/interactiveWidget.py +243 -22
- batFramework/gui/label.py +147 -110
- batFramework/gui/layout.py +442 -81
- batFramework/gui/meter.py +155 -0
- batFramework/gui/radioButton.py +43 -0
- batFramework/gui/root.py +228 -60
- batFramework/gui/scrollingContainer.py +282 -0
- batFramework/gui/selector.py +232 -0
- batFramework/gui/shape.py +286 -86
- batFramework/gui/slider.py +353 -0
- batFramework/gui/style.py +10 -0
- batFramework/gui/styleManager.py +49 -0
- batFramework/gui/syncedVar.py +43 -0
- batFramework/gui/textInput.py +331 -0
- batFramework/gui/textWidget.py +308 -0
- batFramework/gui/toggle.py +140 -62
- batFramework/gui/tooltip.py +35 -0
- batFramework/gui/widget.py +546 -307
- batFramework/manager.py +131 -50
- batFramework/particle.py +118 -0
- batFramework/propertyEaser.py +79 -0
- batFramework/renderGroup.py +34 -0
- batFramework/resourceManager.py +130 -0
- batFramework/scene.py +31 -226
- batFramework/sceneLayer.py +134 -0
- batFramework/sceneManager.py +200 -165
- batFramework/scrollingSprite.py +115 -0
- batFramework/sprite.py +46 -0
- batFramework/stateMachine.py +49 -51
- batFramework/templates/__init__.py +2 -0
- batFramework/templates/character.py +15 -0
- batFramework/templates/controller.py +158 -0
- batFramework/templates/stateMachine.py +39 -0
- batFramework/tileset.py +46 -0
- batFramework/timeManager.py +213 -0
- batFramework/transition.py +162 -157
- batFramework/triggerZone.py +22 -22
- batFramework/utils.py +306 -184
- {batframework-1.0.10.dist-info → batframework-2.0.0a1.dist-info}/LICENSE +20 -20
- {batframework-1.0.10.dist-info → batframework-2.0.0a1.dist-info}/METADATA +2 -2
- batframework-2.0.0a1.dist-info/RECORD +72 -0
- batFramework/cutsceneBlocks.py +0 -176
- batFramework/debugger.py +0 -48
- batFramework/easing.py +0 -71
- batFramework/gui/constraints.py +0 -204
- batFramework/gui/frame.py +0 -19
- batFramework/particles.py +0 -77
- batFramework/time.py +0 -75
- batFramework/transitionManager.py +0 -0
- batframework-1.0.10.dist-info/RECORD +0 -43
- {batframework-1.0.10.dist-info → batframework-2.0.0a1.dist-info}/WHEEL +0 -0
- {batframework-1.0.10.dist-info → batframework-2.0.0a1.dist-info}/top_level.txt +0 -0
batFramework/camera.py
CHANGED
@@ -1,123 +1,245 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
self.
|
13
|
-
self.
|
14
|
-
self.
|
15
|
-
self.
|
16
|
-
|
17
|
-
|
18
|
-
self.
|
19
|
-
self.
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
self.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
self.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
self.
|
38
|
-
|
39
|
-
def
|
40
|
-
return self.
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
self
|
49
|
-
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
"""
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
self
|
68
|
-
|
69
|
-
def
|
70
|
-
self.
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
self.
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
def
|
114
|
-
|
115
|
-
if self.zoom_factor
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
1
|
+
import pygame
|
2
|
+
from pygame.math import Vector2
|
3
|
+
import batFramework as bf
|
4
|
+
from typing import Self
|
5
|
+
import math
|
6
|
+
|
7
|
+
|
8
|
+
class Camera:
|
9
|
+
def __init__(
|
10
|
+
self, flags=0, size: tuple[int, int] | None = None, convert_alpha: bool = False,fullscreen:bool=True
|
11
|
+
) -> None:
|
12
|
+
self.cached_surfaces: dict[tuple[int, int], pygame.Surface] = {}
|
13
|
+
self.fullscreen : bool = fullscreen # auto fill the screen (i.e react to VIDEORESIZE event)
|
14
|
+
self.flags: int = flags | (pygame.SRCALPHA if convert_alpha else 0)
|
15
|
+
self.blit_special_flags: int = pygame.BLEND_ALPHA_SDL2
|
16
|
+
|
17
|
+
size = size if size else bf.const.RESOLUTION
|
18
|
+
self.rect = pygame.FRect(0, 0, *size)
|
19
|
+
self.transform_target_surface : pygame.Surface = pygame.Surface(self.rect.size,self.flags)
|
20
|
+
self.should_convert_alpha: bool = convert_alpha
|
21
|
+
self.world_rect = pygame.FRect(0, 0, *self.rect.size)
|
22
|
+
|
23
|
+
self.vector_center = Vector2(0, 0)
|
24
|
+
self.rotation = 0.0 # Rotation in degrees
|
25
|
+
|
26
|
+
self.surface: pygame.Surface = pygame.Surface((0, 0)) # dynamic : create new at each new zoom value
|
27
|
+
|
28
|
+
self._clear_color: pygame.typing.ColorLike = pygame.Color(0, 0, 0, 0) if convert_alpha else pygame.Color(0, 0, 0)
|
29
|
+
|
30
|
+
self.follow_point_func = None
|
31
|
+
self.damping = float("inf")
|
32
|
+
self.dead_zone_radius = 10
|
33
|
+
|
34
|
+
self.zoom_factor = 1
|
35
|
+
self.max_zoom = 2
|
36
|
+
self.min_zoom = 0.1
|
37
|
+
self.zoom(1,force=True)
|
38
|
+
|
39
|
+
def get_mouse_pos(self) -> tuple[float, float]:
|
40
|
+
return self.screen_to_world(pygame.mouse.get_pos())
|
41
|
+
|
42
|
+
def set_clear_color(self, color: pygame.Color | tuple | str) -> Self:
|
43
|
+
self._clear_color = color
|
44
|
+
return self
|
45
|
+
|
46
|
+
def set_max_zoom(self, value: float) -> Self:
|
47
|
+
self.max_zoom = value
|
48
|
+
return self
|
49
|
+
|
50
|
+
def set_min_zoom(self, value: float) -> Self:
|
51
|
+
self.min_zoom = value
|
52
|
+
return self
|
53
|
+
|
54
|
+
def set_rotation(self, angle: float) -> Self:
|
55
|
+
"""
|
56
|
+
Set the camera rotation in degrees.
|
57
|
+
"""
|
58
|
+
self.rotation = angle % 360
|
59
|
+
return self
|
60
|
+
|
61
|
+
def rotate_by(self,angle:float)->Self:
|
62
|
+
"""
|
63
|
+
Increment rotation by given angle in degrees.
|
64
|
+
"""
|
65
|
+
self.rotation+=angle
|
66
|
+
self.rotation%=360
|
67
|
+
return self
|
68
|
+
|
69
|
+
def clear(self) -> None:
|
70
|
+
if self._clear_color is None:
|
71
|
+
return
|
72
|
+
self.surface.fill(self._clear_color)
|
73
|
+
|
74
|
+
def get_center(self) -> tuple[float, float]:
|
75
|
+
return self.world_rect.center
|
76
|
+
|
77
|
+
def get_position(self) -> tuple[float, float]:
|
78
|
+
return self.world_rect.topleft
|
79
|
+
|
80
|
+
def move_by(self, x: float | int, y: float | int) -> Self:
|
81
|
+
# self.world_rect.move_ip(x, y)
|
82
|
+
self.world_rect.x += x
|
83
|
+
self.world_rect.y += y
|
84
|
+
return self
|
85
|
+
|
86
|
+
def set_position(self, x, y) -> Self:
|
87
|
+
self.world_rect.topleft = (x, y)
|
88
|
+
return self
|
89
|
+
|
90
|
+
def set_center(self, x, y) -> Self:
|
91
|
+
self.world_rect.center = (x, y)
|
92
|
+
return self
|
93
|
+
|
94
|
+
def set_follow_point_func(self, func) -> Self:
|
95
|
+
self.follow_point_func = func
|
96
|
+
return self
|
97
|
+
|
98
|
+
def set_follow_speed(self, speed: float) -> Self:
|
99
|
+
self.follow_speed = speed
|
100
|
+
return self
|
101
|
+
|
102
|
+
def set_follow_damping(self, damping: float) -> Self:
|
103
|
+
self.damping = damping
|
104
|
+
return self
|
105
|
+
|
106
|
+
def set_dead_zone_radius(self, radius: float) -> Self:
|
107
|
+
self.dead_zone_radius = radius
|
108
|
+
return self
|
109
|
+
|
110
|
+
def zoom_by(self, amount: float) -> Self:
|
111
|
+
return self.zoom(self.zoom_factor + amount)
|
112
|
+
|
113
|
+
def zoom(self, factor: float,force:bool=False) -> Self:
|
114
|
+
clamped = max(self.min_zoom, min(self.max_zoom, round(factor, 2)))
|
115
|
+
if clamped == self.zoom_factor and not force:
|
116
|
+
return self
|
117
|
+
|
118
|
+
self.zoom_factor = clamped
|
119
|
+
new_res = tuple([round((i / clamped) / 2) * 2 for i in self.rect.size])
|
120
|
+
|
121
|
+
if self.surface.get_size() != new_res:
|
122
|
+
self.surface = self._get_cached_surface((new_res[0],new_res[1]))
|
123
|
+
|
124
|
+
self.world_rect = self.surface.get_frect(center=self.world_rect.center)
|
125
|
+
self.clear()
|
126
|
+
return self
|
127
|
+
|
128
|
+
def _free_cache(self):
|
129
|
+
self.cached_surfaces.clear()
|
130
|
+
|
131
|
+
def _get_cached_surface(self, new_size: tuple[int, int]):
|
132
|
+
surface = self.cached_surfaces.get(new_size)
|
133
|
+
if surface is None:
|
134
|
+
surface = pygame.Surface(new_size, flags=self.flags)
|
135
|
+
# if self.flags & pygame.SRCALPHA:
|
136
|
+
# surface = surface.convert_alpha()
|
137
|
+
self.cached_surfaces[new_size] = surface
|
138
|
+
return surface
|
139
|
+
|
140
|
+
def set_size(self, size: tuple[int, int] | None = None) -> Self:
|
141
|
+
if size is None:
|
142
|
+
size = bf.const.RESOLUTION
|
143
|
+
center = self.rect.center
|
144
|
+
self.rect.size = size
|
145
|
+
self.rect.center = center
|
146
|
+
self.transform_target_surface = pygame.Surface(self.rect.size,self.flags)
|
147
|
+
self.world_rect.center = (size[0] / 2, size[1] / 2)
|
148
|
+
self.zoom(self.zoom_factor)
|
149
|
+
return self
|
150
|
+
|
151
|
+
def intersects(self, rect: pygame.Rect | pygame.FRect) -> bool:
|
152
|
+
return self.world_rect.colliderect(rect)
|
153
|
+
|
154
|
+
def world_to_screen(self, rect: pygame.Rect | pygame.FRect) -> pygame.FRect:
|
155
|
+
return pygame.FRect(
|
156
|
+
(rect[0] - self.world_rect.left), (rect[1] - self.world_rect.top), rect[2], rect[3]
|
157
|
+
)
|
158
|
+
|
159
|
+
def world_to_screen_scaled(self, rect: pygame.Rect | pygame.FRect) -> pygame.FRect:
|
160
|
+
screen_rect = self.world_to_screen(rect)
|
161
|
+
return pygame.FRect(
|
162
|
+
screen_rect.x * self.zoom_factor,
|
163
|
+
screen_rect.y * self.zoom_factor,
|
164
|
+
screen_rect.w * self.zoom_factor,
|
165
|
+
screen_rect.h * self.zoom_factor,
|
166
|
+
)
|
167
|
+
|
168
|
+
def world_to_screen_point(self, point: tuple[float, float] | tuple[int, int]) -> tuple[float, float]:
|
169
|
+
return (
|
170
|
+
(point[0] - self.world_rect.x),
|
171
|
+
(point[1] - self.world_rect.y),
|
172
|
+
)
|
173
|
+
|
174
|
+
def world_to_screen_point_scaled(self, point: tuple[float, float] | tuple[int, int]) -> tuple[float, float]:
|
175
|
+
return (
|
176
|
+
(point[0] - self.world_rect.x) * self.zoom_factor,
|
177
|
+
(point[1] - self.world_rect.y) * self.zoom_factor,
|
178
|
+
)
|
179
|
+
|
180
|
+
|
181
|
+
def screen_to_world(self, point: tuple[float, float] | tuple[int, int]) -> tuple[float, float]:
|
182
|
+
"""
|
183
|
+
roates, scales and translates point to world coordinates
|
184
|
+
|
185
|
+
"""
|
186
|
+
# Center of the screen (zoomed+rotated surface)
|
187
|
+
cx, cy = self.rect.w / 2, self.rect.h / 2
|
188
|
+
|
189
|
+
# Offset from center
|
190
|
+
dx, dy = point[0] - cx, point[1] - cy
|
191
|
+
|
192
|
+
# rotate that offset
|
193
|
+
if self.rotation != 0:
|
194
|
+
angle_rad = math.radians(self.rotation)
|
195
|
+
cos_a = math.cos(angle_rad)
|
196
|
+
sin_a = math.sin(angle_rad)
|
197
|
+
dx, dy = cos_a * dx - sin_a * dy, sin_a * dx + cos_a * dy
|
198
|
+
|
199
|
+
# Un-zoom and add camera position
|
200
|
+
wx = (dx + cx) / self.zoom_factor + self.world_rect.x
|
201
|
+
wy = (dy + cy) / self.zoom_factor + self.world_rect.y
|
202
|
+
return wx, wy
|
203
|
+
|
204
|
+
|
205
|
+
def update(self, dt: float):
|
206
|
+
if not self.follow_point_func or not (math.isfinite(dt) and dt > 0):
|
207
|
+
return
|
208
|
+
|
209
|
+
target = Vector2(self.follow_point_func())
|
210
|
+
self.vector_center.xy.update(self.world_rect.center)
|
211
|
+
|
212
|
+
if self.damping == float("inf"):
|
213
|
+
self.vector_center.xy = target.xy
|
214
|
+
elif math.isfinite(self.damping) and self.damping > 0:
|
215
|
+
damping_factor = 1 - math.exp(-self.damping * dt)
|
216
|
+
if not math.isnan(damping_factor):
|
217
|
+
diff = target - self.vector_center
|
218
|
+
self.vector_center += diff * damping_factor
|
219
|
+
|
220
|
+
self.world_rect.center = self.vector_center
|
221
|
+
|
222
|
+
|
223
|
+
def draw(self, surface: pygame.Surface):
|
224
|
+
"""
|
225
|
+
Draw the camera view onto the provided surface with proper scaling and rotation.
|
226
|
+
|
227
|
+
Args:
|
228
|
+
surface (pygame.Surface): Surface to draw the camera view onto.
|
229
|
+
"""
|
230
|
+
# Scale the camera surface to the target size
|
231
|
+
if self.zoom_factor == 1 and self.rotation == 0:
|
232
|
+
surface.blit(self.surface, (0, 0), special_flags=self.blit_special_flags)
|
233
|
+
return
|
234
|
+
|
235
|
+
pygame.transform.scale(self.surface, self.rect.size, self.transform_target_surface)
|
236
|
+
|
237
|
+
result_surface = self.transform_target_surface
|
238
|
+
|
239
|
+
if self.rotation != 0:
|
240
|
+
# Rotate around the center of the target surface
|
241
|
+
rotated_surface = pygame.transform.rotate(result_surface, self.rotation)
|
242
|
+
rect = rotated_surface.get_rect(center=(self.rect.w // 2, self.rect.h // 2))
|
243
|
+
surface.blit(rotated_surface, rect.topleft, special_flags=self.blit_special_flags)
|
244
|
+
else:
|
245
|
+
surface.blit(result_surface, (0, 0), special_flags=self.blit_special_flags)
|
batFramework/constants.py
CHANGED
@@ -1,75 +1,57 @@
|
|
1
|
-
import pygame
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
Constants.
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
@staticmethod
|
48
|
-
def
|
49
|
-
Constants.
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
DARK_BLUE = (44, 62, 80)
|
59
|
-
GREEN = (67, 160, 71)
|
60
|
-
DARK_GREEN = (39, 174, 96)
|
61
|
-
BROWN = (109, 76, 65)
|
62
|
-
DARK_RED = (192, 57, 43)
|
63
|
-
ORANGE = (251, 140, 0)
|
64
|
-
CLOUD_WHITE = (236, 240, 241)
|
65
|
-
SILVER = (189, 195, 199)
|
66
|
-
DARK_GRAY = (66, 66, 66)
|
67
|
-
|
68
|
-
DARK_GB = (27, 42, 9)
|
69
|
-
SHADE_GB = (14, 69, 11)
|
70
|
-
BASE_GB = (73, 107, 34)
|
71
|
-
LIGHT_GB = (154, 158, 63)
|
72
|
-
|
73
|
-
class Axis(Enum):
|
74
|
-
HORIZONTAL = 1
|
75
|
-
VERTICAL = 2
|
1
|
+
import pygame
|
2
|
+
|
3
|
+
|
4
|
+
class Constants:
|
5
|
+
SCREEN: pygame.Surface = None
|
6
|
+
RESOLUTION: tuple[int, int] = (1280, 720)
|
7
|
+
WIDTH = 1280
|
8
|
+
HEIGHT = 720
|
9
|
+
VSYNC = 0
|
10
|
+
FLAGS: int = pygame.SCALED | pygame.RESIZABLE
|
11
|
+
FPS: int = 60
|
12
|
+
MUSIC_END_EVENT = pygame.event.custom_type()
|
13
|
+
|
14
|
+
DEFAULT_CURSOR = pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)
|
15
|
+
DEFAULT_HOVER_CURSOR = pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)
|
16
|
+
DEFAULT_CLICK_CURSOR = pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)
|
17
|
+
|
18
|
+
BF_INITIALIZED: bool = False
|
19
|
+
ALLOW_DEBUG : bool = True
|
20
|
+
|
21
|
+
WIDGET_KEY_REPEAT_DELAY = 200
|
22
|
+
WIDGET_KEY_REPEAT_INTERVAL = 50
|
23
|
+
GLOBAL_KEY_REPEAT_DELAY = 200
|
24
|
+
GLOBAL_KEY_REPEAT_INTERVAL = 50
|
25
|
+
|
26
|
+
|
27
|
+
@staticmethod
|
28
|
+
def set_allow_debug(allow_debug:bool):
|
29
|
+
Constants.ALLOW_DEBUG = allow_debug
|
30
|
+
|
31
|
+
@staticmethod
|
32
|
+
def set_resolution(resolution: tuple[int, int]):
|
33
|
+
Constants.RESOLUTION = resolution
|
34
|
+
Constants.WIDTH = resolution[0]
|
35
|
+
Constants.HEIGHT = resolution[1]
|
36
|
+
Constants.update_screen()
|
37
|
+
|
38
|
+
@staticmethod
|
39
|
+
def update_screen():
|
40
|
+
if Constants.BF_INITIALIZED:
|
41
|
+
Constants.SCREEN = pygame.display.set_mode(Constants.RESOLUTION,Constants.FLAGS,vsync=Constants.VSYNC)
|
42
|
+
|
43
|
+
@staticmethod
|
44
|
+
def set_default_cursor(cursor: pygame.Cursor):
|
45
|
+
Constants.DEFAULT_CURSOR = cursor
|
46
|
+
|
47
|
+
@staticmethod
|
48
|
+
def set_default_hover_cursor(cursor: pygame.Cursor):
|
49
|
+
Constants.DEFAULT_HOVER_CURSOR = cursor
|
50
|
+
|
51
|
+
@staticmethod
|
52
|
+
def set_default_click_cursor(cursor: pygame.Cursor):
|
53
|
+
Constants.DEFAULT_CLICK_CURSOR = cursor
|
54
|
+
|
55
|
+
@staticmethod
|
56
|
+
def set_fps_limit(value: int):
|
57
|
+
Constants.FPS = value
|