batframework 1.0.9a11__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. batFramework/__init__.py +52 -76
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +114 -56
  5. batFramework/audioManager.py +36 -82
  6. batFramework/camera.py +69 -263
  7. batFramework/constants.py +53 -29
  8. batFramework/cutscene.py +109 -243
  9. batFramework/cutsceneBlocks.py +176 -0
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -16
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +85 -92
  14. batFramework/gui/__init__.py +3 -14
  15. batFramework/gui/button.py +78 -12
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +31 -188
  18. batFramework/gui/debugger.py +43 -126
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -55
  21. batFramework/gui/indicator.py +22 -95
  22. batFramework/gui/interactiveWidget.py +12 -229
  23. batFramework/gui/label.py +77 -311
  24. batFramework/gui/layout.py +66 -414
  25. batFramework/gui/root.py +35 -203
  26. batFramework/gui/shape.py +57 -247
  27. batFramework/gui/toggle.py +48 -114
  28. batFramework/gui/widget.py +243 -457
  29. batFramework/manager.py +29 -113
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +217 -22
  32. batFramework/sceneManager.py +129 -161
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +75 -0
  35. batFramework/transition.py +124 -129
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +4 -4
  38. batFramework/utils.py +144 -266
  39. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/METADATA +24 -22
  40. batframework-1.1.0.dist-info/RECORD +43 -0
  41. batFramework/animation.py +0 -77
  42. batFramework/baseScene.py +0 -240
  43. batFramework/cutsceneManager.py +0 -34
  44. batFramework/drawable.py +0 -77
  45. batFramework/easingController.py +0 -58
  46. batFramework/enums.py +0 -135
  47. batFramework/fontManager.py +0 -65
  48. batFramework/gui/animatedLabel.py +0 -89
  49. batFramework/gui/clickableWidget.py +0 -244
  50. batFramework/gui/constraints/__init__.py +0 -1
  51. batFramework/gui/constraints/constraints.py +0 -980
  52. batFramework/gui/draggableWidget.py +0 -44
  53. batFramework/gui/meter.py +0 -96
  54. batFramework/gui/radioButton.py +0 -35
  55. batFramework/gui/selector.py +0 -250
  56. batFramework/gui/slider.py +0 -397
  57. batFramework/gui/style.py +0 -10
  58. batFramework/gui/styleManager.py +0 -54
  59. batFramework/gui/syncedVar.py +0 -49
  60. batFramework/gui/textInput.py +0 -306
  61. batFramework/gui/tooltip.py +0 -30
  62. batFramework/particle.py +0 -118
  63. batFramework/propertyEaser.py +0 -79
  64. batFramework/renderGroup.py +0 -34
  65. batFramework/resourceManager.py +0 -130
  66. batFramework/sceneLayer.py +0 -138
  67. batFramework/scrollingSprite.py +0 -115
  68. batFramework/sprite.py +0 -51
  69. batFramework/templates/__init__.py +0 -1
  70. batFramework/templates/controller.py +0 -97
  71. batFramework/tileset.py +0 -46
  72. batFramework/timeManager.py +0 -213
  73. batframework-1.0.9a11.dist-info/RECORD +0 -67
  74. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/LICENSE +0 -0
  75. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/WHEEL +0 -0
  76. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/top_level.txt +0 -0
batFramework/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 math
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 Utils:
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
- Args:
34
- surface (pygame.Surface): The surface to be split.
35
- split_size (tuple[int, int]): The size of each subsurface (width, height).
36
- func (callable, optional): A function to apply to each subsurface. Defaults to None.
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
- if func is not None:
48
- sub = func(sub)
32
+ class Layout(Enum):
33
+ FILL = "fill"
34
+ FIT = "fit"
49
35
 
50
- res[(ix, iy)] = sub
51
36
 
52
- return res
37
+ class Utils:
38
+ pygame.font.init()
39
+ FONTS = {}
40
+ tilesets = {}
53
41
 
54
42
  @staticmethod
