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.
- mima/__init__.py +4 -0
- mima/backend/__init__.py +1 -0
- mima/backend/pygame_assets.py +401 -0
- mima/backend/pygame_audio.py +78 -0
- mima/backend/pygame_backend.py +603 -0
- mima/backend/pygame_camera.py +63 -0
- mima/backend/pygame_events.py +695 -0
- mima/backend/touch_control_scheme_a.py +126 -0
- mima/backend/touch_control_scheme_b.py +132 -0
- mima/core/__init__.py +0 -0
- mima/core/collision.py +325 -0
- mima/core/database.py +58 -0
- mima/core/engine.py +367 -0
- mima/core/mode_engine.py +81 -0
- mima/core/scene_engine.py +81 -0
- mima/integrated/__init__.py +0 -0
- mima/integrated/entity.py +183 -0
- mima/integrated/layered_map.py +351 -0
- mima/integrated/sprite.py +156 -0
- mima/layered/__init__.py +0 -0
- mima/layered/assets.py +56 -0
- mima/layered/scene.py +415 -0
- mima/layered/shape.py +99 -0
- mima/layered/shaped_sprite.py +78 -0
- mima/layered/virtual_input.py +302 -0
- mima/maps/__init__.py +0 -0
- mima/maps/template.py +71 -0
- mima/maps/tile.py +20 -0
- mima/maps/tile_animation.py +7 -0
- mima/maps/tile_info.py +10 -0
- mima/maps/tile_layer.py +52 -0
- mima/maps/tiled/__init__.py +0 -0
- mima/maps/tiled/tiled_layer.py +48 -0
- mima/maps/tiled/tiled_map.py +95 -0
- mima/maps/tiled/tiled_object.py +79 -0
- mima/maps/tiled/tiled_objectgroup.py +25 -0
- mima/maps/tiled/tiled_template.py +49 -0
- mima/maps/tiled/tiled_tile.py +90 -0
- mima/maps/tiled/tiled_tileset.py +51 -0
- mima/maps/tilemap.py +216 -0
- mima/maps/tileset.py +39 -0
- mima/maps/tileset_info.py +9 -0
- mima/maps/transition_map.py +146 -0
- mima/objects/__init__.py +0 -0
- mima/objects/animated_sprite.py +217 -0
- mima/objects/attribute_effect.py +26 -0
- mima/objects/attributes.py +126 -0
- mima/objects/creature.py +384 -0
- mima/objects/dynamic.py +206 -0
- mima/objects/effects/__init__.py +0 -0
- mima/objects/effects/colorize_screen.py +60 -0
- mima/objects/effects/debug_box.py +133 -0
- mima/objects/effects/light.py +103 -0
- mima/objects/effects/show_sprite.py +50 -0
- mima/objects/effects/walking_on_grass.py +70 -0
- mima/objects/effects/walking_on_water.py +57 -0
- mima/objects/loader.py +111 -0
- mima/objects/projectile.py +111 -0
- mima/objects/sprite.py +116 -0
- mima/objects/world/__init__.py +0 -0
- mima/objects/world/color_gate.py +67 -0
- mima/objects/world/color_switch.py +101 -0
- mima/objects/world/container.py +175 -0
- mima/objects/world/floor_switch.py +109 -0
- mima/objects/world/gate.py +178 -0
- mima/objects/world/light_source.py +121 -0
- mima/objects/world/logic_gate.py +157 -0
- mima/objects/world/movable.py +399 -0
- mima/objects/world/oneway.py +195 -0
- mima/objects/world/pickup.py +157 -0
- mima/objects/world/switch.py +179 -0
- mima/objects/world/teleport.py +308 -0
- mima/py.typed +0 -0
- mima/scripts/__init__.py +2 -0
- mima/scripts/command.py +38 -0
- mima/scripts/commands/__init__.py +0 -0
- mima/scripts/commands/add_quest.py +19 -0
- mima/scripts/commands/change_map.py +34 -0
- mima/scripts/commands/close_dialog.py +9 -0
- mima/scripts/commands/equip_weapon.py +23 -0
- mima/scripts/commands/give_item.py +26 -0
- mima/scripts/commands/give_resource.py +51 -0
- mima/scripts/commands/move_map.py +152 -0
- mima/scripts/commands/move_to.py +49 -0
- mima/scripts/commands/oneway_move.py +58 -0
- mima/scripts/commands/parallel.py +66 -0
- mima/scripts/commands/play_sound.py +13 -0
- mima/scripts/commands/present_item.py +53 -0
- mima/scripts/commands/progress_quest.py +12 -0
- mima/scripts/commands/quit_game.py +8 -0
- mima/scripts/commands/save_game.py +14 -0
- mima/scripts/commands/screen_fade.py +83 -0
- mima/scripts/commands/serial.py +69 -0
- mima/scripts/commands/set_facing_direction.py +21 -0
- mima/scripts/commands/set_spawn_map.py +17 -0
- mima/scripts/commands/show_choices.py +52 -0
- mima/scripts/commands/show_dialog.py +118 -0
- mima/scripts/commands/take_coins.py +23 -0
- mima/scripts/script_processor.py +61 -0
- mima/standalone/__init__.py +0 -0
- mima/standalone/camera.py +153 -0
- mima/standalone/geometry.py +1318 -0
- mima/standalone/multicolumn_list.py +54 -0
- mima/standalone/pixel_font.py +84 -0
- mima/standalone/scripting.py +145 -0
- mima/standalone/spatial.py +186 -0
- mima/standalone/sprite.py +158 -0
- mima/standalone/tiled_map.py +1247 -0
- mima/standalone/transformed_view.py +433 -0
- mima/standalone/user_input.py +563 -0
- mima/states/__init__.py +0 -0
- mima/states/game_state.py +189 -0
- mima/states/memory.py +28 -0
- mima/states/quest.py +71 -0
- mima/types/__init__.py +0 -0
- mima/types/alignment.py +7 -0
- mima/types/blend.py +8 -0
- mima/types/damage.py +42 -0
- mima/types/direction.py +44 -0
- mima/types/gate_color.py +7 -0
- mima/types/graphic_state.py +23 -0
- mima/types/keys.py +64 -0
- mima/types/mode.py +9 -0
- mima/types/nature.py +12 -0
- mima/types/object.py +22 -0
- mima/types/player.py +9 -0
- mima/types/position.py +13 -0
- mima/types/start.py +7 -0
- mima/types/terrain.py +9 -0
- mima/types/tile_collision.py +11 -0
- mima/types/weapon_slot.py +6 -0
- mima/types/window.py +44 -0
- mima/usables/__init__.py +0 -0
- mima/usables/item.py +51 -0
- mima/usables/weapon.py +68 -0
- mima/util/__init__.py +1 -0
- mima/util/colors.py +50 -0
- mima/util/constants.py +55 -0
- mima/util/functions.py +38 -0
- mima/util/input_defaults.py +170 -0
- mima/util/logging.py +51 -0
- mima/util/property.py +8 -0
- mima/util/runtime_config.py +327 -0
- mima/util/trading_item.py +23 -0
- mima/view/__init__.py +0 -0
- mima/view/camera.py +192 -0
- mima/view/mima_mode.py +618 -0
- mima/view/mima_scene.py +231 -0
- mima/view/mima_view.py +12 -0
- mima/view/mima_window.py +244 -0
- mima_engine-0.4.0.dist-info/METADATA +47 -0
- mima_engine-0.4.0.dist-info/RECORD +153 -0
- mima_engine-0.4.0.dist-info/WHEEL +4 -0
mima/view/mima_scene.py
ADDED
|
@@ -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
mima/view/mima_window.py
ADDED
|
@@ -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
|
+
|