feather-engine 26.8.2__tar.gz
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.
- feather_engine-26.8.2/PKG-INFO +52 -0
- feather_engine-26.8.2/README.md +42 -0
- feather_engine-26.8.2/feather.py +399 -0
- feather_engine-26.8.2/feather_engine.egg-info/PKG-INFO +52 -0
- feather_engine-26.8.2/feather_engine.egg-info/SOURCES.txt +8 -0
- feather_engine-26.8.2/feather_engine.egg-info/dependency_links.txt +1 -0
- feather_engine-26.8.2/feather_engine.egg-info/requires.txt +1 -0
- feather_engine-26.8.2/feather_engine.egg-info/top_level.txt +1 -0
- feather_engine-26.8.2/pyproject.toml +16 -0
- feather_engine-26.8.2/setup.cfg +4 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: feather-engine
|
|
3
|
+
Version: 26.8.2
|
|
4
|
+
Summary: A pygame utility module
|
|
5
|
+
Author: TheCodingChihuahua
|
|
6
|
+
License-Expression: GPL-3.0-only
|
|
7
|
+
Requires-Python: >=3.14
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: pygame>=2.5
|
|
10
|
+
|
|
11
|
+
# Feather Engine
|
|
12
|
+
|
|
13
|
+
Feather is a small Pygame utility module for beginner-friendly 2D games.
|
|
14
|
+
|
|
15
|
+
## Example
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import feather
|
|
19
|
+
|
|
20
|
+
player = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def init():
|
|
24
|
+
global player
|
|
25
|
+
player = feather.Sprite("assets/player.png")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def update():
|
|
29
|
+
if feather.key_pressed("ENTER"):
|
|
30
|
+
player.image = "assets/playerdance.png"
|
|
31
|
+
if feather.key_pressed("BACKSPACE"):
|
|
32
|
+
player.image = "assets/playercry.png"
|
|
33
|
+
if feather.key_pressed("ESCAPE"):
|
|
34
|
+
feather.end()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
feather.run(init, update)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`update` runs once per frame at up to 60 frames per second. Image paths are resolved relative to the game's current working directory.
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```powershell
|
|
45
|
+
python -m pip install feather-engine
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then import it in your game with:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import feather
|
|
52
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Feather Engine
|
|
2
|
+
|
|
3
|
+
Feather is a small Pygame utility module for beginner-friendly 2D games.
|
|
4
|
+
|
|
5
|
+
## Example
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
import feather
|
|
9
|
+
|
|
10
|
+
player = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def init():
|
|
14
|
+
global player
|
|
15
|
+
player = feather.Sprite("assets/player.png")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def update():
|
|
19
|
+
if feather.key_pressed("ENTER"):
|
|
20
|
+
player.image = "assets/playerdance.png"
|
|
21
|
+
if feather.key_pressed("BACKSPACE"):
|
|
22
|
+
player.image = "assets/playercry.png"
|
|
23
|
+
if feather.key_pressed("ESCAPE"):
|
|
24
|
+
feather.end()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
feather.run(init, update)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`update` runs once per frame at up to 60 frames per second. Image paths are resolved relative to the game's current working directory.
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
python -m pip install feather-engine
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then import it in your game with:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import feather
|
|
42
|
+
```
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pygame
|
|
3
|
+
|
|
4
|
+
_running = True
|
|
5
|
+
_objects = []
|
|
6
|
+
_background_color = (0, 0, 0)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _normalize_layer(value):
|
|
10
|
+
try:
|
|
11
|
+
return int(value)
|
|
12
|
+
except (TypeError, ValueError):
|
|
13
|
+
return 0
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _sort_objects():
|
|
17
|
+
_objects.sort(key=lambda obj: _normalize_layer(getattr(obj, 'layer', 0)), reverse=True)
|
|
18
|
+
|
|
19
|
+
_keys_down = set()
|
|
20
|
+
_key_aliases = {
|
|
21
|
+
'ENTER': 'RETURN',
|
|
22
|
+
'ESC': 'ESCAPE',
|
|
23
|
+
'CTRL': 'CONTROL',
|
|
24
|
+
'CMD': 'GUI',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
framerate: int = 60
|
|
28
|
+
def setWindowTitle(title): pygame.display.set_caption(title)
|
|
29
|
+
def setWindowSize(width, height): pygame.display.set_mode((width, height), pygame.RESIZABLE)
|
|
30
|
+
def setBackgroundColor(color):
|
|
31
|
+
global _background_color
|
|
32
|
+
if isinstance(color, str):
|
|
33
|
+
color = pygame.Color(color)
|
|
34
|
+
_background_color = color
|
|
35
|
+
surface = pygame.display.get_surface()
|
|
36
|
+
if surface is not None:
|
|
37
|
+
surface.fill(color)
|
|
38
|
+
|
|
39
|
+
def _key_name(key):
|
|
40
|
+
name = str(key).upper()
|
|
41
|
+
return _key_aliases.get(name, name)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def run(_init, _update):
|
|
45
|
+
global _running
|
|
46
|
+
_running = True
|
|
47
|
+
|
|
48
|
+
if not pygame.get_init():
|
|
49
|
+
pygame.init()
|
|
50
|
+
|
|
51
|
+
if pygame.display.get_surface() is None:
|
|
52
|
+
pygame.display.set_mode((800, 600), pygame.RESIZABLE)
|
|
53
|
+
|
|
54
|
+
clock = pygame.time.Clock()
|
|
55
|
+
|
|
56
|
+
if _init is not None:
|
|
57
|
+
_init()
|
|
58
|
+
|
|
59
|
+
while _running:
|
|
60
|
+
for event in pygame.event.get():
|
|
61
|
+
if event.type == pygame.QUIT:
|
|
62
|
+
end()
|
|
63
|
+
elif event.type == pygame.KEYDOWN:
|
|
64
|
+
_keys_down.add(_key_name(pygame.key.name(event.key)))
|
|
65
|
+
elif event.type == pygame.KEYUP:
|
|
66
|
+
_keys_down.discard(_key_name(pygame.key.name(event.key)))
|
|
67
|
+
|
|
68
|
+
screen = pygame.display.get_surface()
|
|
69
|
+
screen.fill(_background_color)
|
|
70
|
+
_update()
|
|
71
|
+
|
|
72
|
+
for obj in _objects:
|
|
73
|
+
if isinstance(obj, Sprite):
|
|
74
|
+
screen.blit(obj.image, obj.rect)
|
|
75
|
+
elif isinstance(obj, Label):
|
|
76
|
+
screen.blit(obj.image, obj.rect)
|
|
77
|
+
elif isinstance(obj, Rectangle):
|
|
78
|
+
pygame.draw.rect(screen, obj.color, obj.rect)
|
|
79
|
+
|
|
80
|
+
pygame.display.flip()
|
|
81
|
+
clock.tick(framerate)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def end():
|
|
85
|
+
global _running
|
|
86
|
+
_running = False
|
|
87
|
+
|
|
88
|
+
def key_pressed(key):
|
|
89
|
+
return _key_name(key) in _keys_down
|
|
90
|
+
|
|
91
|
+
def add_sprite(sprite):
|
|
92
|
+
if sprite not in _objects:
|
|
93
|
+
_objects.append(sprite)
|
|
94
|
+
_sort_objects()
|
|
95
|
+
|
|
96
|
+
def add_rect(rect):
|
|
97
|
+
if rect not in _objects:
|
|
98
|
+
_objects.append(rect)
|
|
99
|
+
_sort_objects()
|
|
100
|
+
|
|
101
|
+
def add_label(label):
|
|
102
|
+
if label not in _objects:
|
|
103
|
+
_objects.append(label)
|
|
104
|
+
_sort_objects()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class Sprite:
|
|
108
|
+
def __init__(self, image_path, x=0, y=0, width=None, height=None, layer=0, flip_x=False, flip_y=False):
|
|
109
|
+
file_extension = os.path.splitext(image_path)[1].lower().lstrip('.')
|
|
110
|
+
|
|
111
|
+
if file_extension in {'png', 'svg'}:
|
|
112
|
+
self.image = pygame.image.load(image_path).convert_alpha()
|
|
113
|
+
elif file_extension in {'jpg', 'jpeg'}:
|
|
114
|
+
self.image = pygame.image.load(image_path).convert()
|
|
115
|
+
else:
|
|
116
|
+
raise ValueError("Unsupported image format: {}".format(file_extension))
|
|
117
|
+
|
|
118
|
+
self.rect = self.image.get_rect(topleft=(x, y))
|
|
119
|
+
|
|
120
|
+
if width is not None or height is not None:
|
|
121
|
+
target_width = self.rect.width if width is None else width
|
|
122
|
+
target_height = self.rect.height if height is None else height
|
|
123
|
+
self._resize(target_width, target_height)
|
|
124
|
+
|
|
125
|
+
self._layer = _normalize_layer(layer)
|
|
126
|
+
self._flip_x = False
|
|
127
|
+
self._flip_y = False
|
|
128
|
+
self.flip_x = flip_x
|
|
129
|
+
self.flip_y = flip_y
|
|
130
|
+
add_sprite(self)
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def x(self):
|
|
134
|
+
return self.rect.x
|
|
135
|
+
|
|
136
|
+
@x.setter
|
|
137
|
+
def x(self, value):
|
|
138
|
+
self.rect.x = value
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def y(self):
|
|
142
|
+
return self.rect.y
|
|
143
|
+
|
|
144
|
+
@y.setter
|
|
145
|
+
def y(self, value):
|
|
146
|
+
self.rect.y = value
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def width(self):
|
|
150
|
+
return self.rect.width
|
|
151
|
+
|
|
152
|
+
@width.setter
|
|
153
|
+
def width(self, value):
|
|
154
|
+
self._resize(value, self.height)
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def height(self):
|
|
158
|
+
return self.rect.height
|
|
159
|
+
|
|
160
|
+
@height.setter
|
|
161
|
+
def height(self, value):
|
|
162
|
+
self._resize(self.width, value)
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def layer(self):
|
|
166
|
+
return self._layer
|
|
167
|
+
|
|
168
|
+
@layer.setter
|
|
169
|
+
def layer(self, value):
|
|
170
|
+
self._layer = _normalize_layer(value)
|
|
171
|
+
_sort_objects()
|
|
172
|
+
|
|
173
|
+
def _resize(self, width, height):
|
|
174
|
+
width = max(1, min(int(width), 8192))
|
|
175
|
+
height = max(1, min(int(height), 8192))
|
|
176
|
+
position = self.rect.topleft
|
|
177
|
+
self.image = pygame.transform.scale(self.image, (width, height))
|
|
178
|
+
self.rect = self.image.get_rect(topleft=position)
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def flip_x(self):
|
|
182
|
+
return self._flip_x
|
|
183
|
+
|
|
184
|
+
@flip_x.setter
|
|
185
|
+
def flip_x(self, value):
|
|
186
|
+
value = bool(value)
|
|
187
|
+
if value != self._flip_x:
|
|
188
|
+
self.image = pygame.transform.flip(self.image, True, False)
|
|
189
|
+
self._flip_x = value
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def flip_y(self):
|
|
193
|
+
return self._flip_y
|
|
194
|
+
|
|
195
|
+
@flip_y.setter
|
|
196
|
+
def flip_y(self, value):
|
|
197
|
+
value = bool(value)
|
|
198
|
+
if value != self._flip_y:
|
|
199
|
+
self.image = pygame.transform.flip(self.image, False, True)
|
|
200
|
+
self._flip_y = value
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def image(self):
|
|
204
|
+
return self._image
|
|
205
|
+
|
|
206
|
+
@image.setter
|
|
207
|
+
def image(self, value):
|
|
208
|
+
preserve_size = isinstance(value, str) and hasattr(self, 'rect')
|
|
209
|
+
position = self.rect.topleft if hasattr(self, 'rect') else (0, 0)
|
|
210
|
+
|
|
211
|
+
if isinstance(value, str):
|
|
212
|
+
file_extension = os.path.splitext(value)[1].lower().lstrip('.')
|
|
213
|
+
|
|
214
|
+
if file_extension in {'png', 'svg'}:
|
|
215
|
+
loaded_image = pygame.image.load(value).convert_alpha()
|
|
216
|
+
elif file_extension in {'jpg', 'jpeg'}:
|
|
217
|
+
loaded_image = pygame.image.load(value).convert()
|
|
218
|
+
else:
|
|
219
|
+
raise ValueError("Unsupported image format: {}".format(file_extension))
|
|
220
|
+
elif isinstance(value, pygame.Surface):
|
|
221
|
+
loaded_image = value
|
|
222
|
+
else:
|
|
223
|
+
raise ValueError("Unsupported image type: {}".format(type(value)))
|
|
224
|
+
|
|
225
|
+
if preserve_size:
|
|
226
|
+
loaded_image = pygame.transform.scale(loaded_image, self.rect.size)
|
|
227
|
+
loaded_image = pygame.transform.flip(
|
|
228
|
+
loaded_image,
|
|
229
|
+
getattr(self, '_flip_x', False),
|
|
230
|
+
getattr(self, '_flip_y', False),
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
self._image = loaded_image
|
|
234
|
+
self.rect = self.image.get_rect(topleft=position)
|
|
235
|
+
|
|
236
|
+
class Label:
|
|
237
|
+
def __init__(self, text='', x=0, y=0, layer=0, size=36, color=('black'), font_name=None, rounded=True):
|
|
238
|
+
self._x = x
|
|
239
|
+
self._y = y
|
|
240
|
+
self._text = str(text)
|
|
241
|
+
self._layer = _normalize_layer(layer)
|
|
242
|
+
self._size = size
|
|
243
|
+
self._color = color
|
|
244
|
+
self._font_name = font_name
|
|
245
|
+
self._rounded = rounded
|
|
246
|
+
self.font = pygame.font.Font(self._font_name, self._size)
|
|
247
|
+
self._render()
|
|
248
|
+
add_label(self)
|
|
249
|
+
|
|
250
|
+
def _render(self):
|
|
251
|
+
self.image = self.font.render(self._text, self._rounded, self._color)
|
|
252
|
+
self.rect = self.image.get_rect(topleft=(self._x, self._y))
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def x(self):
|
|
256
|
+
return self._x
|
|
257
|
+
|
|
258
|
+
@x.setter
|
|
259
|
+
def x(self, value):
|
|
260
|
+
self._x = value
|
|
261
|
+
if hasattr(self, 'rect'):
|
|
262
|
+
self.rect.x = value
|
|
263
|
+
|
|
264
|
+
@property
|
|
265
|
+
def y(self):
|
|
266
|
+
return self._y
|
|
267
|
+
|
|
268
|
+
@y.setter
|
|
269
|
+
def y(self, value):
|
|
270
|
+
self._y = value
|
|
271
|
+
if hasattr(self, 'rect'):
|
|
272
|
+
self.rect.y = value
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def layer(self):
|
|
276
|
+
return self._layer
|
|
277
|
+
|
|
278
|
+
@layer.setter
|
|
279
|
+
def layer(self, value):
|
|
280
|
+
self._layer = _normalize_layer(value)
|
|
281
|
+
_sort_objects()
|
|
282
|
+
|
|
283
|
+
@property
|
|
284
|
+
def text(self):
|
|
285
|
+
return self._text
|
|
286
|
+
|
|
287
|
+
@text.setter
|
|
288
|
+
def text(self, value):
|
|
289
|
+
self._text = str(value)
|
|
290
|
+
self._render()
|
|
291
|
+
|
|
292
|
+
@property
|
|
293
|
+
def size(self):
|
|
294
|
+
return self._size
|
|
295
|
+
|
|
296
|
+
@size.setter
|
|
297
|
+
def size(self, value):
|
|
298
|
+
self._size = value
|
|
299
|
+
self.font = pygame.font.Font(self._font_name, self._size)
|
|
300
|
+
self._render()
|
|
301
|
+
|
|
302
|
+
@property
|
|
303
|
+
def color(self):
|
|
304
|
+
return self._color
|
|
305
|
+
|
|
306
|
+
@color.setter
|
|
307
|
+
def color(self, value):
|
|
308
|
+
self._color = value
|
|
309
|
+
self._render()
|
|
310
|
+
|
|
311
|
+
@property
|
|
312
|
+
def font_name(self):
|
|
313
|
+
return self._font_name
|
|
314
|
+
|
|
315
|
+
@font_name.setter
|
|
316
|
+
def font_name(self, value):
|
|
317
|
+
self._font_name = value
|
|
318
|
+
self.font = pygame.font.Font(self._font_name, self._size)
|
|
319
|
+
self._render()
|
|
320
|
+
|
|
321
|
+
@property
|
|
322
|
+
def rounded(self):
|
|
323
|
+
return self._rounded
|
|
324
|
+
|
|
325
|
+
@rounded.setter
|
|
326
|
+
def rounded(self, value):
|
|
327
|
+
self._rounded = value
|
|
328
|
+
self._render()
|
|
329
|
+
|
|
330
|
+
class Rectangle:
|
|
331
|
+
def __init__(self, x=0, y=0, width=30, height=30, color=(255, 255, 255), layer=0):
|
|
332
|
+
self._x = x
|
|
333
|
+
self._y = y
|
|
334
|
+
self._width = width
|
|
335
|
+
self._height = height
|
|
336
|
+
self.rect = pygame.Rect(x, y, width, height)
|
|
337
|
+
self.color = color
|
|
338
|
+
self._layer = _normalize_layer(layer)
|
|
339
|
+
add_rect(self)
|
|
340
|
+
|
|
341
|
+
@property
|
|
342
|
+
def x(self):
|
|
343
|
+
return self._x
|
|
344
|
+
|
|
345
|
+
@x.setter
|
|
346
|
+
def x(self, value):
|
|
347
|
+
self._x = value
|
|
348
|
+
if hasattr(self, 'rect'):
|
|
349
|
+
self.rect.x = value
|
|
350
|
+
|
|
351
|
+
@property
|
|
352
|
+
def y(self):
|
|
353
|
+
return self._y
|
|
354
|
+
|
|
355
|
+
@y.setter
|
|
356
|
+
def y(self, value):
|
|
357
|
+
self._y = value
|
|
358
|
+
if hasattr(self, 'rect'):
|
|
359
|
+
self.rect.y = value
|
|
360
|
+
|
|
361
|
+
@property
|
|
362
|
+
def width(self):
|
|
363
|
+
return self._width
|
|
364
|
+
|
|
365
|
+
@width.setter
|
|
366
|
+
def width(self, value):
|
|
367
|
+
self._width = value
|
|
368
|
+
if hasattr(self, 'rect'):
|
|
369
|
+
self.rect.width = value
|
|
370
|
+
|
|
371
|
+
@property
|
|
372
|
+
def height(self):
|
|
373
|
+
return self._height
|
|
374
|
+
|
|
375
|
+
@height.setter
|
|
376
|
+
def height(self, value):
|
|
377
|
+
self._height = value
|
|
378
|
+
if hasattr(self, 'rect'):
|
|
379
|
+
self.rect.height = value
|
|
380
|
+
|
|
381
|
+
@property
|
|
382
|
+
def color(self):
|
|
383
|
+
return self._color
|
|
384
|
+
|
|
385
|
+
@color.setter
|
|
386
|
+
def color(self, value):
|
|
387
|
+
self._color = value
|
|
388
|
+
|
|
389
|
+
@property
|
|
390
|
+
def layer(self):
|
|
391
|
+
return self._layer
|
|
392
|
+
|
|
393
|
+
@layer.setter
|
|
394
|
+
def layer(self, value):
|
|
395
|
+
try:
|
|
396
|
+
self._layer = int(value)
|
|
397
|
+
except (TypeError, ValueError):
|
|
398
|
+
self._layer = 0
|
|
399
|
+
_sort_objects()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: feather-engine
|
|
3
|
+
Version: 26.8.2
|
|
4
|
+
Summary: A pygame utility module
|
|
5
|
+
Author: TheCodingChihuahua
|
|
6
|
+
License-Expression: GPL-3.0-only
|
|
7
|
+
Requires-Python: >=3.14
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: pygame>=2.5
|
|
10
|
+
|
|
11
|
+
# Feather Engine
|
|
12
|
+
|
|
13
|
+
Feather is a small Pygame utility module for beginner-friendly 2D games.
|
|
14
|
+
|
|
15
|
+
## Example
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import feather
|
|
19
|
+
|
|
20
|
+
player = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def init():
|
|
24
|
+
global player
|
|
25
|
+
player = feather.Sprite("assets/player.png")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def update():
|
|
29
|
+
if feather.key_pressed("ENTER"):
|
|
30
|
+
player.image = "assets/playerdance.png"
|
|
31
|
+
if feather.key_pressed("BACKSPACE"):
|
|
32
|
+
player.image = "assets/playercry.png"
|
|
33
|
+
if feather.key_pressed("ESCAPE"):
|
|
34
|
+
feather.end()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
feather.run(init, update)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`update` runs once per frame at up to 60 frames per second. Image paths are resolved relative to the game's current working directory.
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```powershell
|
|
45
|
+
python -m pip install feather-engine
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then import it in your game with:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import feather
|
|
52
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pygame>=2.5
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
feather
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "feather-engine"
|
|
7
|
+
version = "26.8.2"
|
|
8
|
+
description = "A pygame utility module"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.14"
|
|
11
|
+
authors = [{ name = "TheCodingChihuahua" }]
|
|
12
|
+
license = "GPL-3.0-only"
|
|
13
|
+
dependencies = ["pygame>=2.5"]
|
|
14
|
+
|
|
15
|
+
[tool.setuptools]
|
|
16
|
+
py-modules = ["feather"]
|