55
- def filter_text(text_mode: textMode):
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 create_spotlight(inside_color, outside_color, radius, radius_stop=None, dest_surf=None,size=None):
86
- """
87
- Creates a spotlight effect on a surface with a gradient from inside_color to outside_color.
88
-
89
- Args:
90
- inside_color (tuple[int, int, int]): RGB color at the center of the spotlight.
91
- outside_color (tuple[int, int, int]): RGB color at the outer edge of the spotlight.
92
- radius (int): Radius of the inner circle.
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 draw_spotlight(dest_surf:pygame.Surface,inside_color,outside_color,radius,radius_stop=None,center=None):
129
- """
130
- Draws a spotlight effect directly onto an existing surface.
131
-
132
- Args:
133
- dest_surf (pygame.Surface): The surface to draw the spotlight on.
134
- inside_color (tuple[int, int, int]): RGB color at the center of the spotlight.
135
- outside_color (tuple[int, int, int]): RGB color at the outer edge of the spotlight.
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 random_color(min_value: int = 0, max_value: int = 255) -> tuple[int, int, int]:
157
- """
158
- Generates a random color as an RGB tuple.
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 random_point_on_screen(margin: int = 0) -> tuple[int, int]:
172
- """
173
- Generates a random point on the screen, considering a margin from the edges.
174
-
175
- Args:
176
- margin (int): Margin from the screen edges, where the point won't be generated.
177
- If margin is less than 0 or greater than half the screen resolution, returns (0, 0).
178
-
179
- Returns:
180
- tuple[int, int]: A tuple representing a random point (x, y) on the screen within the screen
181
- resolution minus the margin.
182
- """
183
- if margin < 0 or margin > bf.const.RESOLUTION[0]//2 or margin > bf.const.RESOLUTION[1]//2:
184
- return 0, 0
185
- return random.randint(margin, bf.const.RESOLUTION[0] - margin), random.randint(margin, bf.const.RESOLUTION[1] - margin)
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 distance_point(a:tuple[float,float],b:tuple[float,float]):
189
- return math.sqrt((a[0]-b[0]) ** 2 + (a[1]-b[1])**2)
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 rotate_point(point: Vector2, angle: float, center: Vector2) -> Vector2:
193
- """Rotate a point around a center by angle (in degrees)."""
194
- rad = math.radians(angle)
195
- translated = point - center
196
- rotated = Vector2(
197
- translated.x * math.cos(rad) - translated.y * math.sin(rad),
198
- translated.x * math.sin(rad) + translated.y * math.cos(rad)
199
- )
200
- return rotated + center
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
- def draw_triangle(surface:pygame.Surface, color, rect:pygame.FRect|pygame.Rect, direction:bf.enums.direction=bf.enums.direction.RIGHT,width:int=0):
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
- raise ValueError("Invalid direction")
242
-
243
- # Draw the filled triangle
244
- pygame.draw.polygon(surface, color, points,width=width)
245
-
246
- def draw_arc_by_points(surface, color, start_pos, end_pos, tightness=0.5, width=1, resolution=0.5,antialias:bool=False):
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
- # Midpoint and perpendicular
272
- mid = (p0 + p1) * 0.5
273
- perp = pygame.Vector2(-chord.y, chord.x).normalize()
274
-
275
- # Distance of center from midpoint, based on tightness
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
- # Normalize sweep direction based on sign of tightness
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
- points = []
296
- for i in range(segs + 1):
297
- t = i / segs
298
- a = ang0 + sweep * t
299
- points.append((
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.9a11
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
- Welcome to the `batFramework`. This README provides an overview of the game framework.
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
- ## batFramework
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
- The `batFramework` is a Python game development framework based on pygame, designed to streamline the process of creating 2D games. It provides a set of tools and components to handle scenes, transitions, cutscenes, audio, sprites, and more. The framework is built with flexibility in mind, allowing you to focus on game design while abstracting away low-level details.
38
+ ## Installation and Setup
39
+ To install batFramework, you can use pip:
40
+ ```pip install batFramework```
43
41
 
44
- ### Features
42
+ The only dependency required is pygame-ce.
45
43
 
46
- - Scene management
47
- - Cutscene support
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
- ### Explore batFramework
47
+ ```python
48
+ import batFramework as bf
55
49
 
56
- 1. Install Python (version 3.11 or higher) and the latest stable version of pygame-ce.
57
- 2. Clone or download this repository.
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
- For more detailed information on how to use the framework, refer to the documentation (if available) or explore the source code in the `batFramework` directory.
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