mima-engine 0.2.3__py3-none-any.whl → 0.2.5__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.
Potentially problematic release.
This version of mima-engine might be problematic. Click here for more details.
- mima/__init__.py +1 -1
- mima/backend/pygame_backend.py +4 -1
- mima/backend/pygame_events.py +210 -194
- mima/backend/touch_control_scheme_a.py +126 -0
- mima/backend/touch_control_scheme_b.py +132 -0
- mima/core/collision.py +46 -23
- mima/core/engine.py +33 -14
- mima/core/mode_engine.py +7 -2
- mima/objects/creature.py +9 -3
- mima/objects/effects/debug_box.py +11 -2
- mima/objects/world/container.py +1 -1
- mima/objects/world/oneway.py +34 -8
- mima/objects/world/pickup.py +8 -2
- mima/objects/world/switch.py +20 -4
- mima/scripts/commands/oneway_move.py +4 -3
- mima/scripts/commands/save_game.py +1 -0
- mima/states/game_state.py +60 -35
- mima/util/constants.py +5 -3
- mima/util/input_defaults.py +12 -0
- mima/view/mima_mode.py +60 -19
- mima/view/mima_scene.py +6 -0
- mima/view/mima_window.py +91 -0
- {mima_engine-0.2.3.dist-info → mima_engine-0.2.5.dist-info}/METADATA +2 -2
- {mima_engine-0.2.3.dist-info → mima_engine-0.2.5.dist-info}/RECORD +26 -24
- {mima_engine-0.2.3.dist-info → mima_engine-0.2.5.dist-info}/WHEEL +1 -1
- {mima_engine-0.2.3.dist-info → mima_engine-0.2.5.dist-info}/top_level.txt +0 -0
|
@@ -8,11 +8,12 @@ from ...util.constants import ONEWAY_SPEED_BOOST
|
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from ...objects.dynamic import Dynamic
|
|
11
|
+
from ...types.player import Player
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class CommandOnewayMove(Command):
|
|
14
|
-
def __init__(self, obj: Dynamic, vx: float, vy: float):
|
|
15
|
-
super().__init__()
|
|
15
|
+
def __init__(self, obj: Dynamic, vx: float, vy: float, player: Player):
|
|
16
|
+
super().__init__([player])
|
|
16
17
|
|
|
17
18
|
self.obj: Dynamic = obj
|
|
18
19
|
self.vx: float = vx
|
|
@@ -27,7 +28,7 @@ class CommandOnewayMove(Command):
|
|
|
27
28
|
self.obj.solid_vs_map = False
|
|
28
29
|
self.obj.solid_vs_dyn = False
|
|
29
30
|
self.obj.vx = self.obj.vy = 0.0
|
|
30
|
-
self.obj.vz =
|
|
31
|
+
self.obj.vz = 7.5
|
|
31
32
|
|
|
32
33
|
self.start_px = self.obj.px
|
|
33
34
|
self.start_py = self.obj.py
|
mima/states/game_state.py
CHANGED
|
@@ -2,19 +2,21 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
4
|
from os import PathLike
|
|
5
|
-
from
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Dict, Union
|
|
6
7
|
|
|
8
|
+
# from typing_extensions import overload
|
|
9
|
+
from ..util.constants import SAVE_FILE_NAME
|
|
7
10
|
from ..util.functions import strtobool
|
|
8
11
|
|
|
9
12
|
LOG = logging.getLogger(__name__)
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class GameState:
|
|
13
|
-
def __init__(self,
|
|
14
|
-
self.
|
|
15
|
-
self.
|
|
16
|
-
|
|
17
|
-
}
|
|
16
|
+
def __init__(self, save_path: PathLike, state_name: str = "autosave.json"):
|
|
17
|
+
self.state_name = state_name
|
|
18
|
+
self._save_path = save_path
|
|
19
|
+
self._state: Dict[str, Any] = {}
|
|
18
20
|
|
|
19
21
|
def save_value(
|
|
20
22
|
self, key: str, value: Union[int, float, bool, str, dict, list]
|
|
@@ -27,12 +29,22 @@ class GameState:
|
|
|
27
29
|
else:
|
|
28
30
|
state[part] = value
|
|
29
31
|
|
|
32
|
+
# @overload
|
|
33
|
+
# def load_value(
|
|
34
|
+
# self, key: str, default: str, astype: str | None
|
|
35
|
+
# ) -> str | None: ...
|
|
36
|
+
|
|
37
|
+
# @overload
|
|
38
|
+
# def load_value(
|
|
39
|
+
# self, key: str, default: int, astype: str | None
|
|
40
|
+
# ) -> int | None: ...
|
|
41
|
+
|
|
30
42
|
def load_value(
|
|
31
43
|
self,
|
|
32
44
|
key: str,
|
|
33
|
-
default:
|
|
34
|
-
astype:
|
|
35
|
-
) ->
|
|
45
|
+
default: int | float | bool | str | dict | list | None = None,
|
|
46
|
+
astype: str | None = None,
|
|
47
|
+
) -> int | float | bool | str | dict | list | None:
|
|
36
48
|
parts = key.split("__")
|
|
37
49
|
state = self._state
|
|
38
50
|
for idx, part in enumerate(parts):
|
|
@@ -57,11 +69,11 @@ class GameState:
|
|
|
57
69
|
return data
|
|
58
70
|
|
|
59
71
|
def load_from_disk(self, autosave: bool = False):
|
|
60
|
-
filename = self.filename
|
|
61
|
-
if autosave:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
# filename = self.filename
|
|
73
|
+
# if autosave:
|
|
74
|
+
# filename = os.path.join(self._save_path, "autosave.json")
|
|
75
|
+
# else:
|
|
76
|
+
filename = Path(self._save_path) / self.state_name
|
|
65
77
|
try:
|
|
66
78
|
with open(filename, "r") as fp:
|
|
67
79
|
self._state = json.load(fp)
|
|
@@ -71,32 +83,33 @@ class GameState:
|
|
|
71
83
|
LOG.info("No saved state found or state corrupted.")
|
|
72
84
|
|
|
73
85
|
if autosave:
|
|
74
|
-
self.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
self.state_name = self.load_value("savefile_name", "")
|
|
87
|
+
# if autosave:
|
|
88
|
+
# self.filename = os.path.join(
|
|
89
|
+
# os.path.split(filename)[0],
|
|
90
|
+
# f"{self._state['savefile_name']}.json",
|
|
91
|
+
# )
|
|
78
92
|
|
|
79
93
|
def save_to_disk(self, autosave: bool = False):
|
|
80
|
-
filename = self.filename
|
|
94
|
+
# filename = self.filename
|
|
81
95
|
if autosave:
|
|
82
|
-
filename =
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
self.save_value("savefile_name", "autosave")
|
|
96
|
+
filename = Path(self._save_path) / "autosave.json"
|
|
97
|
+
self.save_value("savefile_name", self.state_name)
|
|
86
98
|
self.save_value("player__pos_x", 5.0)
|
|
87
99
|
self.save_value("player__pos_y", 5.0)
|
|
88
100
|
self.save_value(
|
|
89
101
|
"player__map_name", self.load_value("player__spawn_map")
|
|
90
102
|
)
|
|
91
103
|
else:
|
|
92
|
-
self.
|
|
93
|
-
|
|
94
|
-
|
|
104
|
+
if self.state_name == "autosave.json":
|
|
105
|
+
self.state_name = chose_filename(self._save_path)
|
|
106
|
+
self.save_value("savefile_name", self.state_name)
|
|
107
|
+
filename = Path(self._save_path) / self.state_name
|
|
108
|
+
self._state["savefile_name"] = self.state_name
|
|
109
|
+
|
|
95
110
|
# Auto save file will be removed after a successful save
|
|
96
111
|
try:
|
|
97
|
-
os.remove(
|
|
98
|
-
os.path.join(os.path.split(filename)[0], "autosave.json")
|
|
99
|
-
)
|
|
112
|
+
os.remove(Path(self._save_path) / "autosave.json")
|
|
100
113
|
except FileNotFoundError:
|
|
101
114
|
pass
|
|
102
115
|
|
|
@@ -112,6 +125,17 @@ class GameState:
|
|
|
112
125
|
del self._state[scope][k]
|
|
113
126
|
|
|
114
127
|
|
|
128
|
+
def chose_filename(save_path: PathLike):
|
|
129
|
+
|
|
130
|
+
files = os.listdir(save_path)
|
|
131
|
+
game_idx = 0
|
|
132
|
+
while True:
|
|
133
|
+
savegame = f"{SAVE_FILE_NAME}_{game_idx:03d}.json"
|
|
134
|
+
if savegame not in files:
|
|
135
|
+
return savegame
|
|
136
|
+
game_idx += 1
|
|
137
|
+
|
|
138
|
+
|
|
115
139
|
def convert(value, astype):
|
|
116
140
|
if astype == "int":
|
|
117
141
|
try:
|
|
@@ -144,17 +168,18 @@ def load_saved_games(save_path, save_file_name):
|
|
|
144
168
|
return all_games
|
|
145
169
|
|
|
146
170
|
if "autosave.json" in files:
|
|
147
|
-
all_games["autosave"] = GameState(
|
|
148
|
-
|
|
171
|
+
all_games["autosave.json"] = GameState(save_path)
|
|
172
|
+
all_games["autosave.json"].load_from_disk(autosave=True)
|
|
173
|
+
LOG.debug(
|
|
174
|
+
"Loading saved game from autosave.json (%s)",
|
|
175
|
+
all_games["autosave.json"].state_name,
|
|
149
176
|
)
|
|
150
|
-
all_games["autosave"].load_from_disk(autosave=True)
|
|
151
|
-
LOG.debug("Loading saved game from autosave.json")
|
|
152
177
|
|
|
153
178
|
game_idx = 0
|
|
154
179
|
while True:
|
|
155
|
-
savegame = f"{save_file_name}{game_idx:03d}.json"
|
|
180
|
+
savegame = f"{save_file_name}_{game_idx:03d}.json"
|
|
156
181
|
if savegame in files:
|
|
157
|
-
all_games[savegame] = GameState(
|
|
182
|
+
all_games[savegame] = GameState(save_path, savegame)
|
|
158
183
|
all_games[savegame].load_from_disk()
|
|
159
184
|
LOG.debug(f"Loading saved game from {savegame}")
|
|
160
185
|
game_idx += 1
|
mima/util/constants.py
CHANGED
|
@@ -10,8 +10,8 @@ UI_HIGHT: int = 1 # TODO: remove
|
|
|
10
10
|
# Map transition
|
|
11
11
|
MOVE_MAP_DURATION: float = 1.0
|
|
12
12
|
MAP_TRANSITION_DURATION_FACTOR: float = 0.75
|
|
13
|
-
ONEWAY_ACTIVATION_DELAY: float = 0.
|
|
14
|
-
ONEWAY_SPEED_BOOST: float = 2.
|
|
13
|
+
ONEWAY_ACTIVATION_DELAY: float = 0.075
|
|
14
|
+
ONEWAY_SPEED_BOOST: float = 2.5
|
|
15
15
|
|
|
16
16
|
# Gamepad
|
|
17
17
|
AXIS_DEADZONE: float = 0.25
|
|
@@ -38,7 +38,7 @@ DEFAULT_GRAPHIC_TIMER_DAMAGED: float = 0.075
|
|
|
38
38
|
DEFAULT_GRAPHIC_TIMER_DEAD: float = 0.25
|
|
39
39
|
DEFAULT_GRAPHIC_TIMER: float = 0.5
|
|
40
40
|
ATTRIBUTE_TIMER: float = 0.25
|
|
41
|
-
DEFAULT_KNOCK_SPEED: float =
|
|
41
|
+
DEFAULT_KNOCK_SPEED: float = 6.0
|
|
42
42
|
|
|
43
43
|
# Gameplay
|
|
44
44
|
ABYSS_DAMAGE: int = 1
|
|
@@ -51,3 +51,5 @@ DIALOG_WIDTH: float = 14.0
|
|
|
51
51
|
DIALOG_HEIGHT: float = 3.0
|
|
52
52
|
DIALOG_CHARS_PER_LINE: int = 36
|
|
53
53
|
DIALOG_N_LINES: int = 4
|
|
54
|
+
|
|
55
|
+
SAVE_FILE_NAME = "savegame"
|
mima/util/input_defaults.py
CHANGED
|
@@ -156,3 +156,15 @@ DEFAULT_TOUCHSCREEN_MAP = {
|
|
|
156
156
|
K.P1_B: [[0.5, 0.5], [0.75, 1.0]],
|
|
157
157
|
K.P1_A: [[0.75, 0.5], [1.0, 1.0]],
|
|
158
158
|
}
|
|
159
|
+
|
|
160
|
+
ALT_TOUCHSCREEN_MAP = {
|
|
161
|
+
K.P1_UP: {"pos": [0.1, 0.2], "size": [0.4, 0.7]},
|
|
162
|
+
K.P1_A: {"pos": [0.83, 0.84], "size": [0.12, 0.12]},
|
|
163
|
+
K.P1_B: {"pos": [0.70, 0.84], "size": [0.12, 0.12]},
|
|
164
|
+
K.P1_X: {"pos": [0.76, 0.69], "size": [0.12, 0.12]},
|
|
165
|
+
K.P1_Y: {"pos": [0.63, 0.69], "size": [0.12, 0.12]},
|
|
166
|
+
K.P1_START: {"pos": [0.39, 0.02], "size": [0.1, 0.1]},
|
|
167
|
+
K.P1_SELECT: {"pos": [0.51, 0.02], "size": [0.1, 0.1]},
|
|
168
|
+
K.P1_L: {"pos": [0.01, 0.3], "size": [0.05, 0.4]},
|
|
169
|
+
K.P1_R: {"pos": [0.94, 0.3], "size": [0.05, 0.4]},
|
|
170
|
+
}
|
mima/view/mima_mode.py
CHANGED
|
@@ -90,7 +90,9 @@ class MimaMode(MimaView):
|
|
|
90
90
|
def get_camera_name(self, player: Player = Player.P1):
|
|
91
91
|
return self.scenes[player].camera.name
|
|
92
92
|
|
|
93
|
-
def unload_map(
|
|
93
|
+
def unload_map(
|
|
94
|
+
self, player: Player = Player.P1, player_only: bool = False
|
|
95
|
+
) -> None:
|
|
94
96
|
p_obj = self.engine.memory.player[player]
|
|
95
97
|
map_name = p_obj.tilemap.name
|
|
96
98
|
|
|
@@ -139,12 +141,15 @@ class MimaMode(MimaView):
|
|
|
139
141
|
) -> None:
|
|
140
142
|
p_obj = self.engine.get_player(player)
|
|
141
143
|
p_obj.stop_shining()
|
|
144
|
+
p_obj.on_exit_map()
|
|
142
145
|
|
|
143
146
|
if map_name not in self.players_on_map:
|
|
144
147
|
# Map not loaded
|
|
145
148
|
self.prepare_object_lists(map_name, player, p_obj)
|
|
146
149
|
|
|
147
|
-
self._loader.populate_dynamics(
|
|
150
|
+
self._loader.populate_dynamics(
|
|
151
|
+
self.maps[player], self.dynamics[map_name]
|
|
152
|
+
)
|
|
148
153
|
|
|
149
154
|
for quest in self.engine.memory.quests:
|
|
150
155
|
quest.populate_dynamics(self.dynamics[map_name], map_name)
|
|
@@ -161,6 +166,7 @@ class MimaMode(MimaView):
|
|
|
161
166
|
p_obj.tilemap = self.maps[player]
|
|
162
167
|
p_obj.px = px
|
|
163
168
|
p_obj.py = py
|
|
169
|
+
p_obj.on_enter_map()
|
|
164
170
|
self.engine.memory.last_spawn_px[player] = px
|
|
165
171
|
self.engine.memory.last_spawn_py[player] = py
|
|
166
172
|
|
|
@@ -185,7 +191,9 @@ class MimaMode(MimaView):
|
|
|
185
191
|
chunks_per_row,
|
|
186
192
|
)
|
|
187
193
|
if self.engine.draw_chunk_info:
|
|
188
|
-
self.add_effect(
|
|
194
|
+
self.add_effect(
|
|
195
|
+
DynamicDebugBox(obj, n_frames=-1), map_name
|
|
196
|
+
)
|
|
189
197
|
|
|
190
198
|
def handle_user_input(self):
|
|
191
199
|
for player, scene in self.scenes.items():
|
|
@@ -215,7 +223,9 @@ class MimaMode(MimaView):
|
|
|
215
223
|
else:
|
|
216
224
|
msg += f"object {obj.name} ({obj.dyn_id})"
|
|
217
225
|
else:
|
|
218
|
-
msg =
|
|
226
|
+
msg = (
|
|
227
|
+
"Trying to interact with a quest that is None"
|
|
228
|
+
)
|
|
219
229
|
|
|
220
230
|
LOG.exception(msg)
|
|
221
231
|
raise
|
|
@@ -290,7 +300,9 @@ class MimaMode(MimaView):
|
|
|
290
300
|
tilemap.width + self.chunk_size // 2,
|
|
291
301
|
self.chunk_size,
|
|
292
302
|
):
|
|
293
|
-
chidx = _chunk_index(
|
|
303
|
+
chidx = _chunk_index(
|
|
304
|
+
px, py, self.chunk_size, chunks_per_row
|
|
305
|
+
)
|
|
294
306
|
# collision_lists[map_name][chidx] = []
|
|
295
307
|
self.add_effect(
|
|
296
308
|
StaticDebugBox(
|
|
@@ -333,7 +345,9 @@ class MimaMode(MimaView):
|
|
|
333
345
|
# return collision_lists
|
|
334
346
|
|
|
335
347
|
def _determine_target(self, obj, players) -> Dynamic:
|
|
336
|
-
players = [
|
|
348
|
+
players = [
|
|
349
|
+
p for p in players if not self.engine.get_player(p).occupied
|
|
350
|
+
]
|
|
337
351
|
if not players:
|
|
338
352
|
return None
|
|
339
353
|
dists = [
|
|
@@ -354,7 +368,10 @@ class MimaMode(MimaView):
|
|
|
354
368
|
return target # , skip
|
|
355
369
|
|
|
356
370
|
def _update_velocity_z(self, obj: Dynamic, elapsed_time: float) -> None:
|
|
357
|
-
obj.
|
|
371
|
+
if obj.pz > 0.0:
|
|
372
|
+
obj.vz -= obj.attributes.gravity_vz * elapsed_time
|
|
373
|
+
# else:
|
|
374
|
+
# obj.vz = 0.0
|
|
358
375
|
|
|
359
376
|
def _update_position_z(self, obj: Dynamic, elapsed_time: float) -> None:
|
|
360
377
|
if obj.gravity:
|
|
@@ -364,11 +381,16 @@ class MimaMode(MimaView):
|
|
|
364
381
|
obj.vz = 0.0
|
|
365
382
|
|
|
366
383
|
def handle_collisions(self, elapsed_time: float) -> None:
|
|
367
|
-
screen_width =
|
|
368
|
-
|
|
384
|
+
screen_width = (
|
|
385
|
+
self.engine.backend.render_width // self.engine.rtc.tile_width
|
|
386
|
+
)
|
|
387
|
+
screen_height = (
|
|
388
|
+
self.engine.backend.render_height // self.engine.rtc.tile_height
|
|
389
|
+
)
|
|
369
390
|
max_dist = screen_width + screen_height
|
|
370
391
|
|
|
371
392
|
for map_name, players in self.players_on_map.items():
|
|
393
|
+
# print(f"Collisions for {map_name}: {self.colliders[map_name]}")
|
|
372
394
|
for obj in self.colliders[map_name]:
|
|
373
395
|
if obj.occupied:
|
|
374
396
|
continue
|
|
@@ -407,13 +429,19 @@ class MimaMode(MimaView):
|
|
|
407
429
|
self.engine.memory.quests,
|
|
408
430
|
]
|
|
409
431
|
if self._probe_p2p_collision(obj, other):
|
|
410
|
-
new2_px, new2_py =
|
|
432
|
+
new2_px, new2_py = (
|
|
433
|
+
check_object_to_object_collision(*args)
|
|
434
|
+
)
|
|
411
435
|
|
|
412
436
|
if new2_px == new_px and new2_py == new_py:
|
|
413
437
|
# No change = no collision
|
|
414
|
-
self.engine.trigger_player_collision(
|
|
438
|
+
self.engine.trigger_player_collision(
|
|
439
|
+
True, obj.player
|
|
440
|
+
)
|
|
415
441
|
else:
|
|
416
|
-
new_px, new_py = check_object_to_object_collision(
|
|
442
|
+
new_px, new_py = check_object_to_object_collision(
|
|
443
|
+
*args
|
|
444
|
+
)
|
|
417
445
|
obj.px = new_px
|
|
418
446
|
obj.py = new_py
|
|
419
447
|
|
|
@@ -435,17 +463,23 @@ class MimaMode(MimaView):
|
|
|
435
463
|
vx, vy = vx * 0.707, vy * 0.707
|
|
436
464
|
|
|
437
465
|
obj.real_vx = (
|
|
438
|
-
vx
|
|
466
|
+
vx
|
|
467
|
+
if vx == obj.real_vx
|
|
468
|
+
else calculate(obj, vx, obj.real_vx, elapsed_time)
|
|
439
469
|
)
|
|
440
470
|
obj.real_vy = (
|
|
441
|
-
vy
|
|
471
|
+
vy
|
|
472
|
+
if vy == obj.real_vy
|
|
473
|
+
else calculate(obj, vy, obj.real_vy, elapsed_time)
|
|
442
474
|
)
|
|
443
475
|
|
|
444
476
|
new_px = (
|
|
445
|
-
obj.px
|
|
477
|
+
obj.px
|
|
478
|
+
+ obj.real_vx * obj.speed * obj.attributes.speed_mod * elapsed_time
|
|
446
479
|
)
|
|
447
480
|
new_py = (
|
|
448
|
-
obj.py
|
|
481
|
+
obj.py
|
|
482
|
+
+ obj.real_vy * obj.speed * obj.attributes.speed_mod * elapsed_time
|
|
449
483
|
)
|
|
450
484
|
|
|
451
485
|
return new_px, new_py
|
|
@@ -475,7 +509,9 @@ class MimaMode(MimaView):
|
|
|
475
509
|
for map_name in self.players_on_map:
|
|
476
510
|
for effect in self.effects[map_name]:
|
|
477
511
|
effect.update(elapsed_time)
|
|
478
|
-
effect.px, effect.py = self.update_position(
|
|
512
|
+
effect.px, effect.py = self.update_position(
|
|
513
|
+
effect, elapsed_time
|
|
514
|
+
)
|
|
479
515
|
|
|
480
516
|
def update_scenes(self, elapsed_time: float) -> None:
|
|
481
517
|
for player, scene in self.scenes.items():
|
|
@@ -494,12 +530,17 @@ class MimaMode(MimaView):
|
|
|
494
530
|
|
|
495
531
|
def add_dynamic(self, dynamic: Dynamic, map_name: str):
|
|
496
532
|
self.dynamics[map_name].append(dynamic)
|
|
497
|
-
if
|
|
533
|
+
if (
|
|
534
|
+
map_name in self.collision_targets
|
|
535
|
+
and not dynamic.moves_on_collision
|
|
536
|
+
):
|
|
498
537
|
dynamic.chunks = add_to_collision_chunk(
|
|
499
538
|
self.collision_targets[map_name],
|
|
500
539
|
dynamic,
|
|
501
540
|
self.chunk_size,
|
|
502
|
-
_chunks_per_row(
|
|
541
|
+
_chunks_per_row(
|
|
542
|
+
self.chunk_size, self.engine.get_map(map_name).width
|
|
543
|
+
),
|
|
503
544
|
)
|
|
504
545
|
|
|
505
546
|
def add_projectile(self, projectile: Projectile, map_name: str):
|
mima/view/mima_scene.py
CHANGED
|
@@ -39,8 +39,10 @@ class MimaScene(MimaView):
|
|
|
39
39
|
self._camera_name: str = (
|
|
40
40
|
camera_name if camera_name is not None else f"C_{player.name}"
|
|
41
41
|
)
|
|
42
|
+
self._controls_camera_name: str = f"{self._camera_name}_CONTROLS"
|
|
42
43
|
|
|
43
44
|
self.camera: Camera
|
|
45
|
+
self.controls_camera: Camera
|
|
44
46
|
self._dialog_px: float
|
|
45
47
|
self._dialog_py: float
|
|
46
48
|
self._dialog_width: float = DIALOG_WIDTH
|
|
@@ -85,6 +87,9 @@ class MimaScene(MimaView):
|
|
|
85
87
|
self._dialog_py = height - 4
|
|
86
88
|
|
|
87
89
|
self.camera = Camera(self._camera_name, width, height)
|
|
90
|
+
# self.controls_camera = Camera(
|
|
91
|
+
# self._controls_camera_name, width, height
|
|
92
|
+
# )
|
|
88
93
|
if position == Position.CENTER:
|
|
89
94
|
# print(f"Camera setup finished: {width}, {height}")
|
|
90
95
|
return
|
|
@@ -181,6 +186,7 @@ class MimaScene(MimaView):
|
|
|
181
186
|
self.skip_draw_ui = False
|
|
182
187
|
return
|
|
183
188
|
self._current_window.draw_ui()
|
|
189
|
+
self._current_window.draw_controls()
|
|
184
190
|
|
|
185
191
|
def draw_camera_border(self):
|
|
186
192
|
self.camera.draw_borders()
|
mima/view/mima_window.py
CHANGED
|
@@ -6,6 +6,8 @@ from ..types.direction import Direction
|
|
|
6
6
|
from ..types.keys import Key as K
|
|
7
7
|
from ..types.player import Player
|
|
8
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
|
|
9
11
|
from ..util.functions import wrap_text
|
|
10
12
|
from .mima_view import MimaView
|
|
11
13
|
|
|
@@ -92,6 +94,16 @@ class MimaWindow(MimaView):
|
|
|
92
94
|
obj.draw_self(
|
|
93
95
|
self.camera.ox, self.camera.oy, self.camera.name
|
|
94
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
|
+
)
|
|
95
107
|
|
|
96
108
|
def draw_effect_layers(
|
|
97
109
|
self, effects: List[Dynamic], layers: List[int]
|
|
@@ -116,6 +128,85 @@ class MimaWindow(MimaView):
|
|
|
116
128
|
def draw_ui(self) -> None:
|
|
117
129
|
pass
|
|
118
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
|
+
|
|
119
210
|
def set_camera(self, camera: Camera):
|
|
120
211
|
self.camera = camera
|
|
121
212
|
|