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,231 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Dict, List, Optional
4
+
5
+ from ..types.position import Position
6
+ from ..types.window import Window
7
+ from ..util.colors import BLACK, WHITE
8
+ from ..util.constants import (
9
+ DIALOG_CHARS_PER_LINE,
10
+ DIALOG_HEIGHT,
11
+ DIALOG_N_LINES,
12
+ DIALOG_WIDTH,
13
+ )
14
+ from .camera import Camera
15
+ from .mima_view import MimaView
16
+ from .mima_window import MimaWindow
17
+
18
+ if TYPE_CHECKING:
19
+ from ..objects.dynamic import Dynamic
20
+ from ..types.player import Player
21
+
22
+
23
+ class MimaScene(MimaView):
24
+ def __init__(
25
+ self,
26
+ player: Player,
27
+ position: Position,
28
+ camera_name: Optional[str] = None,
29
+ ) -> None:
30
+ self.window_stack: List[Window] = []
31
+ self.windows: Dict[Window, MimaWindow] = {}
32
+ self._current_window: Optional[MimaWindow] = None
33
+ self.stack_changed = False
34
+ self.skip_draw_ui = False
35
+
36
+ self.player: Player = player
37
+ self._position: Position = position
38
+
39
+ self._camera_name: str = (
40
+ camera_name if camera_name is not None else f"C_{player.name}"
41
+ )
42
+ self._controls_camera_name: str = f"{self._camera_name}_CONTROLS"
43
+
44
+ self.camera: Camera
45
+ self.controls_camera: Camera
46
+ self._dialog_px: float
47
+ self._dialog_py: float
48
+ self._dialog_width: float = DIALOG_WIDTH
49
+ self._dialog_height: float = DIALOG_HEIGHT
50
+ self._dialog_spacing: float = 3 / self.engine.rtc.tile_height
51
+
52
+ self._dialog_text_color = BLACK
53
+ self._dialog_bg_color = WHITE
54
+
55
+ self.update_scene_position(self._position)
56
+
57
+ def update_scene_position(self, position: Position) -> None:
58
+ width = self.engine.backend.render_width / self.engine.rtc.tile_width
59
+ height = (
60
+ self.engine.backend.render_height / self.engine.rtc.tile_height
61
+ )
62
+ # print(f"Starting camera setup: {width}, {height}, {position}")
63
+ if position in (
64
+ Position.LEFT,
65
+ Position.RIGHT,
66
+ Position.TOP_LEFT,
67
+ Position.TOP_RIGHT,
68
+ Position.BOTTOM_LEFT,
69
+ Position.BOTTOM_RIGHT,
70
+ ):
71
+ width /= 2
72
+ self._dialog_px = 1
73
+ else:
74
+ self._dialog_px = width / 2 - self._dialog_width / 2
75
+
76
+ if position in (
77
+ Position.TOP,
78
+ Position.BOTTOM,
79
+ Position.TOP_LEFT,
80
+ Position.TOP_RIGHT,
81
+ Position.BOTTOM_LEFT,
82
+ Position.BOTTOM_RIGHT,
83
+ ):
84
+ height /= 2
85
+ self._dialog_py = height - 4
86
+ else:
87
+ self._dialog_py = height - 4
88
+
89
+ self.camera = Camera(self._camera_name, width, height)
90
+ # self.controls_camera = Camera(
91
+ # self._controls_camera_name, width, height
92
+ # )
93
+ if position == Position.CENTER:
94
+ # print(f"Camera setup finished: {width}, {height}")
95
+ return
96
+
97
+ if position in (
98
+ Position.RIGHT,
99
+ Position.BOTTOM_RIGHT,
100
+ Position.TOP_RIGHT,
101
+ ):
102
+ self.camera.px = self.engine.backend.render_width / 2
103
+ self.camera.border_left = True
104
+
105
+ if position in (
106
+ Position.BOTTOM,
107
+ Position.BOTTOM_LEFT,
108
+ Position.BOTTOM_RIGHT,
109
+ ):
110
+ self.camera.py = self.engine.backend.render_height / 2
111
+ self.camera.border_top = True
112
+
113
+ if position in (
114
+ Position.LEFT,
115
+ Position.TOP_LEFT,
116
+ Position.BOTTOM_LEFT,
117
+ ):
118
+ self.camera.border_right = True
119
+ self.camera.border_color = BLACK
120
+
121
+ if position in (Position.TOP, Position.TOP_LEFT, Position.TOP_RIGHT):
122
+ self.camera.border_bottom = True
123
+ self.camera.border_color = BLACK
124
+
125
+ def update(
126
+ self,
127
+ elapsed_time: float,
128
+ *,
129
+ target: Optional[Dynamic] = None,
130
+ map_width: int = 0,
131
+ map_height: int = 0,
132
+ ) -> bool:
133
+ self.update_window()
134
+
135
+ self.camera.update(target, map_width, map_height)
136
+ self.update_dialog_position()
137
+
138
+ # print(type(self._current_window))
139
+ return self._current_window.update(elapsed_time, self.camera)
140
+
141
+ def clear_stack(self, windows: Optional[List[Window]] = None):
142
+ self.stack_changed = True
143
+ if windows is not None:
144
+ self.window_stack = windows
145
+ else:
146
+ self.window_stack = []
147
+
148
+ def add_window(self, window: Window):
149
+ self.window_stack.append(window)
150
+ self.stack_changed = True
151
+
152
+ def pop_window(self):
153
+ self.stack_changed = True
154
+ return self.window_stack.pop()
155
+
156
+ def get_window(self) -> MimaWindow:
157
+ return self._current_window
158
+
159
+ def get_next_window_type(self) -> Window:
160
+ return self.window_stack[-1]
161
+
162
+ def get_previous_window_type(self) -> Window:
163
+ return self.window_stack[-2]
164
+
165
+ def handle_user_input(self):
166
+ if self._current_window is None:
167
+ self.update_window()
168
+ self._current_window.handle_user_input(self.player)
169
+
170
+ def draw_map_and_objects(
171
+ self, player, camera, tmap, dynamics, projectiles, effects
172
+ ) -> None:
173
+ self._current_window.draw_map_layers(tmap, [-1, 0])
174
+ self._current_window.draw_objects_y_sorted(
175
+ dynamics + projectiles, [-1, 0, 1, 2]
176
+ )
177
+
178
+ self._current_window.draw_effect_layers(effects, [0])
179
+
180
+ self._current_window.draw_map_layers(tmap, [1, 2])
181
+
182
+ self._current_window.draw_effect_layers(effects, [1, 2, 3, 4])
183
+
184
+ def draw_ui(self):
185
+ if self.skip_draw_ui:
186
+ self.skip_draw_ui = False
187
+ return
188
+ self._current_window.draw_ui()
189
+ self._current_window.draw_controls()
190
+
191
+ def draw_camera_border(self):
192
+ self.camera.draw_borders()
193
+
194
+ def load_window(self):
195
+ self._current_window.load(
196
+ self.engine.get_view().maps[self.player].name
197
+ )
198
+
199
+ def update_window(self):
200
+ old_window = self._current_window
201
+ self._current_window = self.windows[self.window_stack[-1]]
202
+ self._current_window.set_camera(self.camera)
203
+ self._current_window.set_player(self.player)
204
+
205
+ if self._current_window != old_window or self.stack_changed:
206
+ self.stack_changed = False
207
+ if old_window is not None:
208
+ old_window.on_exit_focus()
209
+
210
+ self._current_window.on_enter_focus()
211
+ self.skip_draw_ui = True
212
+
213
+ def update_dialog_position(self):
214
+ self._dialog_px = (
215
+ self.camera.visible_tiles_ex - self._dialog_width
216
+ ) / 2
217
+ self._dialog_py = (
218
+ self.camera.visible_tiles_ey - self._dialog_height - 1
219
+ )
220
+
221
+ def display_dialog(self, lines):
222
+ self._current_window.display_dialog(
223
+ lines,
224
+ int(self._dialog_px * self.engine.rtc.tile_width),
225
+ int(self._dialog_py * self.engine.rtc.tile_height),
226
+ int(self._dialog_width * self.engine.rtc.tile_width),
227
+ int(self._dialog_height * self.engine.rtc.tile_height),
228
+ int(self._dialog_spacing * self.engine.rtc.tile_height),
229
+ self._dialog_text_color,
230
+ self._dialog_bg_color,
231
+ )
mima/view/mima_view.py ADDED
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from ..engine import MimaEngine
7
+
8
+
9
+ class MimaView:
10
+ """Base class for all view related classes."""
11
+
12
+ engine: MimaEngine
@@ -0,0 +1,244 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any, List, Optional
4
+
5
+ from ..types.direction import Direction
6
+ from ..types.keys import Key as K
7
+ from ..types.player import Player
8
+ from ..types.window import Window
9
+ from ..util.colors import TRANS_CYAN, TRANS_LIGHT_RED
10
+ from ..util.constants import BIG_FONT_HEIGHT, BIG_FONT_WIDTH
11
+ from ..util.functions import wrap_text
12
+ from .mima_view import MimaView
13
+
14
+ if TYPE_CHECKING:
15
+ from ..maps.tilemap import Tilemap
16
+ from ..objects.dynamic import Dynamic
17
+ from ..util.colors import Color
18
+ from .camera import Camera
19
+ from .mima_mode import MimaMode
20
+ from .mima_scene import MimaScene
21
+
22
+
23
+ class MimaWindow(MimaView):
24
+ def __init__(
25
+ self,
26
+ mode: MimaMode,
27
+ scene: MimaScene,
28
+ wtype: Window = Window.PLACEHOLDER,
29
+ ) -> None:
30
+ self.mode = mode
31
+ self.scene = scene
32
+ self.wtype = wtype
33
+
34
+ self.p_obj: Optional[Dynamic] = None
35
+ self.camera: Optional[Camera] = None
36
+ self.dialog_to_show: List[str] = []
37
+ self.additional_data: Optional[Any] = None
38
+
39
+ def on_enter_focus(self):
40
+ pass
41
+
42
+ def on_exit_focus(self):
43
+ pass
44
+
45
+ def update(self, elapsed_time: float, camera: Camera) -> bool:
46
+ return True
47
+
48
+ def handle_user_input(self, player: Player) -> None:
49
+ self.p_obj.vx = self.p_obj.vy = 0
50
+
51
+ if self.engine.keys.key_held(K.UP, player):
52
+ self.p_obj.vy = -1
53
+ self.p_obj.facing_direction = Direction.NORTH
54
+ if self.engine.keys.key_held(K.DOWN, player):
55
+ self.p_obj.vy = 1
56
+ self.p_obj.facing_direction = Direction.SOUTH
57
+ if self.engine.keys.key_held(K.LEFT, player):
58
+ self.p_obj.vx = -1
59
+ self.p_obj.facing_direction = Direction.WEST
60
+ if self.engine.keys.key_held(K.RIGHT, player):
61
+ self.p_obj.vx = 1
62
+ self.p_obj.facing_direction = Direction.EAST
63
+
64
+ def draw_map_layers(self, tilemap: Tilemap, layers: List[int]) -> None:
65
+ for pos in layers:
66
+ tilemap.draw_self(
67
+ self.camera.ox,
68
+ self.camera.oy,
69
+ self.camera.visible_tiles_sx,
70
+ self.camera.visible_tiles_sy,
71
+ self.camera.visible_tiles_ex,
72
+ self.camera.visible_tiles_ey,
73
+ pos,
74
+ self.camera.name,
75
+ )
76
+
77
+ def draw_objects_y_sorted(
78
+ self, objects: List[Dynamic], layers: Optional[List[int]] = None
79
+ ) -> None:
80
+ layers = layers if layers is not None else list(range(-3, 3))
81
+
82
+ y_sorted = sorted(objects, key=lambda obj: obj.py)
83
+ for layer in layers:
84
+ for obj in y_sorted:
85
+ if self._check_draw_object(obj, layer):
86
+ # print(
87
+ # obj.px,
88
+ # obj.py,
89
+ # obj.name,
90
+ # self._camera.name,
91
+ # self._camera.ox,
92
+ # self._camera.oy,
93
+ # )
94
+ obj.draw_self(
95
+ self.camera.ox, self.camera.oy, self.camera.name
96
+ )
97
+ if self.engine.draw_dyn_ids:
98
+ self.engine.backend.draw_small_text(
99
+ f"{obj.dyn_id}",
100
+ (obj.px - self.camera.ox)
101
+ * self.engine.rtc.tile_width,
102
+ (obj.py - self.camera.oy) * obj.sprite.height
103
+ + obj.sprite.height,
104
+ self.engine.rtc.color_red,
105
+ self.camera.name,
106
+ )
107
+
108
+ def draw_effect_layers(
109
+ self, effects: List[Dynamic], layers: List[int]
110
+ ) -> None:
111
+ for layer in layers:
112
+ for effect in effects:
113
+ if effect.layer == layer:
114
+ effect.draw_self(
115
+ self.camera.ox, self.camera.oy, self.camera.name
116
+ )
117
+
118
+ def _check_draw_object(self, obj, layer) -> bool:
119
+ if obj.redundant or not obj.visible or obj.layer != layer:
120
+ return False
121
+
122
+ return self.check_draw_object(obj, layer)
123
+
124
+ def check_draw_object(self, obj, layer) -> bool:
125
+ """Custom check if object should be drawn."""
126
+ return True
127
+
128
+ def draw_ui(self) -> None:
129
+ pass
130
+
131
+ def draw_controls(self) -> None:
132
+ if not self.engine.show_touch_controls:
133
+ return
134
+
135
+ state = self.engine.keys.get_touch_state()
136
+ if not state:
137
+ return
138
+
139
+ data_move = state[K.UP]
140
+ if data_move["active"]:
141
+ radius = self.engine.rtc.tile_width
142
+ self.engine.backend.draw_circle(
143
+ int(data_move["rsx"] * self.camera.pwidth),
144
+ int(data_move["rsy"] * self.camera.pheight),
145
+ radius,
146
+ TRANS_LIGHT_RED,
147
+ self.camera.name,
148
+ draw_to_ui=True,
149
+ )
150
+ self.engine.backend.fill_circle(
151
+ int(data_move["rpx"] * self.camera.pwidth),
152
+ int(data_move["rpy"] * self.camera.pheight),
153
+ radius,
154
+ TRANS_LIGHT_RED,
155
+ self.camera.name,
156
+ draw_to_ui=True,
157
+ )
158
+
159
+ for idx in range(4, 12):
160
+ key = K(idx)
161
+ data = state.get(key, {})
162
+ if not data:
163
+ continue
164
+ # print(data_a)
165
+
166
+ ppx = int(data["rpx"] * self.camera.pwidth)
167
+ ppy = int(data["rpy"] * self.camera.pheight)
168
+ pwidth = int(data["rwidth"] * self.camera.pwidth)
169
+ pheight = int(data["rheight"] * self.camera.pheight)
170
+ if data["active"]:
171
+ self.engine.backend.fill_rect(
172
+ ppx,
173
+ ppy,
174
+ pwidth,
175
+ pheight,
176
+ TRANS_LIGHT_RED,
177
+ self.camera.name,
178
+ draw_to_ui=True,
179
+ )
180
+ else:
181
+ self.engine.backend.draw_rect(
182
+ ppx,
183
+ ppy,
184
+ pwidth,
185
+ pheight,
186
+ TRANS_LIGHT_RED,
187
+ self.camera.name,
188
+ draw_to_ui=True,
189
+ )
190
+ text = key.name
191
+ text_width = len(text) * BIG_FONT_WIDTH
192
+ self.engine.backend.draw_big_text(
193
+ text,
194
+ int(ppx + pwidth / 2 - text_width / 2),
195
+ int(ppy + pheight / 2 - BIG_FONT_HEIGHT / 2),
196
+ TRANS_LIGHT_RED,
197
+ self.camera.name,
198
+ draw_to_ui=True,
199
+ )
200
+
201
+ # self.engine.backend.fill_circle(
202
+ # int(data_a["px"] * self.camera.pwidth),
203
+ # int(data_a["py"] * self.camera.pheight),
204
+ # int(data_a["width"] * self.camera.pwidth / 2),
205
+ # color,
206
+ # self.camera.name,
207
+ # draw_to_ui=True,
208
+ # )
209
+
210
+ def set_camera(self, camera: Camera):
211
+ self.camera = camera
212
+
213
+ def set_player(self, player: Player):
214
+ self.p_obj = self.engine.get_player(player)
215
+
216
+ def display_dialog(
217
+ self,
218
+ lines: List[str],
219
+ ppx: int,
220
+ ppy: int,
221
+ pwidth: int,
222
+ pheight: int,
223
+ pspacing: int,
224
+ text_color: Color,
225
+ bg_color: Color,
226
+ ):
227
+ self.engine.backend.fill_rect(
228
+ ppx, ppy, pwidth, pheight, bg_color, self.camera.name
229
+ )
230
+ self.engine.backend.draw_rect(
231
+ ppx, ppy, pwidth, pheight, text_color, self.camera.name
232
+ )
233
+ # print(ppx, ppy, pwidth, pheight, lines)
234
+ for idx, line in enumerate(lines):
235
+ self.engine.backend.draw_big_text(
236
+ line,
237
+ ppx + 4,
238
+ ppy
239
+ + 4
240
+ + idx * pspacing
241
+ + idx * self.engine.rtc.big_font_height,
242
+ text_color,
243
+ self.camera.name,
244
+ )
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: mima-engine
3
+ Version: 0.4.0
4
+ Summary: A game engine based on pygame.
5
+ Author-email: Stephan Balduin <stephan.balduin@mailbox.org>
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Programming Language :: Python :: 3
8
+ Requires-Python: >=3.10
9
+ Provides-Extra: ce
10
+ Requires-Dist: pygame-ce; extra == 'ce'
11
+ Provides-Extra: dev
12
+ Requires-Dist: build; extra == 'dev'
13
+ Requires-Dist: pygame-ce; extra == 'dev'
14
+ Requires-Dist: pytest; extra == 'dev'
15
+ Requires-Dist: twine; extra == 'dev'
16
+ Provides-Extra: pygame
17
+ Requires-Dist: pygame; extra == 'pygame'
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Mima Engine
21
+
22
+ A game engine based on pygame.
23
+
24
+ ## Design Philosophy
25
+
26
+ **standalone**:
27
+ - zero architectural assumptions
28
+ - suitable for any pygame project
29
+ - copy-paste friendly
30
+
31
+ **layered**:
32
+ - introduces preferred patterns
33
+ - assumes common game-loop structures
34
+ - flexible but guided usage
35
+
36
+ **integrated**:
37
+ - opinionated systems
38
+ - assumes specific data flow and lifecycle
39
+ - intended for projects that opt into this style
40
+
41
+ | Module | Internal Imports | Copy-Paste Safe | Intended Use |
42
+ | ---------- | ---------------- | --------------- | ------------------ |
43
+ | standalone | none | yes | drop-in utilities |
44
+ | layered | shallow | usually | enhanced helpers |
45
+ | integrated | deep | no | full library usage |
46
+
47
+