batframework 1.0.8a7__py3-none-any.whl → 1.0.8a8__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 (70) hide show
  1. batFramework/__init__.py +51 -68
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +82 -141
  5. batFramework/audioManager.py +26 -69
  6. batFramework/camera.py +69 -259
  7. batFramework/constants.py +54 -16
  8. batFramework/cutscene.py +29 -39
  9. batFramework/cutsceneBlocks.py +43 -36
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -18
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +97 -48
  14. batFramework/gui/__init__.py +2 -10
  15. batFramework/gui/button.py +78 -9
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +32 -174
  18. batFramework/gui/debugger.py +43 -131
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -56
  21. batFramework/gui/indicator.py +21 -38
  22. batFramework/gui/interactiveWidget.py +13 -192
  23. batFramework/gui/label.py +74 -309
  24. batFramework/gui/layout.py +63 -231
  25. batFramework/gui/root.py +38 -134
  26. batFramework/gui/shape.py +57 -237
  27. batFramework/gui/toggle.py +51 -101
  28. batFramework/gui/widget.py +250 -358
  29. batFramework/manager.py +19 -52
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +123 -281
  32. batFramework/sceneManager.py +116 -178
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +58 -145
  35. batFramework/transition.py +124 -195
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +1 -1
  38. batFramework/utils.py +147 -112
  39. batframework-1.0.8a8.dist-info/METADATA +53 -0
  40. batframework-1.0.8a8.dist-info/RECORD +42 -0
  41. {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/WHEEL +1 -1
  42. batFramework/character.py +0 -27
  43. batFramework/easingController.py +0 -58
  44. batFramework/enums.py +0 -113
  45. batFramework/fontManager.py +0 -65
  46. batFramework/gui/clickableWidget.py +0 -220
  47. batFramework/gui/constraints/__init__.py +0 -1
  48. batFramework/gui/constraints/constraints.py +0 -815
  49. batFramework/gui/dialogueBox.py +0 -99
  50. batFramework/gui/draggableWidget.py +0 -40
  51. batFramework/gui/meter.py +0 -74
  52. batFramework/gui/radioButton.py +0 -84
  53. batFramework/gui/slider.py +0 -240
  54. batFramework/gui/style.py +0 -10
  55. batFramework/gui/styleManager.py +0 -48
  56. batFramework/gui/textInput.py +0 -247
  57. batFramework/object.py +0 -123
  58. batFramework/particle.py +0 -115
  59. batFramework/renderGroup.py +0 -67
  60. batFramework/resourceManager.py +0 -100
  61. batFramework/scrollingSprite.py +0 -114
  62. batFramework/sprite.py +0 -51
  63. batFramework/templates/__init__.py +0 -2
  64. batFramework/templates/character.py +0 -44
  65. batFramework/templates/states.py +0 -166
  66. batFramework/tileset.py +0 -46
  67. batframework-1.0.8a7.dist-info/LICENCE +0 -21
  68. batframework-1.0.8a7.dist-info/METADATA +0 -43
  69. batframework-1.0.8a7.dist-info/RECORD +0 -62
  70. {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/top_level.txt +0 -0
@@ -1,247 +0,0 @@
1
- import batFramework as bf
2
- from typing import Self, Callable
3
- from .label import Label
4
- from .interactiveWidget import InteractiveWidget
5
- import pygame
6
-
7
- def find_next_word(s: str, start_index: int) -> int:
8
- length = len(s)
9
- # Ensure the starting index is within the bounds of the string
10
- if start_index < 0 or start_index >= length:
11
- raise ValueError("Starting index is out of bounds")
12
- index = start_index
13
- # If the start_index is at a space, skip leading spaces
14
- if s[index] in [' ','\n']:
15
- while index < length and s[index] in [' ','\n']:
16
- index += 1
17
- # If we've reached the end of the string
18
- if index >= length:
19
- return -1
20
- else:
21
- # If the start_index is within a word, move to the end of that word
22
- while index < length and s[index] not in [' ','\n']:
23
- index += 1
24
- if index == length:
25
- return index
26
- # Return the index of the start of the next word or -1 if no more words are found
27
- return index if index < length else -1
28
-
29
- def find_prev_word(s: str, start_index: int) -> int:
30
- if start_index <= 0 : return 0
31
- length = len(s)
32
-
33
- # Ensure the starting index is within the bounds of the string
34
- if start_index < 0 or start_index >= length:
35
- raise ValueError("Starting index is out of bounds")
36
-
37
- index = start_index
38
-
39
- # If the start_index is at a space, skip trailing spaces
40
- if s[index] in [' ', '\n']:
41
- while index > 0 and s[index-1] in [' ', '\n']:
42
- index -= 1
43
- # If we've reached the beginning of the string
44
- if index <= 0:
45
- return 0 if s[0] not in [' ', '\n'] else -1
46
- else:
47
- # If the start_index is within a word, move to the start of that word
48
- while index > 0 and s[index-1] not in [' ', '\n']:
49
- index -= 1
50
- if index == 0 and s[index] not in [' ', '\n']:
51
- return 0
52
-
53
- # Return the index of the start of the previous word or -1 if no more words are found
54
- return index if index > 0 or (index == 0 and s[0] not in [' ', '\n']) else -1
55
-
56
-
57
- class TextInput(Label, InteractiveWidget):
58
- def __init__(self) -> None:
59
- self.cursor_position = (0, 0)
60
- self.old_key_repeat = (0, 0)
61
- self.cursor_timer = bf.Timer(0.3, self._cursor_toggle, loop=True).start()
62
- self.cursor_timer.pause()
63
- self.show_cursor = False
64
- self.on_modify: Callable[[str], str] = None
65
- self.set_focusable(True)
66
- self.set_outline_color("black")
67
- super().__init__("")
68
- self.alignment = bf.alignment.TOPLEFT
69
-
70
- def set_modify_callback(self, callback: Callable[[str], str]) -> Self:
71
- self.on_modify = callback
72
- return self
73
-
74
- def __str__(self) -> str:
75
- return f"TextInput({repr(self.text)})"
76
-
77
- def _cursor_toggle(self, value: bool | None = None):
78
- if value is None:
79
- value = not self.show_cursor
80
- self.show_cursor = value
81
- self.dirty_surface = True
82
-
83
- def do_on_click_down(self, button):
84
- if button != 1:
85
- return
86
- self.get_focus()
87
-
88
- def do_on_enter(self):
89
- pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_IBEAM)
90
-
91
- def do_on_exit(self):
92
- pygame.mouse.set_cursor(bf.const.DEFAULT_CURSOR)
93
-
94
- def do_on_get_focus(self):
95
- self.cursor_timer.resume()
96
- self._cursor_toggle(True)
97
- self.old_key_repeat = pygame.key.get_repeat()
98
- pygame.key.set_repeat(200, 50)
99
-
100
- def do_on_lose_focus(self):
101
- self.cursor_timer.pause()
102
- self._cursor_toggle(False)
103
- pygame.key.set_repeat(*self.old_key_repeat)
104
-
105
- def get_line(self, line: int) -> str | None:
106
- if line < 0:
107
- return None
108
- lines = self.text.split('\n')
109
- if line >= len(lines):
110
- return None
111
- return lines[line]
112
-
113
- def set_cursor_position(self, position: tuple[int, int]) -> Self:
114
- x, y = position
115
-
116
- lines = self.text.split('\n')
117
- y = max(0, min(y, len(lines) - 1))
118
- line_length = len(lines[y])
119
- x = max(0, min(x, line_length))
120
-
121
- self.cursor_position = (x, y)
122
- self.show_cursor = True
123
- self.dirty_shape = True
124
- return self
125
-
126
- def cursor_to_absolute(self, position: tuple[int, int]) -> int:
127
- x, y = position
128
-
129
- y = max(0, min(y, len(self.text.split('\n')) - 1))
130
- lines = self.text.split('\n')
131
- x = max(0, min(x, len(lines[y])))
132
-
133
- absolute_position = sum(len(line) + 1 for line in lines[:y]) + x
134
- return absolute_position
135
-
136
- def absolute_to_cursor(self, absolute: int) -> tuple[int, int]:
137
- text = self.text
138
- lines = text.split('\n')
139
- current_pos = 0
140
-
141
- for line_no, line in enumerate(lines):
142
- if absolute <= current_pos + len(line):
143
- return (absolute - current_pos, line_no)
144
- current_pos += len(line) + 1
145
-
146
- return (len(lines[-1]), len(lines) - 1)
147
-
148
- def do_handle_event(self, event):
149
- if not self.is_focused:
150
- return
151
-
152
- if event.type not in [pygame.TEXTINPUT, pygame.KEYDOWN]:
153
- return
154
-
155
- text = self.get_text()
156
- current = self.cursor_to_absolute(self.cursor_position)
157
- if event.type == pygame.TEXTINPUT:
158
- self.set_text(text[:current] + event.text + text[current:])
159
- self.set_cursor_position(self.absolute_to_cursor(current + len(event.text)))
160
- elif event.type == pygame.KEYDOWN:
161
- pressed = pygame.key.get_pressed()
162
- if event.key == pygame.K_ESCAPE:
163
- self.lose_focus()
164
- elif event.key == pygame.K_BACKSPACE:
165
- if current > 0:
166
- self.set_text(text[:current - 1] + text[current:])
167
- self.set_cursor_position(self.absolute_to_cursor(current - 1))
168
- elif event.key == pygame.K_DELETE:
169
- if current < len(text):
170
- self.set_text(text[:current] + text[current + 1:])
171
- elif event.key == pygame.K_RIGHT:
172
- if self.cursor_to_absolute(self.cursor_position)>=len(self.text):
173
- return
174
- if self.cursor_position[0] == len(self.get_line(self.cursor_position[1])):
175
- self.set_cursor_position((0, self.cursor_position[1] + 1))
176
- else:
177
- if pressed[pygame.K_LCTRL] or pressed[pygame.K_RCTRL]:
178
- index = find_next_word(self.text,current)
179
- if index ==-1 : index = current+1
180
- self.set_cursor_position(self.absolute_to_cursor(index))
181
- else:
182
- self.set_cursor_position(self.absolute_to_cursor(current + 1))
183
- elif event.key == pygame.K_LEFT:
184
-
185
-
186
- if self.cursor_position[0] == 0 and self.cursor_position[1] > 0:
187
- self.set_cursor_position((len(self.get_line(self.cursor_position[1] - 1)), self.cursor_position[1] - 1))
188
- else:
189
- if pressed[pygame.K_LCTRL] or pressed[pygame.K_RCTRL]:
190
- index = find_prev_word(self.text,current-1)
191
- if index ==-1 : index = current-1
192
- self.set_cursor_position(self.absolute_to_cursor(index))
193
- else:
194
- self.set_cursor_position(self.absolute_to_cursor(current - 1))
195
- elif event.key == pygame.K_UP:
196
- x, y = self.cursor_position
197
- self.set_cursor_position((x, y - 1))
198
- elif event.key == pygame.K_DOWN:
199
- x, y = self.cursor_position
200
- self.set_cursor_position((x, y + 1))
201
- elif event.key == pygame.K_RETURN:
202
- self.set_text(text[:current] + '\n' + text[current:])
203
- self.set_cursor_position(self.absolute_to_cursor(current + 1))
204
- else:
205
- return
206
- else:
207
- return
208
-
209
- event.consumed = True
210
-
211
- def set_text(self, text: str) -> Self:
212
- if self.on_modify:
213
- text = self.on_modify(text)
214
- return super().set_text(text)
215
-
216
- def _paint_cursor(self) -> None:
217
- if not self.font_object or not self.show_cursor:
218
- return
219
-
220
- lines = self.text.split('\n')
221
- line_x, line_y = self.cursor_position
222
-
223
- cursor_y = self.padding[1]
224
- cursor_y += line_y * self.font_object.get_linesize()
225
- cursor_x = self.padding[0]
226
- cursor_x += self.font_object.size(lines[line_y][:line_x])[0] if line_x > 0 else 0
227
-
228
- cursor_rect = pygame.Rect(cursor_x, cursor_y, 2, self.font_object.get_height())
229
- pygame.draw.rect(self.surface, self.text_color, cursor_rect)
230
-
231
- def paint(self) -> None:
232
- super().paint()
233
- self._paint_cursor()
234
-
235
- # def set_alignment(self, alignment: bf.alignment) -> Self:
236
- # return self
237
-
238
- # def align_text(
239
- # self, text_rect: pygame.FRect, area: pygame.FRect, alignment: bf.alignment
240
- # ):
241
- # if alignment == bf.alignment.LEFT:
242
- # alignment = bf.alignment.MIDLEFT
243
- # elif alignment == bf.alignment.MIDRIGHT:
244
- # alignment = bf.alignment.MIDRIGHT
245
- # pos = area.__getattribute__(alignment.value)
246
- # text_rect.__setattr__(alignment.value, pos)
247
- # return
batFramework/object.py DELETED
@@ -1,123 +0,0 @@
1
- from typing import Any, Self
2
- import pygame
3
- import batFramework as bf
4
- from typing import TYPE_CHECKING
5
-
6
- if TYPE_CHECKING:
7
- from .camera import Camera
8
-
9
-
10
- class Object:
11
- __count = 0
12
- __available_uid = set()
13
- __used_uid = set()
14
-
15
- def __init__(self) -> None:
16
- self.rect = pygame.FRect(0, 0, 0, 0)
17
- self.tags: list[str] = []
18
- self.parent_scene: bf.Scene | None = None
19
- self.debug_color: tuple | str = "red"
20
- self.render_order: int = 0
21
- self.uid: int = Object.__count
22
- Object.__used_uid.add(self.uid)
23
-
24
- if Object.__available_uid:
25
- self.name = Object.__available_uid.pop()
26
- else:
27
- self.name = Object.__count
28
- Object.__count += 1
29
-
30
- def __del__(self):
31
- Object.__available_uid.add(self.uid)
32
-
33
- def set_position(self, x, y) -> Self:
34
- self.rect.topleft = x, y
35
- return self
36
-
37
- def set_center(self, x, y) -> Self:
38
- self.rect.center = x, y
39
- return self
40
-
41
- def get_debug_outlines(self):
42
- yield (self.rect, self.debug_color)
43
-
44
- def set_debug_color(self, color) -> Self:
45
- self.debug_color = color
46
- return self
47
-
48
- def set_parent_scene(self, scene) -> Self:
49
- if scene == self.parent_scene:
50
- return self
51
- if self.parent_scene is not None:
52
- self.do_when_removed()
53
- self.parent_scene = scene
54
- if scene is not None:
55
- self.do_when_added()
56
- return self
57
-
58
- def do_when_added(self):
59
- pass
60
-
61
- def do_when_removed(self):
62
- pass
63
-
64
- def set_uid(self, uid: int) -> Self:
65
- if uid in Object.__used_uid:
66
- print(f"set_uid error : UID '{uid}' is already in use")
67
- return self
68
- self.uid = uid
69
- Object.__used_uid.add(uid)
70
- return self
71
-
72
- def add_tags(self, *tags) -> Self:
73
- for tag in tags:
74
- if tag not in self.tags:
75
- self.tags.append(tag)
76
- self.tags.sort()
77
- return self
78
-
79
- def remove_tags(self, *tags):
80
- self.tags = [tag for tag in self.tags if tag not in tags]
81
-
82
- def has_tags(self, *tags) -> bool:
83
- return all(tag in self.tags for tag in tags)
84
-
85
- def get_tags(self) -> list[str]:
86
- return self.tags
87
-
88
- def process_event(self, event: pygame.Event) -> bool:
89
- """
90
- Returns bool : True if the method is blocking (no propagation to next object of the scene)
91
- """
92
- if event.consumed:
93
- return
94
- self.do_process_actions(event)
95
- self.do_handle_event(event)
96
-
97
- def do_process_actions(self, event: pygame.Event) -> None:
98
- """
99
- Process entity actions you may have set
100
- """
101
-
102
- def do_reset_actions(self) -> None:
103
- """
104
- Reset entity actions you may have set
105
- """
106
-
107
- def do_handle_event(self, event: pygame.Event):
108
- """
109
- Handle specific events with no action support
110
- """
111
- return False
112
-
113
- def update(self, dt: float) -> None:
114
- """
115
- Update method to be overriden by subclasses of object (must call do_update and do_reset_actions)
116
- """
117
- self.do_update(dt)
118
- self.do_reset_actions()
119
-
120
- def do_update(self, dt: float) -> None:
121
- """
122
- Update method to be overriden for specific behavior by the end user
123
- """
batFramework/particle.py DELETED
@@ -1,115 +0,0 @@
1
- import batFramework as bf
2
- import pygame
3
- from pygame.math import Vector2
4
-
5
-
6
- class Particle:
7
- def __init__(self, *args, **kwargs):
8
- self.dead = False
9
- self.surface = None
10
- self.generator = None
11
-
12
- def do_when_added(self):
13
- pass
14
-
15
- def update(self, dt):
16
- pass
17
-
18
- def kill(self):
19
- self.dead = True
20
-
21
- def update_surface(self):
22
- pass
23
-
24
-
25
- class TimedParticle(Particle):
26
- def __init__(self, duration):
27
- super().__init__()
28
- self.duration = duration
29
-
30
- def do_when_added(self):
31
- if self.generator and self.generator.parent_scene:
32
- self.timer = bf.SceneTimer(
33
- self.duration, end_callback=self.kill,
34
- scene_name=self.generator.parent_scene.name).start()
35
- else:
36
- self.timer = bf.Timer(self.duration, end_callback=self.kill).start()
37
-
38
-
39
- class BasicParticle(TimedParticle):
40
- def __init__(
41
- self,
42
- start_pos: tuple[float, float],
43
- start_vel: tuple[float, float],
44
- duration=1,
45
- color=None,
46
- size: tuple[int, int] = (4, 4),
47
- *args,
48
- **kwargs,
49
- ):
50
- super().__init__(duration)
51
- self.rect = pygame.FRect(0,0, *size)
52
- self.rect.center = start_pos
53
- self.surface = pygame.Surface(size)
54
- self.velocity = Vector2(start_vel)
55
- if color:
56
- self.surface.fill(color)
57
- self.start()
58
-
59
- def start(self):
60
- pass
61
-
62
- def update(self, dt):
63
- super().update(dt)
64
- self.rect.center += self.velocity * dt
65
- self.update_surface()
66
-
67
- def update_surface(self):
68
- self.surface.set_alpha(255 - int(self.timer.get_progression() * 255))
69
-
70
-
71
- class DirectionalParticle(BasicParticle):
72
- def start(self):
73
- self.original_surface = self.surface.copy()
74
-
75
- def update_surface(self):
76
- angle = self.velocity.angle_to(Vector2(1, 0))
77
- self.surface = pygame.transform.rotate(self.original_surface, angle)
78
- super().update_surface()
79
-
80
-
81
- class ParticleGenerator(bf.Entity):
82
- def __init__(self) -> None:
83
- super().__init__((0, 0))
84
- self.particles: list[Particle] = []
85
-
86
- def get_debug_outlines(self):
87
- return
88
- for particle in self.particles:
89
- yield (
90
- particle.rect.move(particle.rect.w // 2, particle.rect.h // 2),
91
- "blue",
92
- )
93
- yield (self.rect, "cyan")
94
-
95
- def add_particle(self, particle:Particle):
96
- particle.generator = self
97
- particle.do_when_added()
98
- self.particles.append(particle)
99
-
100
- def clear(self):
101
- self.particles = []
102
-
103
- def update(self, dt: float):
104
- particles_to_remove = []
105
- for particle in self.particles:
106
- particle.update(dt)
107
- if particle.dead:
108
- particles_to_remove.append(particle)
109
- for p in particles_to_remove:
110
- self.particles.remove(p)
111
-
112
- def draw(self, camera) -> None:
113
- camera.surface.fblits(
114
- [(p.surface, camera.world_to_screen(p.rect)) for p in self.particles]
115
- )
@@ -1,67 +0,0 @@
1
- import batFramework as bf
2
- import pygame
3
- from typing import Self, Iterator, Callable
4
-
5
- """
6
- + same render order
7
- + fblits
8
- """
9
-
10
-
11
- class RenderGroup(bf.Entity):
12
- def __init__(
13
- self, entity_iterator: Callable[[], Iterator[bf.Entity]], blit_flags: int = 0
14
- ) -> None:
15
- super().__init__()
16
- self.entity_iterator = entity_iterator
17
- self.set_blit_flags(blit_flags)
18
- self.set_debug_color("white")
19
-
20
- def get_debug_outlines(self):
21
- # yield (self.rect, self.debug_color)
22
- for e in self.entity_iterator():
23
- yield from e.get_debug_outlines()
24
-
25
- def set_parent_scene(self, scene) -> Self:
26
- self.parent_scene = scene
27
- for e in self.entity_iterator():
28
- e.set_parent_scene(scene)
29
- return self
30
-
31
- def process_event(self, event: pygame.Event) -> bool:
32
- """
33
- Returns bool : True if the method is blocking (no propagation to next children of the scene)
34
- """
35
- self.do_process_actions(event)
36
- res = self.do_handle_event(event)
37
- if res:
38
- return res
39
- for e in self.entity_iterator():
40
- if e.process_event(event):
41
- return True
42
- return False
43
-
44
- def update(self, dt: float) -> None:
45
- """
46
- Update method to be overriden by subclasses of entity
47
- """
48
- for e in self.entity_iterator():
49
- e.update(dt)
50
- # gen = self.entity_iterator()
51
- # self.rect = next(gen).rect.unionall([e.rect for e in gen])
52
-
53
- self.do_update(dt)
54
- self.do_reset_actions()
55
-
56
- def draw(self, camera: bf.Camera) -> None:
57
- """
58
- Draw the entity onto the camera with coordinate transposing
59
- """
60
- if not self.visible:
61
- return
62
- fblits_data = (
63
- (e.surface, (e.rect.x - camera.rect.x, e.rect.y - camera.rect.y))
64
- for e in self.entity_iterator()
65
- if camera.rect.colliderect(e.rect)
66
- )
67
- camera.surface.fblits(fblits_data, self.blit_flags)
@@ -1,100 +0,0 @@
1
- import batFramework as bf
2
- import os
3
- import pygame
4
- import sys
5
- import json
6
- from typing import Any
7
- from .utils import Singleton
8
-
9
- if getattr(sys, "frozen", False):
10
- # If the application is run as a bundle, the PyInstaller bootloader
11
- # extends the sys module by a flag frozen=True and sets the app
12
- # path into variable _MEIPASS'.
13
- application_path = sys._MEIPASS
14
- else:
15
- application_path = os.getcwd()
16
-
17
-
18
- class ResourceManager(metaclass=Singleton):
19
- def __init__(self):
20
- self.shared_variables: dict[str,Any] = {}
21
- self.convert_image_cache = {}
22
- self.convert_alpha_image_cache = {}
23
- self.sound_cache = {}
24
- self.RESOURCE_PATH = "."
25
-
26
- def load_dir(self, path) -> None:
27
- for root, dirs, files in os.walk(path):
28
- files = [f for f in files if not f[0] == "."]
29
- dirs[:] = [d for d in dirs if not d[0] == "."]
30
-
31
- for file in files:
32
- file_path = os.path.join(root, file)
33
- if file.lower().endswith((".png", ".jpg", ".jpeg", ".gif")):
34
- self.load_image(file_path)
35
- # print(f"Loaded image : '{file_path}'")
36
-
37
- elif file.lower().endswith((".mp3", ".wav")):
38
- bf.AudioManager().load_sound(file.split(".")[0], file_path)
39
- # print(f"Loaded sound : '{file_path}'")
40
-
41
- elif file.lower().endswith((".ttf", ".otf")):
42
- bf.FontManager().load_font(file_path, file.split(".")[0])
43
- # print(f"Loaded font : '{file_path}'")
44
-
45
- print(f"Loaded resources in directory : '{path}'")
46
-
47
- def set_resource_path(self, path: str):
48
- self.RESOURCE_PATH = os.path.join(application_path, path)
49
- print(f"Resource path : '{self.RESOURCE_PATH}'")
50
-
51
- def get_path(self, path: str) -> str:
52
- # Normalize path separators
53
- normalized_path = path.replace("/", os.sep).replace("\\", os.sep)
54
- return os.path.join(self.RESOURCE_PATH, normalized_path)
55
-
56
- def load_image(self, path) -> None:
57
- key = self.get_path(path)
58
- if key in self.convert_image_cache:
59
- return
60
- self.convert_image_cache[key] = pygame.image.load(path).convert()
61
- self.convert_alpha_image_cache[key] = pygame.image.load(path).convert_alpha()
62
-
63
- def get_image(self, path, convert_alpha: bool = False) -> pygame.Surface | None:
64
- key = self.get_path(path)
65
- return (
66
- self.convert_alpha_image_cache.get(key, None)
67
- if convert_alpha
68
- else self.convert_image_cache.get(key, None)
69
- )
70
-
71
- def load_json_from_file(self, path: str) -> dict | None:
72
- try:
73
- with open(self.get_path(path), "r") as file:
74
- data = json.load(file)
75
- return data
76
- except FileNotFoundError:
77
- print(f"File '{path}' not found")
78
- return None
79
-
80
- def save_json_to_file(self, path: str, data) -> bool:
81
- try:
82
- with open(self.get_path(path), "w") as file:
83
- json.dump(data, file, indent=2)
84
- return True
85
- except FileNotFoundError:
86
- return False
87
-
88
-
89
- def set_sharedVar(self, name, value) -> bool:
90
- """
91
- Set a shared variable of any type. This will be accessible (read/write) from any scene
92
- """
93
- self.shared_variables[name] = value
94
- return True
95
-
96
- def get_sharedVar(self, name, error_value=None):
97
- """
98
- Get a shared variable
99
- """
100
- return self.shared_variables.get(name, error_value)