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.
- batFramework/__init__.py +52 -76
- batFramework/action.py +99 -126
- batFramework/actionContainer.py +9 -53
- batFramework/animatedSprite.py +114 -56
- batFramework/audioManager.py +36 -82
- batFramework/camera.py +69 -263
- batFramework/constants.py +53 -29
- batFramework/cutscene.py +109 -243
- batFramework/cutsceneBlocks.py +176 -0
- batFramework/debugger.py +48 -0
- batFramework/dynamicEntity.py +9 -16
- batFramework/easing.py +71 -0
- batFramework/entity.py +85 -92
- batFramework/gui/__init__.py +3 -14
- batFramework/gui/button.py +78 -12
- batFramework/gui/constraints.py +204 -0
- batFramework/gui/container.py +31 -188
- batFramework/gui/debugger.py +43 -126
- batFramework/gui/frame.py +19 -0
- batFramework/gui/image.py +20 -55
- batFramework/gui/indicator.py +22 -95
- batFramework/gui/interactiveWidget.py +12 -229
- batFramework/gui/label.py +77 -311
- batFramework/gui/layout.py +66 -414
- batFramework/gui/root.py +35 -203
- batFramework/gui/shape.py +57 -247
- batFramework/gui/toggle.py +48 -114
- batFramework/gui/widget.py +243 -457
- batFramework/manager.py +29 -113
- batFramework/particles.py +77 -0
- batFramework/scene.py +217 -22
- batFramework/sceneManager.py +129 -161
- batFramework/stateMachine.py +8 -11
- batFramework/time.py +75 -0
- batFramework/transition.py +124 -129
- batFramework/transitionManager.py +0 -0
- batFramework/triggerZone.py +4 -4
- batFramework/utils.py +144 -266
- {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/METADATA +24 -22
- batframework-1.1.0.dist-info/RECORD +43 -0
- batFramework/animation.py +0 -77
- batFramework/baseScene.py +0 -240
- batFramework/cutsceneManager.py +0 -34
- batFramework/drawable.py +0 -77
- batFramework/easingController.py +0 -58
- batFramework/enums.py +0 -135
- batFramework/fontManager.py +0 -65
- batFramework/gui/animatedLabel.py +0 -89
- batFramework/gui/clickableWidget.py +0 -244
- batFramework/gui/constraints/__init__.py +0 -1
- batFramework/gui/constraints/constraints.py +0 -980
- batFramework/gui/draggableWidget.py +0 -44
- batFramework/gui/meter.py +0 -96
- batFramework/gui/radioButton.py +0 -35
- batFramework/gui/selector.py +0 -250
- batFramework/gui/slider.py +0 -397
- batFramework/gui/style.py +0 -10
- batFramework/gui/styleManager.py +0 -54
- batFramework/gui/syncedVar.py +0 -49
- batFramework/gui/textInput.py +0 -306
- batFramework/gui/tooltip.py +0 -30
- batFramework/particle.py +0 -118
- batFramework/propertyEaser.py +0 -79
- batFramework/renderGroup.py +0 -34
- batFramework/resourceManager.py +0 -130
- batFramework/sceneLayer.py +0 -138
- batFramework/scrollingSprite.py +0 -115
- batFramework/sprite.py +0 -51
- batFramework/templates/__init__.py +0 -1
- batFramework/templates/controller.py +0 -97
- batFramework/tileset.py +0 -46
- batFramework/timeManager.py +0 -213
- batframework-1.0.9a11.dist-info/RECORD +0 -67
- {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/LICENSE +0 -0
- {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/WHEEL +0 -0
- {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/top_level.txt +0 -0
batFramework/utils.py
CHANGED
@@ -1,16 +1,11 @@
|
|
1
1
|
import pygame
|
2
|
+
from enum import Enum
|
3
|
+
import os
|
2
4
|
import batFramework as bf
|
3
|
-
import
|
4
|
-
import random
|
5
|
-
from .enums import *
|
6
|
-
import re
|
7
|
-
from typing import Callable, TYPE_CHECKING
|
8
|
-
from functools import cache
|
9
|
-
if TYPE_CHECKING:
|
10
|
-
from .drawable import Drawable
|
11
|
-
from .entity import Entity
|
12
|
-
from pygame.math import Vector2
|
5
|
+
import json
|
13
6
|
|
7
|
+
MAX_FONT_SIZE = 100
|
8
|
+
MIN_FONT_SIZE = 8
|
14
9
|
|
15
10
|
class Singleton(type):
|
16
11
|
_instances = {}
|
@@ -21,286 +16,169 @@ class Singleton(type):
|
|
21
16
|
return cls._instances[cls]
|
22
17
|
|
23
18
|
|
24
|
-
class
|
19
|
+
class Direction(Enum):
|
20
|
+
HORIZONTAL = "horizontal"
|
21
|
+
VERTICAL = "vertical"
|
25
22
|
|
26
|
-
@staticmethod
|
27
|
-
def split_surface(
|
28
|
-
surface: pygame.Surface, split_size: tuple[int, int], func=None
|
29
|
-
) -> dict[tuple[int, int], pygame.Surface]:
|
30
|
-
"""
|
31
|
-
Splits a surface into subsurfaces based on a given size and returns a dictionary of them with their coordinates as keys.
|
32
23
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
24
|
+
class Alignment(Enum):
|
25
|
+
LEFT = "left"
|
26
|
+
RIGHT = "right"
|
27
|
+
CENTER = "center"
|
28
|
+
TOP = "top"
|
29
|
+
BOTTOM = "bottom"
|
37
30
|
|
38
|
-
Returns:
|
39
|
-
dict[tuple[int, int], pygame.Surface]: A dictionary with (x, y) coordinates as keys and the corresponding subsurfaces as values.
|
40
|
-
"""
|
41
|
-
width, height = surface.get_size()
|
42
|
-
res = {}
|
43
|
-
for iy, y in enumerate(range(0, height, split_size[1])):
|
44
|
-
for ix, x in enumerate(range(0, width, split_size[0])):
|
45
|
-
sub = surface.subsurface((x, y, split_size[0], split_size[1]))
|
46
31
|
|
47
|
-
|
48
|
-
|
32
|
+
class Layout(Enum):
|
33
|
+
FILL = "fill"
|
34
|
+
FIT = "fit"
|
49
35
|
|
50
|
-
res[(ix, iy)] = sub
|
51
36
|
|
52
|
-
|
37
|
+
class Utils:
|
38
|
+
pygame.font.init()
|
39
|
+
FONTS = {}
|
40
|
+
tilesets = {}
|
53
41
|
|
54
42
|
@staticmethod
|
55
|
-
def
|
56
|
-
|
57
|
-
Filters a string based on the specified text mode.
|
58
|
-
|
59
|
-
Args:
|
60
|
-
text_mode (textMode): Mode specifying the type of filtering (ALPHABETICAL, NUMERICAL, ALPHANUMERICAL).
|
61
|
-
|
62
|
-
Returns:
|
63
|
-
callable: A function that takes a string and removes all characters not allowed by the text mode.
|
64
|
-
|
65
|
-
Raises:
|
66
|
-
ValueError: If an unsupported text mode is provided.
|
67
|
-
"""
|
68
|
-
|
69
|
-
if text_mode == textMode.ALPHABETICAL:
|
70
|
-
pattern = re.compile(r"[^a-zA-Z]")
|
71
|
-
elif text_mode == textMode.NUMERICAL:
|
72
|
-
pattern = re.compile(r"[^0-9]")
|
73
|
-
elif text_mode == textMode.ALPHANUMERICAL:
|
74
|
-
pattern = re.compile(r"[^a-zA-Z0-9]")
|
75
|
-
else:
|
76
|
-
raise ValueError("Unsupported text mode")
|
77
|
-
|
78
|
-
def filter_function(s: str) -> str:
|
79
|
-
return pattern.sub("", s)
|
80
|
-
|
81
|
-
return filter_function
|
82
|
-
|
43
|
+
def get_path(path: str):
|
44
|
+
return os.path.join(bf.const.RESOURCE_PATH, path)
|
83
45
|
|
84
46
|
@staticmethod
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
radius_stop (int, optional): Radius where the spotlight ends. Defaults to the value of radius.
|
94
|
-
dest_surf (pygame.Surface, optional): Surface to draw the spotlight on. Defaults to None.
|
95
|
-
size (tuple[int, int], optional): Size of the surface if dest_surf is None. Defaults to a square based on radius_stop.
|
96
|
-
|
97
|
-
Returns:
|
98
|
-
pygame.Surface: The surface with the spotlight effect drawn on it.
|
99
|
-
"""
|
100
|
-
|
101
|
-
if radius_stop is None:
|
102
|
-
radius_stop = radius
|
103
|
-
diameter = radius_stop * 2
|
104
|
-
|
105
|
-
if dest_surf is None:
|
106
|
-
if size is None:
|
107
|
-
size = (diameter,diameter)
|
108
|
-
dest_surf = pygame.Surface(size, pygame.SRCALPHA)
|
109
|
-
|
110
|
-
dest_surf.fill((0,0,0,0))
|
111
|
-
|
112
|
-
|
113
|
-
center = dest_surf.get_rect().center
|
114
|
-
|
115
|
-
if radius_stop != radius:
|
116
|
-
for r in range(radius_stop, radius - 1, -1):
|
117
|
-
color = [
|
118
|
-
inside_color[i] + (outside_color[i] - inside_color[i]) * (r - radius) / (radius_stop - radius)
|
119
|
-
for i in range(3)
|
120
|
-
] + [255] # Preserve the alpha channel as fully opaque
|
121
|
-
pygame.draw.circle(dest_surf, color, center, r)
|
122
|
-
else:
|
123
|
-
pygame.draw.circle(dest_surf, inside_color, center, radius)
|
124
|
-
|
125
|
-
return dest_surf
|
47
|
+
def load_json_from_file(path: str) -> dict:
|
48
|
+
try:
|
49
|
+
with open(Utils.get_path(path), "r") as file:
|
50
|
+
data = json.load(file)
|
51
|
+
return data
|
52
|
+
except FileNotFoundError:
|
53
|
+
print(f"File '{path}' not found")
|
54
|
+
return None
|
126
55
|
|
127
56
|
@staticmethod
|
128
|
-
def
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
radius (int): Radius of the inner circle.
|
137
|
-
radius_stop (int, optional): Radius where the spotlight ends. Defaults to the value of radius.
|
138
|
-
center (tuple[int, int], optional): Center point of the spotlight. Defaults to the center of dest_surf.
|
139
|
-
"""
|
140
|
-
|
141
|
-
if radius_stop is None:
|
142
|
-
radius_stop = radius
|
143
|
-
center = dest_surf.get_rect().center if center is None else center
|
144
|
-
if radius_stop != radius:
|
145
|
-
for r in range(radius_stop, radius - 1, -1):
|
146
|
-
color = [
|
147
|
-
inside_color[i] + (outside_color[i] - inside_color[i]) * (r - radius) / (radius_stop - radius)
|
148
|
-
for i in range(3)
|
149
|
-
] + [255]
|
150
|
-
pygame.draw.circle(dest_surf, color, center, r)
|
151
|
-
else:
|
152
|
-
pygame.draw.circle(dest_surf, inside_color, center, radius)
|
153
|
-
|
154
|
-
|
57
|
+
def save_json_to_file(path: str, data) -> bool:
|
58
|
+
try:
|
59
|
+
with open(Utils.get_path(path), "w") as file:
|
60
|
+
json.dump(data, file, indent=2)
|
61
|
+
return True
|
62
|
+
except FileNotFoundError:
|
63
|
+
return False
|
64
|
+
|
155
65
|
@staticmethod
|
156
|
-
def
|
157
|
-
|
158
|
-
|
66
|
+
def init_font(raw_path:str):
|
67
|
+
try :
|
68
|
+
if raw_path is not None:
|
69
|
+
Utils.load_font(raw_path if raw_path else None,None)
|
70
|
+
Utils.load_font(raw_path)
|
71
|
+
except FileNotFoundError:
|
72
|
+
Utils.load_sysfont(raw_path)
|
73
|
+
Utils.load_sysfont(raw_path,None)
|
159
74
|
|
160
|
-
Args:
|
161
|
-
min_value (int): Minimum value for each RGB component (inclusive). Defaults to 0.
|
162
|
-
max_value (int): Maximum value for each RGB component (inclusive). Defaults to 255.
|
163
|
-
|
164
|
-
Returns:
|
165
|
-
tuple[int, int, int]: A tuple representing a random color in RGB format, with each component
|
166
|
-
between min_value and max_value.
|
167
|
-
"""
|
168
|
-
return random.randint(min_value, max_value), random.randint(min_value, max_value), random.randint(min_value, max_value)
|
169
75
|
|
170
76
|
@staticmethod
|
171
|
-
def
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
77
|
+
def load_font(path:str,name:str=''):
|
78
|
+
if path is not None: path = Utils.get_path(path) # convert path if given
|
79
|
+
filename = os.path.basename(path).split('.')[0] if path is not None else None # get filename if path is given, else None
|
80
|
+
if name != '' : filename = name # if name is not given, name is the filename
|
81
|
+
Utils.FONTS[filename] = {}
|
82
|
+
# fill the dict
|
83
|
+
for size in range(MIN_FONT_SIZE, MAX_FONT_SIZE, 2):
|
84
|
+
Utils.FONTS[filename][size] = pygame.font.Font(path,size=size)
|
85
|
+
|
86
|
+
def load_sysfont(font_name:str,key:str=''):
|
87
|
+
if key == '' : key = font_name
|
88
|
+
if pygame.font.match_font(font_name) is None:
|
89
|
+
raise FileNotFoundError(f"Requested font '{font_namey}' was not found")
|
90
|
+
Utils.FONTS[font_name] = {}
|
91
|
+
|
92
|
+
for size in range(MIN_FONT_SIZE, MAX_FONT_SIZE, 2):
|
93
|
+
Utils.FONTS[key][size] = pygame.font.SysFont(font_name,size=size)
|
94
|
+
|
186
95
|
|
187
96
|
@staticmethod
|
188
|
-
def
|
189
|
-
|
97
|
+
def get_font(name:str|None=None,text_size:int=12) -> pygame.Font:
|
98
|
+
if not name in Utils.FONTS: return None
|
99
|
+
if not text_size in Utils.FONTS[name]: return None
|
100
|
+
return Utils.FONTS[name][text_size]
|
101
|
+
|
102
|
+
class Tileset:
|
103
|
+
_flip_cache = {} # {"tileset":tileset,"index","flipX","flipY"}
|
104
|
+
|
105
|
+
def __init__(self, surface: pygame.Surface, tilesize) -> None:
|
106
|
+
self.tile_dict = {}
|
107
|
+
self.surface = surface
|
108
|
+
self.tile_size = tilesize
|
109
|
+
self.split_surface(surface)
|
110
|
+
|
111
|
+
def split_surface(self, surface: pygame.Surface):
|
112
|
+
width, height = surface.get_size()
|
113
|
+
num_tiles_x = width // self.tile_size
|
114
|
+
num_tiles_y = height // self.tile_size
|
115
|
+
# Iterate over the tiles vertically and horizontally
|
116
|
+
for y in range(num_tiles_y):
|
117
|
+
for x in range(num_tiles_x):
|
118
|
+
# Calculate the coordinates of the current tile in the tileset
|
119
|
+
tile_x = x * self.tile_size
|
120
|
+
tile_y = y * self.tile_size
|
121
|
+
# Create a subsurface for the current tile
|
122
|
+
tile_surface = surface.subsurface(
|
123
|
+
pygame.Rect(tile_x, tile_y, self.tile_size, self.tile_size)
|
124
|
+
)
|
125
|
+
# Calculate the unique key for the tile (e.g., based on its coordinates)
|
126
|
+
tile_key = (x, y)
|
127
|
+
# Store the subsurface in the dictionary with the corresponding key
|
128
|
+
self.tile_dict[tile_key] = tile_surface
|
129
|
+
# print(self.tile_dict)
|
130
|
+
|
131
|
+
def get_tile(self, x, y, flipX=False, flipY=False) -> pygame.Surface | None:
|
132
|
+
if (x, y) not in self.tile_dict:
|
133
|
+
return None
|
134
|
+
if flipX or flipY:
|
135
|
+
key = f"{x}{y}:{flipX}{flipY}"
|
136
|
+
if not key in self._flip_cache:
|
137
|
+
self._flip_cache[key] = pygame.transform.flip(
|
138
|
+
self.tile_dict[(x, y)], flipX, flipY
|
139
|
+
)
|
140
|
+
return self._flip_cache[key]
|
141
|
+
return self.tile_dict[(x, y)]
|
190
142
|
|
191
143
|
@staticmethod
|
192
|
-
def
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
144
|
+
def img_slice(file, cell_width, cell_height, flipX=False) -> list[pygame.Surface]:
|
145
|
+
src = pygame.image.load(
|
146
|
+
os.path.join(bf.const.RESOURCE_PATH, file)
|
147
|
+
).convert_alpha()
|
148
|
+
width, height = src.get_size()
|
149
|
+
res = []
|
150
|
+
for y in range(0, height, cell_height):
|
151
|
+
for x in range(0, width, cell_width):
|
152
|
+
sub = src.subsurface((x, y, cell_width, cell_height))
|
153
|
+
if flipX:
|
154
|
+
sub = pygame.transform.flip(sub, True, False)
|
155
|
+
|
156
|
+
res.append(sub)
|
157
|
+
return res
|
201
158
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
Draw a filled triangle inside a rectangle on a Pygame surface, pointing in the specified direction.
|
206
|
-
|
207
|
-
Args:
|
208
|
-
surface: The Pygame surface to draw on.
|
209
|
-
color: The color of the triangle (e.g., (255, 0, 0) for red).
|
210
|
-
rect: A pygame.Rect object defining the rectangle's position and size.
|
211
|
-
direction: A string ('up', 'down', 'left', 'right') indicating the triangle's orientation.
|
212
|
-
"""
|
213
|
-
# Define the three vertices of the triangle based on direction
|
214
|
-
rect = rect.copy()
|
215
|
-
rect.inflate_ip(-1,-1)
|
216
|
-
if direction == direction.UP:
|
217
|
-
points = [
|
218
|
-
(rect.left, rect.bottom), # Bottom-left corner
|
219
|
-
(rect.right, rect.bottom), # Bottom-right corner
|
220
|
-
(rect.centerx, rect.top) # Top center (apex)
|
221
|
-
]
|
222
|
-
elif direction == direction.DOWN:
|
223
|
-
points = [
|
224
|
-
(rect.left, rect.top), # Top-left corner
|
225
|
-
(rect.right, rect.top), # Top-right corner
|
226
|
-
(rect.centerx, rect.bottom) # Bottom center (apex)
|
227
|
-
]
|
228
|
-
elif direction == direction.LEFT:
|
229
|
-
points = [
|
230
|
-
(rect.right, rect.top), # Top-right corner
|
231
|
-
(rect.right, rect.bottom), # Bottom-right corner
|
232
|
-
(rect.left, rect.centery) # Left center (apex)
|
233
|
-
]
|
234
|
-
elif direction == direction.RIGHT:
|
235
|
-
points = [
|
236
|
-
(rect.left, rect.top), # Top-left corner
|
237
|
-
(rect.left, rect.bottom), # Bottom-left corner
|
238
|
-
(rect.right, rect.centery) # Right center (apex)
|
239
|
-
]
|
159
|
+
def load_tileset(path: str, name: str, tilesize):
|
160
|
+
if name in Utils.tilesets:
|
161
|
+
return Utils.tilesets[name]
|
240
162
|
else:
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
"""
|
248
|
-
Draw a smooth circular arc connecting start_pos and end_pos.
|
249
|
-
`tightness` controls curvature: 0 is straight line, 1 is semicircle, higher = more bulge.
|
250
|
-
Negative tightness flips the bulge direction.
|
251
|
-
|
252
|
-
Args:
|
253
|
-
surface - pygame Surface
|
254
|
-
color - RGB or RGBA
|
255
|
-
start_pos - (x, y)
|
256
|
-
end_pos - (x, y)
|
257
|
-
tightness - curvature control, 0 = straight, 1 = half circle
|
258
|
-
width - line width
|
259
|
-
resolution - approx pixels per segment
|
260
|
-
Returns:
|
261
|
-
pygame.Rect bounding the drawn arc
|
262
|
-
"""
|
263
|
-
p0 = pygame.Vector2(start_pos)
|
264
|
-
p1 = pygame.Vector2(end_pos)
|
265
|
-
chord = p1 - p0
|
266
|
-
if chord.length_squared() == 0:
|
267
|
-
if antialias:
|
268
|
-
return pygame.draw.aacircle(surface, color, p0, width // 2)
|
269
|
-
return pygame.draw.circle(surface, color, p0, width // 2)
|
163
|
+
img = pygame.image.load(
|
164
|
+
os.path.join(bf.const.RESOURCE_PATH, path)
|
165
|
+
).convert_alpha()
|
166
|
+
tileset = Utils.Tileset(img, tilesize)
|
167
|
+
Utils.tilesets[name] = tileset
|
168
|
+
return tileset
|
270
169
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
h = chord.length() * tightness
|
277
|
-
center = mid + perp * h
|
170
|
+
@staticmethod
|
171
|
+
def get_tileset(name: str) -> Tileset:
|
172
|
+
if name not in Utils.tilesets:
|
173
|
+
return None
|
174
|
+
return Utils.tilesets[name]
|
278
175
|
|
279
|
-
# Radius and angles
|
280
|
-
r = (p0 - center).length()
|
281
|
-
ang0 = math.atan2(p0.y - center.y, p0.x - center.x)
|
282
|
-
ang1 = math.atan2(p1.y - center.y, p1.x - center.x)
|
283
176
|
|
284
|
-
|
285
|
-
sweep = ang1 - ang0
|
286
|
-
if tightness > 0 and sweep < 0:
|
287
|
-
sweep += 2 * math.pi
|
288
|
-
elif tightness < 0 and sweep > 0:
|
289
|
-
sweep -= 2 * math.pi
|
177
|
+
|
290
178
|
|
291
|
-
# Number of points
|
292
|
-
arc_len = abs(sweep * r)
|
293
|
-
segs = max(2, int(arc_len / max(resolution, 1)))
|
294
179
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
center.x + math.cos(a) * r,
|
301
|
-
center.y + math.sin(a) * r
|
302
|
-
))
|
303
|
-
if antialias:
|
304
|
-
return pygame.draw.aalines(surface, color, False, points)
|
305
|
-
|
306
|
-
return pygame.draw.lines(surface, color, False, points, width)
|
180
|
+
def move_points(delta, *points):
|
181
|
+
res = []
|
182
|
+
for point in points:
|
183
|
+
res.append((point[0] + delta[0], point[1] + delta[1]))
|
184
|
+
return res
|
@@ -1,8 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: batframework
|
3
|
-
Version: 1.0
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: Pygame framework for making games easier.
|
5
|
-
Author-email: Turan Baturay <baturayturan@gmail.com>
|
6
5
|
License: MIT License
|
7
6
|
|
8
7
|
Copyright (c) [2023] [TURAN BATURAY]
|
@@ -24,10 +23,6 @@ License: MIT License
|
|
24
23
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
24
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
25
|
SOFTWARE.
|
27
|
-
Project-URL: Homepage, https://github.com/TuranBaturay/batFramework
|
28
|
-
Classifier: Programming Language :: Python :: 3
|
29
|
-
Classifier: License :: OSI Approved :: MIT License
|
30
|
-
Classifier: Operating System :: OS Independent
|
31
26
|
Requires-Python: >=3.11
|
32
27
|
Description-Content-Type: text/markdown
|
33
28
|
License-File: LICENSE
|
@@ -35,30 +30,37 @@ Requires-Dist: pygame-ce
|
|
35
30
|
|
36
31
|
# batFramework
|
37
32
|
|
38
|
-
|
33
|
+
batFramework is a Python game framework built using Pygame, designed to simplify game development by providing entities, scenes, a scene manager, and various utilities.
|
39
34
|
|
40
|
-
##
|
35
|
+
## Purpose and Overview
|
36
|
+
The primary objective of batFramework is to streamline game development. It is mainly designed to program small 2D games
|
41
37
|
|
42
|
-
|
38
|
+
## Installation and Setup
|
39
|
+
To install batFramework, you can use pip:
|
40
|
+
```pip install batFramework```
|
43
41
|
|
44
|
-
|
42
|
+
The only dependency required is pygame-ce.
|
45
43
|
|
46
|
-
|
47
|
-
|
48
|
-
- Audio management (music and sound effects with volume control)
|
49
|
-
- Entity, sprite, and animated sprite handling
|
50
|
-
- Transition effects
|
51
|
-
- Utility modules (time management, constants, etc.)
|
52
|
-
- No external dependency except for pygame
|
44
|
+
## Usage Instructions
|
45
|
+
To create a basic app using batFramework, here's an example:
|
53
46
|
|
54
|
-
|
47
|
+
```python
|
48
|
+
import batFramework as bf
|
55
49
|
|
56
|
-
|
57
|
-
|
58
|
-
4. Explore the framework's modules in the `batFramework` directory and integrate them into your own game project.
|
50
|
+
# Initialize the framework
|
51
|
+
bf.init(resolution=(1280, 720), window_caption="My Amazing Program")
|
59
52
|
|
60
|
-
|
53
|
+
# Create a manager and a scene
|
54
|
+
bf.Manager(bf.Scene("main")).run()
|
55
|
+
```
|
56
|
+
In practice, users can inherit bf.Scene to create their own scenes, adding specific behaviors, entities, etc.
|
61
57
|
|
58
|
+
## Features and Functionalities
|
62
59
|
|
60
|
+
For more detailed information, please refer to the [documentation](https://batframework.github.io/batDocumentation/).
|
61
|
+
|
62
|
+
|
63
|
+
# License
|
64
|
+
MIT License
|
63
65
|
|
64
66
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
batFramework/__init__.py,sha256=MLVXC2ymkO3k8LdCgB6TbahgJfhxk4GKAbmndmEgZS4,2146
|
2
|
+
batFramework/action.py,sha256=Phk6-q2P-XyV2GVlXPpxyje0due4fIrKnhI1_4anfjI,7600
|
3
|
+
batFramework/actionContainer.py,sha256=K9dIgG559ckxzRB3t-lpON4dFTcM2mcKZfsf4bhuJ1k,1092
|
4
|
+
batFramework/animatedSprite.py,sha256=kJPKrTOfkbQu2uYDziIEop1z6-gjBwZxkC1Rxd_vBwE,3992
|
5
|
+
batFramework/audioManager.py,sha256=5UsDPy4zsDO7Va1y1kM4lSpEJXU95o9F01E-Sts3osg,2546
|
6
|
+
batFramework/camera.py,sha256=wt4TyWTgQmQElBVeFI7ONzNI75r0FKtB3KmNH00GeFM,4322
|
7
|
+
batFramework/constants.py,sha256=FSyEYLxdAb3JaXA11sAwZBfAImedASohpFcd_7qnG0I,2075
|
8
|
+
batFramework/cutscene.py,sha256=5aiIQeWGmvHCb-N3vjmwxhE4dCXv3iZRFHiexSNxCXM,3650
|
9
|
+
batFramework/cutsceneBlocks.py,sha256=1gmof0jKJ8SqE-RoErm6n1A0JJ4Ang9Q30xEZnW9NaI,5123
|
10
|
+
batFramework/debugger.py,sha256=gh5kOUmGr4t-BFXA17tImid4nzxUqrhsUhE_JV9srNg,1671
|
11
|
+
batFramework/dynamicEntity.py,sha256=REIqH0jnfX6yUThoQNkQrsG0390TR6C5la1h2MAioYk,665
|
12
|
+
batFramework/easing.py,sha256=vGkk7FDPj27X7NCJXALCEyVKDbpXXebWYtMvxkbhOh0,2217
|
13
|
+
batFramework/entity.py,sha256=Tw4_PIA_sY8fhbj9TjE6wPcDTrZZX_Tj7l8oKquqe8U,3178
|
14
|
+
batFramework/manager.py,sha256=LdiQVyuPQE23jwO4EjR4zqDymxtRmthUJ7VE7RIEDpU,1583
|
15
|
+
batFramework/particles.py,sha256=PX8zSqOS1gyDloGAz3fAlrto51lWMUpBXDIM152EYWc,2172
|
16
|
+
batFramework/scene.py,sha256=KM1e53ZfPvuJoSGQZaEl_IouWRYCbFq0QOYTuXYCr-E,7324
|
17
|
+
batFramework/sceneManager.py,sha256=sFkQbfMuR19M4duvCf0SOxSY7MkMrkmiiKh72-tC1nI,5743
|
18
|
+
batFramework/stateMachine.py,sha256=_er9_dcm6MLmlTjXTVm175eqZ9puaKb31PFmNPRhcSU,1338
|
19
|
+
batFramework/time.py,sha256=iGV9mxUFrdXsvm4fJ1faX-VYNsOH7DX2N_aXsDRHhmM,2403
|
20
|
+
batFramework/transition.py,sha256=wmL1Mgg_xopzeDbEPJyAmllLB2BCRJZtuMOR7Mez480,4873
|
21
|
+
batFramework/transitionManager.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
+
batFramework/triggerZone.py,sha256=ikOOlJT1KIND0MO2xiilCHuKlb1eQhkCMEhZTi1btsI,586
|
23
|
+
batFramework/utils.py,sha256=EUB3bMldWTYFVZxcJk5_7XAWcEz080P7PT5ZtkO5TAQ,6164
|
24
|
+
batFramework/gui/__init__.py,sha256=azu5HpC8Q9kupythU5GN5blt7K9oH55oXlOeXsIw1Mw,391
|
25
|
+
batFramework/gui/button.py,sha256=05RMQ20P5npgU9QmiT8v6abJhnhjqRgYbpZGaQXr6Bg,2703
|
26
|
+
batFramework/gui/constraints.py,sha256=pUTNwJqI2Tu57l8ZeQXVXg3b5F5t3aR4Us-CD5qXwnM,7544
|
27
|
+
batFramework/gui/container.py,sha256=XAkPZ0BOVXxzxWP5mKDF_MjYPPPAmUBY-J5zIadO0wQ,1480
|
28
|
+
batFramework/gui/debugger.py,sha256=JORHcSYQQCZ0tDzjnNQvDSOOjZVwEQLeqlr8e6xk2RI,1379
|
29
|
+
batFramework/gui/frame.py,sha256=zjHwbQT1fpRuvNgfBGZhMO_GdMEWqExa5dNlN9kUnUM,514
|
30
|
+
batFramework/gui/image.py,sha256=goOcPntsJeTb3LR7avzi4cXfYHwyGb0KXYttbCiE6fA,777
|
31
|
+
batFramework/gui/indicator.py,sha256=OgqDFsi2HCfbSzVjHkHO_shmo4q4ro3wfd0LWSLTJeQ,957
|
32
|
+
batFramework/gui/interactiveWidget.py,sha256=rRElxI1eFkvOeTfTaA6f8kVTOswOD-DFLAJDUCAI_Yk,641
|
33
|
+
batFramework/gui/label.py,sha256=EO1J5zPVe1skHz-KVqXKBZVKug8UVJUCXyHnvdRDuig,3586
|
34
|
+
batFramework/gui/layout.py,sha256=HyVhYTy1AQacALg6XMY5aX5lj7WY__HCCh8sTSBXwgI,3210
|
35
|
+
batFramework/gui/root.py,sha256=mhlu8ohqq8N-8q__ugv_tGRgPv-1jIHXBFezMFZ4mUM,1763
|
36
|
+
batFramework/gui/shape.py,sha256=CYaD0BdCiuGJO_tS2pALfKPlNGaGRNPzvy-Lk08_R8g,2490
|
37
|
+
batFramework/gui/toggle.py,sha256=jAeEyQXA893gDBUmjN7aoGgfsVln5RTODpSFB4LxwTY,2020
|
38
|
+
batFramework/gui/widget.py,sha256=1PkxThmet8nI5rvSDE6-iPtD_DsZkk-OxriZHbBZaFc,10509
|
39
|
+
batframework-1.1.0.dist-info/LICENSE,sha256=A65iXbMDbOxQLDNOODJLqA7o5RxszYlEqIgNSzBQRf4,1073
|
40
|
+
batframework-1.1.0.dist-info/METADATA,sha256=rykq5QH77bM0rueFOF2N93HiLgFuZHRPWc_4Nl-YTHs,2515
|
41
|
+
batframework-1.1.0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
42
|
+
batframework-1.1.0.dist-info/top_level.txt,sha256=vxAKBIk1oparFTxeXGBrgfIO7iq_YR5Fv1JvPVAIwmA,13
|
43
|
+
batframework-1.1.0.dist-info/RECORD,,
|
batFramework/animation.py
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
import pygame
|
2
|
-
import batFramework as bf
|
3
|
-
from typing import List, Dict, Tuple, Union, Optional, Self
|
4
|
-
|
5
|
-
|
6
|
-
def search_index(target: int, lst: List[int]) -> int:
|
7
|
-
cumulative_sum = 0
|
8
|
-
for index, value in enumerate(lst):
|
9
|
-
cumulative_sum += value
|
10
|
-
if cumulative_sum >= target:
|
11
|
-
return index
|
12
|
-
return -1
|
13
|
-
|
14
|
-
|
15
|
-
class Animation:
|
16
|
-
def __init__(
|
17
|
-
self,
|
18
|
-
name: str
|
19
|
-
) -> None:
|
20
|
-
"""
|
21
|
-
Class to hold 2D animation data.
|
22
|
-
All frames are expected to have the same size.
|
23
|
-
This class does not do anything on its own, but can be used to easily manage
|
24
|
-
multiple animations using a simple counter.
|
25
|
-
The duration list provides a entry point for tweaking the timings,
|
26
|
-
so image data can be saved (no need for contiguous duplicate frames)
|
27
|
-
"""
|
28
|
-
self.name = name
|
29
|
-
self.frames: list[pygame.Surface] = []
|
30
|
-
self.frames_flipX : list[pygame.Surface] = []
|
31
|
-
self.duration_list = []
|
32
|
-
self.duration_list_length = 0 # prevents calling len() each frame
|
33
|
-
self.numFrames : int = 0
|
34
|
-
|
35
|
-
def from_surface(self,surface:pygame.Surface,frame_size : Tuple[int,int])->Self:
|
36
|
-
"""
|
37
|
-
Loads frames from a spritesheet containing all animation frames aligned horizontally, left to right
|
38
|
-
Frames are cut and stored in 2 versions, original and flipped on the horizontal axis.
|
39
|
-
Flipping sprites being pretty common, this serves as a builtin cache.
|
40
|
-
"""
|
41
|
-
self.frames : List[pygame.Surface] = list(
|
42
|
-
bf.utils.split_surface(surface, frame_size).values()
|
43
|
-
)
|
44
|
-
self.frames_flipX : List[pygame.Surface] = list(
|
45
|
-
bf.utils.split_surface(
|
46
|
-
surface, frame_size,
|
47
|
-
func=lambda s : pygame.transform.flip(s,True,False)
|
48
|
-
).values()
|
49
|
-
)
|
50
|
-
self.duration_list_length = len(self.frames)
|
51
|
-
self.numFrames = self.duration_list_length
|
52
|
-
if not self.duration_list:
|
53
|
-
self.duration_list = [1]*self.duration_list_length
|
54
|
-
return self
|
55
|
-
|
56
|
-
def __repr__(self):
|
57
|
-
return f"Animation({self.name})"
|
58
|
-
|
59
|
-
def counter_to_frame(self, counter: Union[float, int]) -> int:
|
60
|
-
if not self.frames :
|
61
|
-
raise ValueError("Animation has no frames")
|
62
|
-
return search_index(
|
63
|
-
int(counter % self.duration_list_length), self.duration_list
|
64
|
-
)
|
65
|
-
|
66
|
-
def get_frame(self, counter: Union[float, int], flip: bool) -> pygame.Surface:
|
67
|
-
i = self.counter_to_frame(counter)
|
68
|
-
return self.frames_flipX[i] if flip else self.frames[i]
|
69
|
-
|
70
|
-
def set_duration_list(self, duration_list: Union[List[int], int]) -> Self:
|
71
|
-
if isinstance(duration_list, int):
|
72
|
-
duration_list = [duration_list] * len(self.frames)
|
73
|
-
if len(duration_list) != self.numFrames:
|
74
|
-
raise ValueError("duration_list should have values for all frames")
|
75
|
-
self.duration_list = duration_list
|
76
|
-
self.duration_list_length = sum(self.duration_list)
|
77
|
-
return self
|