mima-engine 0.4.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 (153) hide show
  1. mima/__init__.py +4 -0
  2. mima/backend/__init__.py +1 -0
  3. mima/backend/pygame_assets.py +401 -0
  4. mima/backend/pygame_audio.py +78 -0
  5. mima/backend/pygame_backend.py +603 -0
  6. mima/backend/pygame_camera.py +63 -0
  7. mima/backend/pygame_events.py +695 -0
  8. mima/backend/touch_control_scheme_a.py +126 -0
  9. mima/backend/touch_control_scheme_b.py +132 -0
  10. mima/core/__init__.py +0 -0
  11. mima/core/collision.py +325 -0
  12. mima/core/database.py +58 -0
  13. mima/core/engine.py +367 -0
  14. mima/core/mode_engine.py +81 -0
  15. mima/core/scene_engine.py +81 -0
  16. mima/integrated/__init__.py +0 -0
  17. mima/integrated/entity.py +183 -0
  18. mima/integrated/layered_map.py +351 -0
  19. mima/integrated/sprite.py +156 -0
  20. mima/layered/__init__.py +0 -0
  21. mima/layered/assets.py +56 -0
  22. mima/layered/scene.py +415 -0
  23. mima/layered/shape.py +99 -0
  24. mima/layered/shaped_sprite.py +78 -0
  25. mima/layered/virtual_input.py +302 -0
  26. mima/maps/__init__.py +0 -0
  27. mima/maps/template.py +71 -0
  28. mima/maps/tile.py +20 -0
  29. mima/maps/tile_animation.py +7 -0
  30. mima/maps/tile_info.py +10 -0
  31. mima/maps/tile_layer.py +52 -0
  32. mima/maps/tiled/__init__.py +0 -0
  33. mima/maps/tiled/tiled_layer.py +48 -0
  34. mima/maps/tiled/tiled_map.py +95 -0
  35. mima/maps/tiled/tiled_object.py +79 -0
  36. mima/maps/tiled/tiled_objectgroup.py +25 -0
  37. mima/maps/tiled/tiled_template.py +49 -0
  38. mima/maps/tiled/tiled_tile.py +90 -0
  39. mima/maps/tiled/tiled_tileset.py +51 -0
  40. mima/maps/tilemap.py +216 -0
  41. mima/maps/tileset.py +39 -0
  42. mima/maps/tileset_info.py +9 -0
  43. mima/maps/transition_map.py +146 -0
  44. mima/objects/__init__.py +0 -0
  45. mima/objects/animated_sprite.py +217 -0
  46. mima/objects/attribute_effect.py +26 -0
  47. mima/objects/attributes.py +126 -0
  48. mima/objects/creature.py +384 -0
  49. mima/objects/dynamic.py +206 -0
  50. mima/objects/effects/__init__.py +0 -0
  51. mima/objects/effects/colorize_screen.py +60 -0
  52. mima/objects/effects/debug_box.py +133 -0
  53. mima/objects/effects/light.py +103 -0
  54. mima/objects/effects/show_sprite.py +50 -0
  55. mima/objects/effects/walking_on_grass.py +70 -0
  56. mima/objects/effects/walking_on_water.py +57 -0
  57. mima/objects/loader.py +111 -0
  58. mima/objects/projectile.py +111 -0
  59. mima/objects/sprite.py +116 -0
  60. mima/objects/world/__init__.py +0 -0
  61. mima/objects/world/color_gate.py +67 -0
  62. mima/objects/world/color_switch.py +101 -0
  63. mima/objects/world/container.py +175 -0
  64. mima/objects/world/floor_switch.py +109 -0
  65. mima/objects/world/gate.py +178 -0
  66. mima/objects/world/light_source.py +121 -0
  67. mima/objects/world/logic_gate.py +157 -0
  68. mima/objects/world/movable.py +399 -0
  69. mima/objects/world/oneway.py +195 -0
  70. mima/objects/world/pickup.py +157 -0
  71. mima/objects/world/switch.py +179 -0
  72. mima/objects/world/teleport.py +308 -0
  73. mima/py.typed +0 -0
  74. mima/scripts/__init__.py +2 -0
  75. mima/scripts/command.py +38 -0
  76. mima/scripts/commands/__init__.py +0 -0
  77. mima/scripts/commands/add_quest.py +19 -0
  78. mima/scripts/commands/change_map.py +34 -0
  79. mima/scripts/commands/close_dialog.py +9 -0
  80. mima/scripts/commands/equip_weapon.py +23 -0
  81. mima/scripts/commands/give_item.py +26 -0
  82. mima/scripts/commands/give_resource.py +51 -0
  83. mima/scripts/commands/move_map.py +152 -0
  84. mima/scripts/commands/move_to.py +49 -0
  85. mima/scripts/commands/oneway_move.py +58 -0
  86. mima/scripts/commands/parallel.py +66 -0
  87. mima/scripts/commands/play_sound.py +13 -0
  88. mima/scripts/commands/present_item.py +53 -0
  89. mima/scripts/commands/progress_quest.py +12 -0
  90. mima/scripts/commands/quit_game.py +8 -0
  91. mima/scripts/commands/save_game.py +14 -0
  92. mima/scripts/commands/screen_fade.py +83 -0
  93. mima/scripts/commands/serial.py +69 -0
  94. mima/scripts/commands/set_facing_direction.py +21 -0
  95. mima/scripts/commands/set_spawn_map.py +17 -0
  96. mima/scripts/commands/show_choices.py +52 -0
  97. mima/scripts/commands/show_dialog.py +118 -0
  98. mima/scripts/commands/take_coins.py +23 -0
  99. mima/scripts/script_processor.py +61 -0
  100. mima/standalone/__init__.py +0 -0
  101. mima/standalone/camera.py +153 -0
  102. mima/standalone/geometry.py +1318 -0
  103. mima/standalone/multicolumn_list.py +54 -0
  104. mima/standalone/pixel_font.py +84 -0
  105. mima/standalone/scripting.py +145 -0
  106. mima/standalone/spatial.py +186 -0
  107. mima/standalone/sprite.py +158 -0
  108. mima/standalone/tiled_map.py +1247 -0
  109. mima/standalone/transformed_view.py +433 -0
  110. mima/standalone/user_input.py +563 -0
  111. mima/states/__init__.py +0 -0
  112. mima/states/game_state.py +189 -0
  113. mima/states/memory.py +28 -0
  114. mima/states/quest.py +71 -0
  115. mima/types/__init__.py +0 -0
  116. mima/types/alignment.py +7 -0
  117. mima/types/blend.py +8 -0
  118. mima/types/damage.py +42 -0
  119. mima/types/direction.py +44 -0
  120. mima/types/gate_color.py +7 -0
  121. mima/types/graphic_state.py +23 -0
  122. mima/types/keys.py +64 -0
  123. mima/types/mode.py +9 -0
  124. mima/types/nature.py +12 -0
  125. mima/types/object.py +22 -0
  126. mima/types/player.py +9 -0
  127. mima/types/position.py +13 -0
  128. mima/types/start.py +7 -0
  129. mima/types/terrain.py +9 -0
  130. mima/types/tile_collision.py +11 -0
  131. mima/types/weapon_slot.py +6 -0
  132. mima/types/window.py +44 -0
  133. mima/usables/__init__.py +0 -0
  134. mima/usables/item.py +51 -0
  135. mima/usables/weapon.py +68 -0
  136. mima/util/__init__.py +1 -0
  137. mima/util/colors.py +50 -0
  138. mima/util/constants.py +55 -0
  139. mima/util/functions.py +38 -0
  140. mima/util/input_defaults.py +170 -0
  141. mima/util/logging.py +51 -0
  142. mima/util/property.py +8 -0
  143. mima/util/runtime_config.py +327 -0
  144. mima/util/trading_item.py +23 -0
  145. mima/view/__init__.py +0 -0
  146. mima/view/camera.py +192 -0
  147. mima/view/mima_mode.py +618 -0
  148. mima/view/mima_scene.py +231 -0
  149. mima/view/mima_view.py +12 -0
  150. mima/view/mima_window.py +244 -0
  151. mima_engine-0.4.0.dist-info/METADATA +47 -0
  152. mima_engine-0.4.0.dist-info/RECORD +153 -0
  153. mima_engine-0.4.0.dist-info/WHEEL +4 -0
