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
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from ..command import Command
6
+
7
+ if TYPE_CHECKING:
8
+ from ...states.quest import Quest
9
+
10
+
11
+ class CommandAddQuest(Command):
12
+ def __init__(self, quest: Quest):
13
+ super().__init__()
14
+
15
+ self._quest: Quest = quest
16
+
17
+ def start(self):
18
+ self.engine.add_quest(self._quest)
19
+ self.completed = True
@@ -0,0 +1,34 @@
1
+ from typing import List, Optional
2
+
3
+ from ...types.player import Player
4
+ from ..command import Command
5
+
6
+
7
+ class CommandChangeMap(Command):
8
+ def __init__(
9
+ self,
10
+ map_name: str,
11
+ spawn_px: float,
12
+ spawn_py,
13
+ players: Optional[List[Player]] = None,
14
+ ):
15
+ if players is None:
16
+ players = [Player.P1]
17
+
18
+ super().__init__(players)
19
+
20
+ self._map_name: str = map_name
21
+ self._spawn_px: float = spawn_px
22
+ self._spawn_py: float = spawn_py
23
+
24
+ def start(self):
25
+ self.engine.get_view().unload_map(self.players[0])
26
+ self.engine.get_view().load_map(
27
+ self._map_name, self._spawn_px, self._spawn_py, self.players[0]
28
+ )
29
+ # self.engine.change_map(self._map_name, self._spawn_px, self._spawn_py)
30
+ self.completed = True
31
+
32
+ def finalize(self):
33
+ self.engine.trigger_teleport(False, self.players[0])
34
+ self.engine.trigger_player_collision(False, self.players[0])
@@ -0,0 +1,9 @@
1
+ from ..command import Command
2
+
3
+
4
+ class CommandCloseDialog(Command):
5
+ def start(self):
6
+ for player in self.players:
7
+ self.engine.trigger_dialog(False, player)
8
+ self.engine.exit_dialog_active = False
9
+ self.completed = True
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ from ..command import Command
6
+
7
+ if TYPE_CHECKING:
8
+ from ...objects.creature import Creature
9
+ from ...types.weapon_slot import WeaponSlot
10
+ from ...usables.weapon import Weapon
11
+
12
+
13
+ class CommandEquipWeapon(Command):
14
+ def __init__(self, weapon: Weapon, creature: Creature, slot: WeaponSlot):
15
+ super().__init__()
16
+
17
+ self._weapon: Weapon = weapon
18
+ self._target: Creature = creature
19
+ self._slot: WeaponSlot = slot
20
+
21
+ def start(self):
22
+ self._target.equip_weapon(self._slot, self._weapon)
23
+ self.completed = True
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ from ..command import Command
6
+
7
+ if TYPE_CHECKING:
8
+ from ...objects.dynamic import Dynamic
9
+
10
+
11
+ class CommandGiveItem(Command):
12
+ def __init__(self, item_name: str, dynamic: Optional[Dynamic] = None):
13
+ super().__init__()
14
+
15
+ self._item_name: str = item_name
16
+
17
+ # if dynamic is None:
18
+ # dynamic = self.engine.player
19
+
20
+ self._dynamic: Dynamic = dynamic
21
+
22
+ def start(self):
23
+ # if self._dynamic is None:
24
+ # self._dynamic = self.engine.get_player(self.players[0])
25
+ self.engine.give_item(self._item_name, self.players[0])
26
+ self.completed = True
@@ -0,0 +1,51 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Dict, Optional
4
+
5
+ from ..command import Command
6
+
7
+ if TYPE_CHECKING:
8
+ from ...objects.dynamic import Dynamic
9
+
10
+
11
+ class CommandGiveResource(Command):
12
+ def __init__(self, dynamic: Optional[Dynamic] = None, **resources: Dict[str, int]):
13
+ super().__init__()
14
+
15
+ if dynamic is None:
16
+ dynamic = self.engine.player
17
+
18
+ self._dynamic: Dynamic = dynamic
19
+ self._health: int = resources.get("health", 0)
20
+ self._magic: int = resources.get("magic", 0)
21
+ self._stamina: int = resources.get("stamina", 0)
22
+ self._arrows: int = resources.get("arrows", 0)
23
+ self._bombs: int = resources.get("bombs", 0)
24
+ self._coins: int = resources.get("coins", 0)
25
+ self._keys: int = resources.get("keys", 0)
26
+
27
+ def start(self):
28
+ self._dynamic.attributes.health = min(
29
+ self._dynamic.attributes.health + self._health,
30
+ self._dynamic.attributes.health_max,
31
+ )
32
+ self._dynamic.attributes.magic = min(
33
+ self._dynamic.attributes.magic + self._magic,
34
+ self._dynamic.attributes.magic_max,
35
+ )
36
+ self._dynamic.attributes.stamina = min(
37
+ self._dynamic.attributes.stamina + self._stamina,
38
+ self._dynamic.attributes.stamina_max,
39
+ )
40
+ self._dynamic.attributes.arrows = min(
41
+ self._dynamic.attributes.arrows + self._arrows,
42
+ self._dynamic.attributes.arrows_max,
43
+ )
44
+ self._dynamic.attributes.bombs = min(
45
+ self._dynamic.attributes.bombs + self._bombs,
46
+ self._dynamic.attributes.bombs_max,
47
+ )
48
+ self._dynamic.attributes.coins += self._coins
49
+ self._dynamic.attributes.keys += self._keys
50
+
51
+ self.completed = True
@@ -0,0 +1,152 @@
1
+ from typing import List, Optional
2
+
3
+ from ...maps.transition_map import TransitionMap
4
+ from ...objects.dynamic import Dynamic
5
+ from ...types.player import Player
6
+ from ...util.constants import HEIGHT, MOVE_MAP_DURATION, WIDTH
7
+ from ..command import Command
8
+
9
+
10
+ class CommandMoveMap(Command):
11
+ def __init__(
12
+ self,
13
+ *,
14
+ new_map_name: str,
15
+ obj: Dynamic,
16
+ target_px: float,
17
+ target_py: float,
18
+ vx: float,
19
+ vy: float,
20
+ players: Optional[List[Player]] = None,
21
+ ):
22
+ super().__init__()
23
+
24
+ self.players = [obj.is_player()]
25
+ self.src_map = self.engine.scene.tilemap
26
+ self.dst_map = self.engine.assets.get_map(new_map_name)
27
+ self.obj: Dynamic = obj
28
+ self.vx: float = vx
29
+ self.vy: float = vy
30
+ self.start_px: float = 0
31
+ self.start_py: float = 0
32
+ self.start_ox: float = 0
33
+ self.start_oy: float = 0
34
+ self.target_px: float = target_px
35
+ self.target_py: float = target_py
36
+ self.target_ox: float = 0
37
+ self.target_oy: float = 0
38
+ self.final_px: float = target_px
39
+ self.final_py: float = target_py
40
+
41
+ if self.vx == 0 and self.vy == 0:
42
+ # Error
43
+ self.completed = True
44
+ self.started = True
45
+
46
+ self.duration: float = MOVE_MAP_DURATION
47
+ self.time_so_far: float = 0.0
48
+
49
+ def start(self) -> None:
50
+ # Prevent circular import
51
+ # from ...maps.transition_map import TransitionMap
52
+
53
+ self.start_ox = self._get_offset_x(self.obj.px)
54
+ self.start_oy = self._get_offset_y(self.obj.py)
55
+ self.target_ox = self._get_offset_x(self.target_px)
56
+ self.target_oy = self._get_offset_y(self.target_py)
57
+ self.start_px = self.obj.px
58
+ self.start_py = self.obj.py
59
+
60
+ # print(
61
+ # f"start_pos=({self.start_px:.1f}, {self.start_py:.1f}), "
62
+ # f"tar_pos=({self.target_px:.1f}, {self.target_py:.1f}), "
63
+ # f"start_off=({self.start_ox:.1f}, {self.start_oy:.1f}), "
64
+ # f"tar_off=({self.target_ox:.1f}, {self.target_oy:.1f})"
65
+ # )
66
+
67
+ if self.vx != 0:
68
+ if self.vx < 0:
69
+ self.target_px -= self.target_ox
70
+ else:
71
+ self.target_px += self.start_ox
72
+ self.target_py = self.start_py
73
+
74
+ elif self.vy != 0:
75
+ self.target_px = self.start_px
76
+ if self.vy < 0:
77
+ self.target_py -= self.target_oy + 1
78
+ else:
79
+ self.target_py += self.start_oy + 1
80
+
81
+ self.obj.solid_vs_dyn = False
82
+ self.obj.solid_vs_map = False
83
+ self.obj.vx = self.obj.vy = 0
84
+ self.engine.teleport_triggered = True
85
+ self.engine.scene.tilemap = TransitionMap(
86
+ self.src_map, self.dst_map, self.vx, self.vy
87
+ )
88
+ self.engine.scene.delete_map_dynamics()
89
+
90
+ def update(self, elapsed_time):
91
+ self.time_so_far += elapsed_time
92
+ rela_time = self.time_so_far / self.duration
93
+ if rela_time > 1.0:
94
+ rela_time = 1.0
95
+
96
+ self.obj.px = (
97
+ self.target_px - self.start_px
98
+ ) * rela_time + self.start_px
99
+ self.obj.py = (
100
+ self.target_py - self.start_py
101
+ ) * rela_time + self.start_py
102
+
103
+ ox = self._get_offset_x(self.obj.px)
104
+ oy = self._get_offset_y(self.obj.py)
105
+ self.obj.extra_ox = ox - self.start_ox
106
+ self.obj.extra_oy = oy - self.start_oy
107
+
108
+ if self.time_so_far >= self.duration:
109
+ self.completed = True
110
+ else:
111
+ self.engine.teleport_triggered = True
112
+
113
+ # print(f"obj_pos=({self.obj.px:.1f}, {self.obj.py:.1f})")
114
+
115
+ def finalize(self):
116
+ if self.vy != 0:
117
+ self.obj.px = self.target_px
118
+ if self.vy > 0:
119
+ self.obj.py = self.target_py - self.start_oy - 1
120
+ else:
121
+ self.obj.py = self.target_py + self.target_oy + 1
122
+
123
+ self.obj.vx = self.obj.vy = 0
124
+ self.obj.solid_vs_dyn = True
125
+ self.obj.solid_vs_map = True
126
+ self.obj.extra_ox = self.obj.extra_oy = 0
127
+ self.engine.scene.change_map(
128
+ self.dst_map.name, self.final_px, self.final_py
129
+ )
130
+
131
+ def _get_offset_x(self, px: float) -> float:
132
+ visible_tiles = WIDTH / self.engine.rtc.tile_width
133
+ offset = px - visible_tiles / 2.0
134
+
135
+ if offset < 0:
136
+ offset = 0
137
+ if offset > self.src_map.width - visible_tiles:
138
+ offset = self.src_map.width - visible_tiles
139
+
140
+ return offset
141
+
142
+ def _get_offset_y(self, py: float) -> float:
143
+ visible_tiles = HEIGHT / self.engine.rtc.tile_width - 1
144
+ offset = py - visible_tiles / 2.0
145
+
146
+ if offset < 0:
147
+ offset = 0
148
+ if offset > self.src_map.height - visible_tiles:
149
+ offset = self.src_map.height - visible_tiles
150
+
151
+ offset -= 1
152
+ return offset
@@ -0,0 +1,49 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from ...scripts.command import Command
6
+
7
+ if TYPE_CHECKING:
8
+ from ...objects.dynamic import Dynamic
9
+
10
+
11
+ class CommandMoveTo(Command):
12
+ def __init__(
13
+ self,
14
+ obj: Dynamic,
15
+ target_px: float,
16
+ target_py: float,
17
+ duration: float = 0.0,
18
+ ):
19
+ super().__init__()
20
+
21
+ self.obj: Dynamic = obj
22
+ self.start_px: float = 0.0
23
+ self.start_py: float = 0.0
24
+ self.target_px: float = target_px
25
+ self.target_py: float = target_py
26
+
27
+ self.duration: float = max(duration, 0.001)
28
+ self.time_so_far: float = 0.0
29
+
30
+ def start(self):
31
+ self.start_px = self.obj.px
32
+ self.start_py = self.obj.py
33
+
34
+ def update(self, elapsed_time: float):
35
+ self.time_so_far += elapsed_time
36
+ relatime = min(1.0, self.time_so_far / self.duration)
37
+
38
+ self.obj.px = (self.target_px - self.start_px) * relatime + self.start_px
39
+ self.obj.py = (self.target_py - self.start_py) * relatime + self.start_py
40
+ self.obj.vx = (self.target_px - self.start_px) / self.duration
41
+ self.obj.vy = (self.target_py - self.start_py) / self.duration
42
+
43
+ if self.time_so_far >= self.duration:
44
+ self.completed = True
45
+
46
+ def finalize(self):
47
+ self.obj.px = self.target_px
48
+ self.obj.py = self.target_py
49
+ self.obj.vx = self.obj.vy = 0.0
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ from typing import TYPE_CHECKING
5
+
6
+ from ...scripts.command import Command
7
+ from ...util.constants import ONEWAY_SPEED_BOOST
8
+
9
+ if TYPE_CHECKING:
10
+ from ...objects.dynamic import Dynamic
11
+ from ...types.player import Player
12
+
13
+
14
+ class CommandOnewayMove(Command):
15
+ def __init__(self, obj: Dynamic, vx: float, vy: float, player: Player):
16
+ super().__init__([player])
17
+
18
+ self.obj: Dynamic = obj
19
+ self.vx: float = vx
20
+ self.vy: float = vy
21
+ self.start_px: float = 0.0
22
+ self.start_py: float = 0.0
23
+ self.target_px: float = 0.0
24
+ self.target_py: float = 0.0
25
+ self.distance: float = 0.0
26
+
27
+ def start(self):
28
+ self.obj.solid_vs_map = False
29
+ self.obj.solid_vs_dyn = False
30
+ self.obj.vx = self.obj.vy = 0.0
31
+ self.obj.vz = 7.5
32
+
33
+ self.start_px = self.obj.px
34
+ self.start_py = self.obj.py
35
+ self.target_px = self.obj.px + self.vx
36
+ self.target_py = self.obj.py + self.vy
37
+
38
+ dx = self.target_px - self.start_px
39
+ dy = self.target_py - self.start_py
40
+ self.distance = math.sqrt(dx * dx + dy * dy)
41
+
42
+ def update(self, elapsed_time):
43
+ self.obj.px += self.vx * elapsed_time * ONEWAY_SPEED_BOOST
44
+ self.obj.py += self.vy * elapsed_time * ONEWAY_SPEED_BOOST
45
+
46
+ dx = self.obj.px - self.start_px
47
+ dy = self.obj.py - self.start_py
48
+ distance = math.sqrt(dx * dx + dy * dy)
49
+
50
+ if distance >= self.distance:
51
+ self.completed = True
52
+
53
+ def finalize(self):
54
+ self.obj.px = self.target_px
55
+ self.obj.py = self.target_py
56
+ self.obj.vx = self.obj.vy = 0.0
57
+ self.obj.solid_vs_dyn = True
58
+ self.obj.solid_vs_map = True
@@ -0,0 +1,66 @@
1
+ from typing import List, Optional
2
+
3
+ from ...types.player import Player
4
+ from ..command import Command
5
+
6
+
7
+ class CommandParallel(Command):
8
+ ALL_COMPLETED: int = 0
9
+ ANY_COMPLETED: int = 1
10
+ FIRST_COMPLETED: int = 2
11
+
12
+ def __init__(
13
+ self,
14
+ cmds: List[Command],
15
+ completed_when: int = ALL_COMPLETED,
16
+ players: Optional[List[Player]] = None,
17
+ ):
18
+ super().__init__()
19
+ self._cmds: List[Command] = cmds
20
+ self._completed_when: int = completed_when
21
+
22
+ def start(self):
23
+ for cmd in self._cmds:
24
+ cmd.start()
25
+
26
+ def update(self, delta_time):
27
+ for cmd in self._cmds:
28
+ cmd.update(delta_time)
29
+
30
+ if self._completed_when == self.ALL_COMPLETED:
31
+ self._check_for_all()
32
+ elif self._completed_when == self.ANY_COMPLETED:
33
+ self._check_for_any()
34
+ elif self._completed_when == self.FIRST_COMPLETED:
35
+ self._check_for_first()
36
+ else:
37
+ raise ValueError(
38
+ f"Unknown value {self._completed_when} for "
39
+ "attribute _completed_when"
40
+ )
41
+
42
+ def finalize(self):
43
+ for cmd in self._cmds:
44
+ cmd.finalize()
45
+
46
+ def _check_for_all(self):
47
+ completed = True
48
+ for cmd in self._cmds:
49
+ completed = completed and cmd.completed
50
+
51
+ self.completed = completed
52
+
53
+ def _check_for_any(self):
54
+ completed = False
55
+ for cmd in self._cmds:
56
+ completed = completed or cmd.completed
57
+
58
+ self.completed = completed
59
+
60
+ def _check_for_first(self):
61
+ self.completed = self._cmds[0].completed
62
+
63
+ def set_players(self, players: List[Player]):
64
+ self.players = players
65
+ for cmd in self._cmds:
66
+ cmd.set_players(players)
@@ -0,0 +1,13 @@
1
+ from ..command import Command
2
+
3
+
4
+ class CommandPlaySound(Command):
5
+ def __init__(self, sound: str, delay: float = 0.0):
6
+ super().__init__()
7
+
8
+ self._sound_to_play: str = sound
9
+ self._delay: float = delay
10
+
11
+ def start(self):
12
+ self.engine.audio.play_sound(self._sound_to_play, self._delay)
13
+ self.completed = True
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ from ...objects.projectile import Projectile
6
+ from ...scripts.command import Command
7
+ from ...types.graphic_state import GraphicState
8
+
9
+ if TYPE_CHECKING:
10
+ from ...objects.dynamic import Dynamic
11
+
12
+
13
+ class CommandPresentItem(Command):
14
+ def __init__(self, item_name: str, dynamic: Optional[Dynamic] = None):
15
+ super().__init__()
16
+
17
+ self._dynamic: Optional[Dynamic] = dynamic
18
+ self._item_name: str = item_name
19
+ self._item_sprite: Optional[Projectile] = None
20
+
21
+ def start(self):
22
+ if self._dynamic is None:
23
+ self._dynamic = self.engine.get_player(self.players[0])
24
+ item = self.engine.get_item(self._item_name)
25
+ self._item_sprite = Projectile(
26
+ self._dynamic.px,
27
+ self._dynamic.py - 1,
28
+ f"Present {item.name}",
29
+ sprite_name=item.sprite_name,
30
+ tilemap=self._dynamic.tilemap,
31
+ duration=3600,
32
+ alignment=self._dynamic.alignment,
33
+ )
34
+ self._item_sprite.layer = 2
35
+ # self._item_sprite.sprite.name = item.sprite_name
36
+ # self._item_sprite.sprite.ox = item.sprite_ox
37
+ # self._item_sprite.sprite.oy = item.sprite_oy
38
+ # self._item_sprite.sprite.width = item.sprite_width
39
+ # self._item_sprite.sprite.height = item.sprite_height
40
+ self._item_sprite.solid_vs_dyn = False
41
+ self._item_sprite.solid_vs_map = False
42
+ self._item_sprite.one_hit = False
43
+ self._item_sprite.damage = 0
44
+
45
+ self.engine.get_view().add_projectile(
46
+ self._item_sprite, self._dynamic.tilemap.name
47
+ )
48
+ self._dynamic.lock_graphic_state(GraphicState.CELEBRATING)
49
+ self.completed = True
50
+
51
+ def finalize(self):
52
+ self._item_sprite.kill()
53
+ self._dynamic.unlock_graphic_state()
@@ -0,0 +1,12 @@
1
+ from ..command import Command
2
+
3
+
4
+ class CommandProgressQuest(Command):
5
+ def __init__(self, quest_name: str, new_state: int):
6
+ super().__init__()
7
+ self._quest_name: str = quest_name
8
+ self._new_state: int = new_state
9
+
10
+ def start(self):
11
+ self.engine.progress_quest(self._quest_name, self._new_state)
12
+ self.completed = True
@@ -0,0 +1,8 @@
1
+ from ..command import Command
2
+
3
+
4
+ class CommandQuitGame(Command):
5
+ def start(self):
6
+ self.engine.game_state.save_to_disk(autosave=True)
7
+ self.engine.backend.terminate = True
8
+ self.completed = True
@@ -0,0 +1,14 @@
1
+ from ...scripts.command import Command
2
+
3
+
4
+ class CommandSaveGame(Command):
5
+ def start(self):
6
+ # print(self.engine.game_state._state["player"])
7
+ # print(self.engine.items)
8
+ for quest in self.engine.quests:
9
+ quest.save_state()
10
+ self.engine.game_state.save_to_disk()
11
+ self.completed = True
12
+ print(f"Saved the game to {self.engine.game_state.state_name}")
13
+
14
+ # print(self.engine.game_state._state["player"])
@@ -0,0 +1,83 @@
1
+ from typing import Optional
2
+
3
+ from ...objects.effects.colorize_screen import ColorizeScreen
4
+ from ...util.colors import BLACK, Color
5
+ from ..command import Command
6
+
7
+
8
+ class CommandScreenFade(Command):
9
+ def __init__(
10
+ self,
11
+ duration: float = 0.5,
12
+ color: Optional[Color] = None,
13
+ fadein: bool = False,
14
+ map_name: Optional[str] = None,
15
+ ):
16
+ super().__init__()
17
+
18
+ self.duration: float = duration
19
+ if color is None:
20
+ color = self.engine.rtc.color_black
21
+
22
+ self.color: Color = color
23
+ self.fadein: bool = fadein
24
+ self.time_so_far: float = 0.0
25
+ self._start: int = 0
26
+ self._end: int = 255
27
+ self._iter: int = 15
28
+
29
+ if fadein:
30
+ self._start = 255
31
+ self._end = 0
32
+ self._iter = -self._iter
33
+
34
+ self._map_name = map_name
35
+
36
+ self._effect: Optional[ColorizeScreen] = None
37
+ # self.duration -= 0.1
38
+
39
+ def start(self):
40
+
41
+ self._effect = ColorizeScreen(
42
+ cameras=[
43
+ self.engine.get_view().get_camera_name(p) for p in self.players
44
+ ]
45
+ )
46
+ self._effect.alpha = self._start
47
+ if self._map_name is None:
48
+ map_names = list(
49
+ set(
50
+ [
51
+ self.engine.get_player(p).tilemap.name
52
+ for p in self.players
53
+ ]
54
+ )
55
+ )
56
+ for map_name in map_names:
57
+ self.engine.get_view().add_effect(self._effect, map_name)
58
+ else:
59
+ self.engine.get_view().add_effect(self._effect, self._map_name)
60
+ for p in self.players:
61
+ self.engine.get_player(p).halt()
62
+
63
+ def update(self, elapsed_time: float):
64
+ self.time_so_far += elapsed_time
65
+
66
+ progress = self.time_so_far / self.duration
67
+
68
+ alpha = progress * 256
69
+ if self.fadein:
70
+ alpha = 255 - alpha
71
+
72
+ self._effect.alpha = min(255, max(0, alpha))
73
+
74
+ for p in self.players:
75
+ self.engine.get_player(p).halt()
76
+
77
+ if self.time_so_far >= self.duration:
78
+ self._effect.alpha = self._end
79
+ self.completed = True
80
+
81
+ def finalize(self):
82
+ self.completed = True
83
+ self._effect.kill()