mima/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ __version__ = "0.4.0"
2
+
3
+ from .core.engine import MimaEngine as MimaEngine
4
+ from .core.mode_engine import MimaModeEngine as MimaModeEngine
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,401 @@
1
+ from __future__ import annotations
2
+
3
+ import csv
4
+ import logging
5
+ import os
6
+ from typing import TYPE_CHECKING, Any, Dict, Optional
7
+
8
+ import pygame
9
+
10
+ from ..maps.tiled.tiled_map import TiledMap
11
+ from ..maps.tiled.tiled_template import TiledTemplate
12
+ from ..maps.tiled.tiled_tileset import TiledTileset
13
+
14
+ if TYPE_CHECKING:
15
+ from ..maps.tilemap import Tilemap
16
+ from ..util import RuntimeConfig
17
+
18
+ LOG = logging.getLogger(__name__)
19
+
20
+
21
+ class PygameAssets:
22
+ def __init__(self, rtc: RuntimeConfig, init_file: str):
23
+ self.rtc = rtc
24
+ self._images: Dict[str, pygame.Surface] = {}
25
+ self._tilesets: Dict[str, TiledTileset] = {}
26
+ self._templates: Dict[str, TiledTemplate] = {}
27
+ self._sprite_sheets: Dict[str, Dict[Any]] = {}
28
+ self._maps: Dict[str, TiledMap] = {}
29
+ self._music: Dict[str, str] = {}
30
+ self._sound: Dict[str, str] = {}
31
+ self._csvs: Dict[str, str] = {}
32
+ self._assets_to_load: Dict[str, str] = {}
33
+ self._assets_to_preload: Dict[str, str] = {}
34
+ self._paths: Dict[str, str] = {}
35
+ self.data_path = ""
36
+ self._preprocess_asset_file(init_file)
37
+
38
+ def _preprocess_asset_file(self, init_file: str):
39
+ self.data_path = os.path.dirname(init_file)
40
+ # path = os.path.join(self._data_path, asset_file)
41
+ current_type = "paths"
42
+
43
+ with open(init_file) as f:
44
+ for line in f.readlines():
45
+ line = line.strip()
46
+ self._assets_to_load.setdefault(current_type, [])
47
+ self._assets_to_preload.setdefault(current_type, [])
48
+
49
+ assets_to_load = self._assets_to_load
50
+
51
+ if "_PRELOAD]" in line:
52
+ assets_to_load = self._assets_to_preload
53
+ if "[PATHS]" in line:
54
+ current_type = "paths"
55
+ elif "[GFX" in line:
56
+ current_type = "gfx"
57
+ elif "[MAPS" in line:
58
+ current_type = "maps"
59
+ elif "[TEMPLATES" in line:
60
+ current_type = "templates"
61
+ elif "[TILESETS" in line:
62
+ current_type = "tilesets"
63
+ elif "[MUSIC" in line:
64
+ current_type = "music"
65
+ elif "[SFX" in line:
66
+ current_type = "sound"
67
+ elif "[CSV" in line:
68
+ current_type = "csv"
69
+ else:
70
+ if line != "" and not line.startswith("#"):
71
+ if current_type != "paths":
72
+ # print(self.data_path, current_type, line)
73
+ assets_to_load[current_type].append(
74
+ os.path.abspath(
75
+ os.path.join(
76
+ self.data_path,
77
+ self._paths.get(current_type, "."),
78
+ line,
79
+ )
80
+ )
81
+ )
82
+ else:
83
+ name, p = line.split("=")
84
+ self._paths[name] = p
85
+
86
+ def load(self):
87
+ for gfx in self._assets_to_load.get("gfx", []):
88
+ name = os.path.split(gfx)[1].split(".")[0]
89
+ # print(gfx, name)
90
+ self._load_sprite(name, gfx)
91
+
92
+ for tts in self._assets_to_load.get("tilesets", []):
93
+ try:
94
+ LOG.debug("Attempting to load tileset %s", tts)
95
+ name = os.path.split(tts)[1].split(".")[0]
96
+ self._load_tileset(name, tts)
97
+ except Exception as err:
98
+ LOG.warning("Couldn't load tileset %s: %s", tts, err)
99
+
100
+ for tmp in self._assets_to_load.get("templates", []):
101
+ name = os.path.split(tmp)[1].split(".")[0]
102
+ self._load_template(name, tmp)
103
+
104
+ for tmap in self._assets_to_load.get("maps", []):
105
+ name = os.path.split(tmap)[1].split(".")[0]
106
+ self._load_map(name, tmap)
107
+
108
+ for mus in self._assets_to_load.get("music", []):
109
+ name = os.path.split(mus)[1].split(".")[0]
110
+ self._load_music(name, mus)
111
+
112
+ for snd in self._assets_to_load.get("sound", []):
113
+ name = os.path.split(snd)[1].split(".")[0]
114
+ self._load_sound(name, snd)
115
+
116
+ for csvf in self._assets_to_load.get("csv", []):
117
+ name = os.path.split(csvf)[1].split(".")[0]
118
+ self._load_csv(name, csvf)
119
+
120
+ def _load_csv(self, name, filename):
121
+ if not os.path.isfile(filename):
122
+ filename = os.path.join(
123
+ self.data_path, "csv", os.path.split(filename)[-1]
124
+ )
125
+
126
+ possible_name = os.path.split(filename)[-1][:-4]
127
+ if possible_name in self._csvs:
128
+ LOG.warning(f"CSV '{filename}' already loaded as {possible_name}.")
129
+ elif name in self._csvs:
130
+ LOG.debug(f"CSV '{name}' alread loaded. Skipping.")
131
+ return name
132
+
133
+ with open(filename, "r") as csv_file:
134
+ reader = csv.DictReader(csv_file, delimiter=",")
135
+ self._csvs[name] = [row for row in reader]
136
+
137
+ def _load_sprite(self, name, filename=None):
138
+ if filename is None:
139
+ filename = f"{name}.png"
140
+
141
+ # print(filename)
142
+ if not os.path.isfile(filename):
143
+ filename = os.path.join(
144
+ self.data_path, "gfx", os.path.split(filename)[-1]
145
+ )
146
+ # print(name, filename)
147
+
148
+ possible_name = os.path.split(filename)[-1][:-4]
149
+ if possible_name in self._images:
150
+ LOG.warning(
151
+ "Sprite '%s' is possibly already loaded with name %s.",
152
+ filename,
153
+ possible_name,
154
+ )
155
+ elif name in self._images:
156
+ LOG.debug("Sprite '%s' already loaded. Skipping.")
157
+ return name
158
+
159
+ self._images[name] = self._load_sprite_from_disk(filename)
160
+
161
+ return name
162
+
163
+ def _load_tileset(self, name, filename=None):
164
+ if filename is None:
165
+ filename = f"{name}.tsx"
166
+
167
+ if not os.path.isfile(filename):
168
+ filename = os.path.abspath(
169
+ os.path.join(
170
+ self.data_path,
171
+ self._paths.get("tilesets", "."),
172
+ os.path.split(filename)[-1],
173
+ )
174
+ )
175
+
176
+ possible_name = os.path.split(filename)[-1][:-4]
177
+ if possible_name in self._tilesets:
178
+ LOG.warning(
179
+ "Tileset at '%s' is possible already loaded with name %s.",
180
+ filename,
181
+ possible_name,
182
+ )
183
+ elif name in self._tilesets:
184
+ LOG.debug("Tileset at '%s' already loaded. Skipping", filename)
185
+ return name
186
+ ts = TiledTileset(name, filename)
187
+ self._tilesets[name] = ts
188
+
189
+ # Load sprite sheets
190
+ for tile in ts.tiles:
191
+ if not tile.sprite_name:
192
+ continue
193
+
194
+ self._sprite_sheets.setdefault(tile.sprite_name, {})
195
+ data = {
196
+ "duration": [],
197
+ "ox": [],
198
+ "oy": [],
199
+ "image": [],
200
+ "width": [],
201
+ "height": [],
202
+ }
203
+ if tile.animated:
204
+ for frame in tile._frames:
205
+ data["duration"].append(frame.duration)
206
+ data["ox"].append(frame.frame_id % ts.columns)
207
+ data["oy"].append(frame.frame_id // ts.columns)
208
+ data["image"].append(ts.image_name)
209
+ data["width"].append(ts.tile_width)
210
+ data["height"].append(ts.tile_height)
211
+ else:
212
+ data["duration"].append(1000)
213
+ data["ox"].append(tile.tile_id % ts.columns)
214
+ data["oy"].append(tile.tile_id // ts.columns)
215
+ data["image"].append(ts.image_name)
216
+ data["width"].append(ts.tile_width)
217
+ data["height"].append(ts.tile_height)
218
+
219
+ self._sprite_sheets[tile.sprite_name].setdefault(
220
+ tile.graphic_state, {}
221
+ )
222
+ self._sprite_sheets[tile.sprite_name][tile.graphic_state][
223
+ tile.facing_direction
224
+ ] = data
225
+ LOG.debug(
226
+ "%s",
227
+ {
228
+ "operation": "add frames",
229
+ "image": ts.image_name,
230
+ "sprite": tile.sprite_name,
231
+ "graphic_state": tile.graphic_state.name,
232
+ "direction": tile.facing_direction.name,
233
+ "frame_data": data,
234
+ },
235
+ )
236
+
237
+ # for sprite_name in ts.sprite_names:
238
+ # self._sprites[sprite_name] = {}
239
+ return name
240
+
241
+ def _load_template(self, name, filename=None):
242
+ if filename is None:
243
+ filename = f"{name}.tx"
244
+
245
+ if not os.path.isfile(filename):
246
+ filename = os.path.join(
247
+ self.data_path, "templates", os.path.split(filename)[-1]
248
+ )
249
+
250
+ possible_name = os.path.split(filename)[-1][:-3]
251
+ if possible_name in self._templates:
252
+ LOG.warning(
253
+ "Template at '%s' is possible already loaded with name %s.",
254
+ filename,
255
+ possible_name,
256
+ )
257
+ elif name in self._templates:
258
+ LOG.debug("Template at '%s' already loaded. Skipping", filename)
259
+ return name
260
+
261
+ self._templates[name] = TiledTemplate(name, filename)
262
+ return name
263
+
264
+ def _load_map(self, name, filename=None):
265
+ possible_name = os.path.split(filename)[-1][:-4]
266
+ if possible_name in self._maps:
267
+ LOG.warning(
268
+ "Map at '%s' is possibly already loaded with name %s.",
269
+ filename,
270
+ possible_name,
271
+ )
272
+ elif name in self._maps:
273
+ LOG.debug("Map at '%s' already loaded. Skipping", filename)
274
+ return name
275
+ try:
276
+ self._maps[name] = TiledMap(name, filename)
277
+ except KeyError:
278
+ LOG.exception(f"Failed to load map={name}")
279
+ raise
280
+
281
+ return name
282
+
283
+ def _load_music(self, name, filename=None):
284
+ if filename is None:
285
+ filename = f"{name}.ogg"
286
+
287
+ if not os.path.isfile(filename):
288
+ filename = os.path.join(
289
+ self.data_path,
290
+ self._paths.get("music", "."),
291
+ os.path.split(filename)[-1],
292
+ )
293
+ possible_name = os.path.split(filename)[-1][:-4]
294
+ if possible_name in self._music:
295
+ LOG.warning(
296
+ "Music at '%s' is possibly already loaded with name %s.",
297
+ filename,
298
+ possible_name,
299
+ )
300
+ elif name in self._music:
301
+ LOG.debug("Music at '%s already loaded. Skipping.", filename)
302
+ return name
303
+
304
+ self._music[name] = filename
305
+ return name
306
+
307
+ def _load_sound(self, name, filename=None):
308
+ if filename is None:
309
+ filename = f"{name}.ogg"
310
+
311
+ if not os.path.isfile(filename):
312
+ filename = os.path.join(
313
+ self.data_path,
314
+ self._paths.get("sfx", "."),
315
+ os.path.split(filename)[-1],
316
+ )
317
+ possible_name = os.path.split(filename)[-1][:-4]
318
+ if possible_name in self._sound:
319
+ LOG.warning(
320
+ "Sound at '%s' is possibly already loaded with name %s.",
321
+ filename,
322
+ possible_name,
323
+ )
324
+ elif name in self._sound:
325
+ LOG.debug("Sound at '%s already loaded. Skipping.", filename)
326
+ return name
327
+
328
+ self._sound[name] = pygame.mixer.Sound(filename)
329
+ return name
330
+
331
+ def _load_item(self, item):
332
+ LOG.debug("Loading item %s.", item.name)
333
+ self._items[item.name] = item
334
+
335
+ def get_sprite(self, name) -> Optional[pygame.Surface]:
336
+ if name is None:
337
+ return None
338
+ else:
339
+ if self.rtc.flags.get("use_color", False):
340
+ name_color = f"{name}_color"
341
+ else:
342
+ name_color = name
343
+ return self._images.get(name_color, self._images[name])
344
+
345
+ def get_sprite_data(self, sprite_id):
346
+ if not sprite_id:
347
+ return {}
348
+ return self._sprite_sheets[sprite_id]
349
+
350
+ def new_map(self, name, tilemap: Tilemap):
351
+ self._maps[name] = tilemap
352
+
353
+ def new_sprite(self, name, surface: pygame.Surface):
354
+ self._images[name] = surface
355
+
356
+ def get_tileset(self, name):
357
+ if name not in self._tilesets:
358
+ msg = f"Could not find tileset '{name}'."
359
+ raise ValueError(msg)
360
+ # LOG.warning("Could not find tileset %s.", name)
361
+ # return self._tilesets["simple_sheet"]
362
+ return self._tilesets[name]
363
+
364
+ def get_template(self, name):
365
+ if name not in self._templates:
366
+ LOG.warning("Could not find template %s.", name)
367
+ return self._templates["bush01"]
368
+ return self._templates[name]
369
+
370
+ def get_map(self, name):
371
+ return self._maps[name]
372
+
373
+ def get_music(self, name):
374
+ return self._music[name]
375
+
376
+ def get_sound(self, name):
377
+ return self._sound[name]
378
+
379
+ def get_csv(self, name):
380
+ return self._csvs[name]
381
+
382
+ def _load_sprite_from_disk(self, filename: str) -> pygame.Surface:
383
+ if "color" in filename:
384
+ return pygame.image.load(filename).convert_alpha()
385
+ else:
386
+ image = pygame.image.load(filename).convert_alpha()
387
+ var = pygame.PixelArray(image)
388
+
389
+ new_colors = {
390
+ name: color
391
+ for name, color in self.rtc.colors.items()
392
+ if f"{name}_default" in self.rtc.colors
393
+ }
394
+ for name, new_color in new_colors.items():
395
+ var.replace(
396
+ self.rtc.colors[f"{name}_default"].getRGBA(),
397
+ new_color.getRGBA(),
398
+ )
399
+
400
+ del var
401
+ return image
@@ -0,0 +1,78 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from typing import TYPE_CHECKING, List, Tuple
5
+
6
+ import pygame
7
+
8
+ if TYPE_CHECKING:
9
+ from .pygame_assets import PygameAssets
10
+
11
+ LOG = logging.getLogger(__name__)
12
+
13
+
14
+ class PygameAudio:
15
+ def __init__(self, assets: PygameAssets):
16
+ self.assets = assets
17
+ self.current_track: str = ""
18
+ self.is_playing: bool = False
19
+ self.sound_schedule: List[Tuple[float, str]] = []
20
+ self._time_so_far: float = 0.0
21
+
22
+ def update(self, elapsed_time: float):
23
+ self._time_so_far += elapsed_time
24
+
25
+ sounds_to_remove = []
26
+ for sound_tuple in self.sound_schedule:
27
+ if self._time_so_far >= sound_tuple[0]:
28
+ self._play_sound(sound_tuple[1])
29
+ sounds_to_remove.append(sound_tuple)
30
+
31
+ for sound in sounds_to_remove:
32
+ self.sound_schedule.remove(sound)
33
+
34
+ if self._time_so_far >= 10.0:
35
+ self._time_so_far -= 10.0
36
+ for idx in range(len(self.sound_schedule)):
37
+ self.sound_schedule[idx] = (
38
+ self.sound_schedule[idx][0] - 10.0,
39
+ self.sound_schedule[idx][1],
40
+ )
41
+
42
+ def play_music(self, name: str, repeat: int = -1):
43
+ if self.is_playing and name == self.current_track:
44
+ return
45
+
46
+ else:
47
+ try:
48
+ self._play_music(name)
49
+ self.current_track = name
50
+ self.is_playing = True
51
+ except Exception:
52
+ LOG.exception(f"Could not load {name}.")
53
+
54
+ def _play_music(self, name: str, repeat: int = -1):
55
+ pygame.mixer.music.load(self.assets.get_music(name))
56
+ pygame.mixer.music.play(repeat)
57
+
58
+ def _play_sound(self, name: str):
59
+ snd = self.assets.get_sound(name)
60
+ snd.set_volume(100)
61
+ snd.play()
62
+
63
+ def stop(self):
64
+ if self.is_playing:
65
+ pygame.mixer.music.pause()
66
+ self.is_playing = False
67
+
68
+ def stop_sound(self, sound_to_stop: str):
69
+ self.assets.get_sound(sound_to_stop).set_volume(0)
70
+
71
+ def set_music_volume(self, vol: float):
72
+ pygame.mixer.music.set_volume(vol)
73
+
74
+ def set_sound_volume(self, vol: float):
75
+ pass
76
+
77
+ def play_sound(self, sound_to_play: str, delay: float = 0.0):
78
+ self.sound_schedule.append((self._time_so_far + delay, sound_to_play))