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
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
import pygame
|
|
4
|
+
|
|
5
|
+
from ..types.keys import Key as K
|
|
6
|
+
from ..util.constants import DOUBLE_TAP_SPEED
|
|
7
|
+
from ..util.input_defaults import ALT_TOUCHSCREEN_MAP, BUTTONS
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TouchControlSchemeB:
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
|
|
14
|
+
self.move_start_pos = pygame.Vector2()
|
|
15
|
+
self.move_pos = pygame.Vector2()
|
|
16
|
+
self.move_sy = 0.0
|
|
17
|
+
self.move_px = 0.0
|
|
18
|
+
self.move_py = 0.0
|
|
19
|
+
self._left_finger_tap_pos = 0.0
|
|
20
|
+
self._right_finger_tap_pos = 0.0
|
|
21
|
+
|
|
22
|
+
self._last_left_tap = 0.0
|
|
23
|
+
self._last_right_tap = 0.0
|
|
24
|
+
self._keys_active = {k: False for k in K}
|
|
25
|
+
self._state = {}
|
|
26
|
+
for key, conf in ALT_TOUCHSCREEN_MAP.items():
|
|
27
|
+
px, py = conf["pos"]
|
|
28
|
+
w, h = conf["size"]
|
|
29
|
+
self._state[key] = {
|
|
30
|
+
"rpx": px,
|
|
31
|
+
"rpy": py,
|
|
32
|
+
"rwidth": w,
|
|
33
|
+
"rheight": h,
|
|
34
|
+
"active": False,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def handle_touch(self, event, width=1.0, height=1.0):
|
|
38
|
+
set_keys = []
|
|
39
|
+
unset_keys = []
|
|
40
|
+
|
|
41
|
+
tap_pos = pygame.Vector2(event.x * width, event.y * height)
|
|
42
|
+
keys_active = {k: False for k in K}
|
|
43
|
+
# print(f"{event.x:.2f}, {event.y:.2f}", end="")
|
|
44
|
+
for key, conf in ALT_TOUCHSCREEN_MAP.items():
|
|
45
|
+
px, py = conf["pos"]
|
|
46
|
+
w, h = conf["size"]
|
|
47
|
+
area = [[px, py], [px + w, py + h]]
|
|
48
|
+
|
|
49
|
+
if (
|
|
50
|
+
area[0][0] <= event.x < area[1][0]
|
|
51
|
+
and area[0][1] <= event.y < area[1][1]
|
|
52
|
+
):
|
|
53
|
+
if key == K.P1_UP:
|
|
54
|
+
if event.type == pygame.FINGERDOWN:
|
|
55
|
+
self.move_start_pos = pygame.Vector2(tap_pos)
|
|
56
|
+
self.move_pos = pygame.Vector2(tap_pos)
|
|
57
|
+
self._state[key]["rsx"] = event.x
|
|
58
|
+
self._state[key]["rsy"] = event.y
|
|
59
|
+
self._state[key]["rpx"] = event.x
|
|
60
|
+
self._state[key]["rpy"] = event.y
|
|
61
|
+
elif event.type == pygame.FINGERMOTION:
|
|
62
|
+
self.move_pos = tap_pos
|
|
63
|
+
self._state[key]["rpx"] = event.x
|
|
64
|
+
self._state[key]["rpy"] = event.y
|
|
65
|
+
|
|
66
|
+
vd = self.move_pos - self.move_start_pos
|
|
67
|
+
if abs(vd.x) > 2 * abs(vd.y):
|
|
68
|
+
# Horizontal
|
|
69
|
+
if vd.x > 5.0:
|
|
70
|
+
keys_active[K.P1_RIGHT] = True
|
|
71
|
+
# print("..>", end="")
|
|
72
|
+
elif vd.x < -5.0:
|
|
73
|
+
keys_active[K.P1_LEFT] = True
|
|
74
|
+
# print("..<", end="")
|
|
75
|
+
elif abs(vd.x) * 2 < abs(vd.y):
|
|
76
|
+
# Vertical
|
|
77
|
+
if vd.y > 5.0:
|
|
78
|
+
keys_active[K.P1_DOWN] = True
|
|
79
|
+
# print("..v", end="")
|
|
80
|
+
elif vd.y < -5.0:
|
|
81
|
+
keys_active[K.P1_UP] = True
|
|
82
|
+
# print("..^", end="")
|
|
83
|
+
elif abs(vd.x) * 1.05 > abs(vd.y) or abs(
|
|
84
|
+
vd.x
|
|
85
|
+
) < 1.05 * abs(vd.y):
|
|
86
|
+
# Diagonal
|
|
87
|
+
if vd.x < 0:
|
|
88
|
+
keys_active[K.P1_LEFT] = True
|
|
89
|
+
# print("..<", end="")
|
|
90
|
+
elif vd.x > 0:
|
|
91
|
+
keys_active[K.P1_RIGHT] = True
|
|
92
|
+
# print("..>", end="")
|
|
93
|
+
if vd.y < 0:
|
|
94
|
+
keys_active[K.P1_UP] = True
|
|
95
|
+
# print("..^", end="")
|
|
96
|
+
elif vd.y > 0:
|
|
97
|
+
keys_active[K.P1_DOWN] = True
|
|
98
|
+
# print("..v", end="")
|
|
99
|
+
# elif event.type == pygame.FINGERUP:
|
|
100
|
+
# unset_keys.append(K.P1_RIGHT)
|
|
101
|
+
# unset_keys.append(K.P1_LEFT)
|
|
102
|
+
# unset_keys.append(K.P1_UP)
|
|
103
|
+
# unset_keys.append(K.P1_DOWN)
|
|
104
|
+
else:
|
|
105
|
+
if event.type == pygame.FINGERDOWN:
|
|
106
|
+
keys_active[key] = True
|
|
107
|
+
# print(f"..{key.name}", end="")
|
|
108
|
+
if event.type == pygame.FINGERMOTION:
|
|
109
|
+
keys_active[key] = True
|
|
110
|
+
# print(f"..{key.name}", end="")
|
|
111
|
+
# print()
|
|
112
|
+
for k, val in keys_active.items():
|
|
113
|
+
if val:
|
|
114
|
+
set_keys.append(k)
|
|
115
|
+
# self._state.setdefault(k, {})["active"] = True
|
|
116
|
+
if k in self._state:
|
|
117
|
+
self._state[k]["active"] = True
|
|
118
|
+
if k in [K.P1_LEFT, K.P1_RIGHT, K.P1_DOWN]:
|
|
119
|
+
self._state[K.P1_UP]["active"] = True
|
|
120
|
+
else:
|
|
121
|
+
unset_keys.append(k)
|
|
122
|
+
if k in self._state:
|
|
123
|
+
self._state[k]["active"] = False
|
|
124
|
+
return set_keys, unset_keys
|
|
125
|
+
|
|
126
|
+
def get_touch_state(self):
|
|
127
|
+
state = {}
|
|
128
|
+
for key, conf in self._state.items():
|
|
129
|
+
nkey = K(key.value - 12)
|
|
130
|
+
state[nkey] = conf
|
|
131
|
+
|
|
132
|
+
return state
|
mima/core/collision.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import math
|
|
4
|
+
from itertools import product
|
|
4
5
|
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
|
|
5
6
|
|
|
6
7
|
from ..maps.tilemap import Tilemap
|
|
@@ -35,7 +36,9 @@ def check_object_to_map_collision(
|
|
|
35
36
|
|
|
36
37
|
collided_with_map = False
|
|
37
38
|
if obj.solid_vs_map:
|
|
38
|
-
if collision_with_map(
|
|
39
|
+
if collision_with_map(
|
|
40
|
+
tilemap, left, right, top, bottom, layer, collision
|
|
41
|
+
):
|
|
39
42
|
# On rare occasions, the object might be pushed towards
|
|
40
43
|
# the wall, i.e. old and new pos are equal
|
|
41
44
|
# Decide depending on the decimal part of the position
|
|
@@ -66,7 +69,9 @@ def check_object_to_map_collision(
|
|
|
66
69
|
top = new_py + obj.hitbox_py
|
|
67
70
|
bottom = top + obj.hitbox_height
|
|
68
71
|
|
|
69
|
-
if collision_with_map(
|
|
72
|
+
if collision_with_map(
|
|
73
|
+
tilemap, left, right, top, bottom, layer, collision
|
|
74
|
+
):
|
|
70
75
|
# See comment above
|
|
71
76
|
if new_py == obj.py:
|
|
72
77
|
decimal_dif = new_py - int(new_py)
|
|
@@ -244,34 +249,50 @@ def add_to_collision_chunk(
|
|
|
244
249
|
# collision_chunks[chidx].insert(0, obj)
|
|
245
250
|
# else:
|
|
246
251
|
# collision_chunks[chidx].append(obj)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
collision_chunks, obj, obj.px, obj.py + 1, chunk_size, chunks_per_row
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
chunk_ids.append(chid)
|
|
260
|
-
if chid != chid_right:
|
|
261
|
-
chunk_ids.append(chid_right)
|
|
262
|
-
if chid != chid_bottom:
|
|
263
|
-
chunk_ids.append(chid_bottom)
|
|
264
|
-
if chid != chid_right and chid != chid_bottom:
|
|
252
|
+
centerx = obj.px + (obj.hitbox_px + obj.hitbox_width) / 2
|
|
253
|
+
centery = obj.py + (obj.hitbox_py + obj.hitbox_height) / 2
|
|
254
|
+
# chid = _test_chunk_position(
|
|
255
|
+
# collision_chunks, obj, centerx, centery, chunk_size, chunks_per_row
|
|
256
|
+
# )
|
|
257
|
+
offsets = [[0, 0]] + [
|
|
258
|
+
list(p) for p in product([-1, 0, 1], repeat=2) if p != (0, 0)
|
|
259
|
+
]
|
|
260
|
+
for x, y in offsets:
|
|
265
261
|
chunk_ids.append(
|
|
266
262
|
_test_chunk_position(
|
|
267
263
|
collision_chunks,
|
|
268
264
|
obj,
|
|
269
|
-
|
|
270
|
-
|
|
265
|
+
centerx + x,
|
|
266
|
+
centery + y,
|
|
271
267
|
chunk_size,
|
|
272
268
|
chunks_per_row,
|
|
273
269
|
)
|
|
274
270
|
)
|
|
271
|
+
chunk_ids = list(dict.fromkeys(chunk_ids))
|
|
272
|
+
# chid_right = _test_chunk_position(
|
|
273
|
+
# collision_chunks, obj, obj.px + 1, obj.py, chunk_size, chunks_per_row
|
|
274
|
+
# )
|
|
275
|
+
|
|
276
|
+
# chid_bottom = _test_chunk_position(
|
|
277
|
+
# collision_chunks, obj, obj.px, obj.py + 1, chunk_size, chunks_per_row
|
|
278
|
+
# )
|
|
279
|
+
|
|
280
|
+
# chunk_ids.append(chid)
|
|
281
|
+
# if chid != chid_right:
|
|
282
|
+
# chunk_ids.append(chid_right)
|
|
283
|
+
# if chid != chid_bottom:
|
|
284
|
+
# chunk_ids.append(chid_bottom)
|
|
285
|
+
# if chid != chid_right and chid != chid_bottom:
|
|
286
|
+
# chunk_ids.append(
|
|
287
|
+
# _test_chunk_position(
|
|
288
|
+
# collision_chunks,
|
|
289
|
+
# obj,
|
|
290
|
+
# obj.px + 1,
|
|
291
|
+
# obj.py + 1,
|
|
292
|
+
# chunk_size,
|
|
293
|
+
# chunks_per_row,
|
|
294
|
+
# )
|
|
295
|
+
# )
|
|
275
296
|
|
|
276
297
|
for chid in obj.chunks:
|
|
277
298
|
if (
|
|
@@ -283,7 +304,9 @@ def add_to_collision_chunk(
|
|
|
283
304
|
return chunk_ids
|
|
284
305
|
|
|
285
306
|
|
|
286
|
-
def _test_chunk_position(
|
|
307
|
+
def _test_chunk_position(
|
|
308
|
+
collision_chunks, obj, px, py, chunk_size, chunks_per_row
|
|
309
|
+
):
|
|
287
310
|
chidx = _chunk_index(px, py, chunk_size, chunks_per_row)
|
|
288
311
|
collision_chunks.setdefault(chidx, [])
|
|
289
312
|
|
mima/core/engine.py
CHANGED
|
@@ -26,13 +26,9 @@ from ..usables.weapon import Weapon
|
|
|
26
26
|
from ..util import RuntimeConfig
|
|
27
27
|
from ..util.logging import install_trace_logger
|
|
28
28
|
from ..view.camera import Camera
|
|
29
|
-
|
|
30
|
-
# from .view.game_mode import GameMode
|
|
31
29
|
from ..view.mima_view import MimaView
|
|
32
30
|
from .database import Database
|
|
33
31
|
|
|
34
|
-
# from .view.scene import Scene
|
|
35
|
-
|
|
36
32
|
if TYPE_CHECKING:
|
|
37
33
|
from .states.game_state import GameState
|
|
38
34
|
|
|
@@ -51,7 +47,9 @@ class MimaEngine(ABC):
|
|
|
51
47
|
self.rtc = RuntimeConfig(config_path, default_config)
|
|
52
48
|
install_trace_logger()
|
|
53
49
|
|
|
54
|
-
self.backend: PygameBackend = PygameBackend(
|
|
50
|
+
self.backend: PygameBackend = PygameBackend(
|
|
51
|
+
self.rtc, init_file, platform
|
|
52
|
+
)
|
|
55
53
|
self.db: Database
|
|
56
54
|
self._caption: str = caption
|
|
57
55
|
self.seconds_total: float = 0.0
|
|
@@ -60,6 +58,9 @@ class MimaEngine(ABC):
|
|
|
60
58
|
self.elapsed_time: float = 0.00022
|
|
61
59
|
self._app_time: float = 0.0
|
|
62
60
|
|
|
61
|
+
self.enable_touch_controls: bool = False
|
|
62
|
+
self.show_touch_controls: bool = False
|
|
63
|
+
|
|
63
64
|
self.mode: Mode = Mode.LOADING
|
|
64
65
|
self.gate_color: GateColor = GateColor.RED
|
|
65
66
|
self.n_gate_colors = 2
|
|
@@ -67,9 +68,6 @@ class MimaEngine(ABC):
|
|
|
67
68
|
self.memory: Memory = Memory()
|
|
68
69
|
self.all_games: Dict[str, GameState] = {}
|
|
69
70
|
self.current_game: str = ""
|
|
70
|
-
# self.player: Creature
|
|
71
|
-
# self.quests: List[Quest] = []
|
|
72
|
-
# self._items: Dict[str, Item] = {}
|
|
73
71
|
self.cameras: List[str] = []
|
|
74
72
|
|
|
75
73
|
def construct(
|
|
@@ -80,6 +78,7 @@ class MimaEngine(ABC):
|
|
|
80
78
|
fullscreen: bool = False,
|
|
81
79
|
target_fps: int = 60,
|
|
82
80
|
resizable: bool = False,
|
|
81
|
+
no_scaled_flag: bool = False,
|
|
83
82
|
kb_map=None,
|
|
84
83
|
):
|
|
85
84
|
"""Initialize backend and create a window."""
|
|
@@ -108,7 +107,16 @@ class MimaEngine(ABC):
|
|
|
108
107
|
joy_to_player=self.rtc.get_joy_to_player(),
|
|
109
108
|
)
|
|
110
109
|
self.backend.construct(
|
|
111
|
-
width,
|
|
110
|
+
width,
|
|
111
|
+
height,
|
|
112
|
+
pixel_size,
|
|
113
|
+
fullscreen,
|
|
114
|
+
target_fps,
|
|
115
|
+
resizable,
|
|
116
|
+
no_scaled_flag,
|
|
117
|
+
)
|
|
118
|
+
self.backend.user_input.enable_touch_controls = (
|
|
119
|
+
self.enable_touch_controls
|
|
112
120
|
)
|
|
113
121
|
|
|
114
122
|
return True
|
|
@@ -126,7 +134,8 @@ class MimaEngine(ABC):
|
|
|
126
134
|
if self.on_user_create():
|
|
127
135
|
while self.backend.keep_running():
|
|
128
136
|
self.backend.set_caption(
|
|
129
|
-
f"{self._caption} ({self.game_fps:.2f}/"
|
|
137
|
+
f"{self._caption} ({self.game_fps:.2f}/"
|
|
138
|
+
f"{self.app_fps:.2f} fps)"
|
|
130
139
|
)
|
|
131
140
|
self.backend.process_events()
|
|
132
141
|
|
|
@@ -160,7 +169,10 @@ class MimaEngine(ABC):
|
|
|
160
169
|
app_frames = 0
|
|
161
170
|
app_seconds -= 1.0
|
|
162
171
|
|
|
163
|
-
print(
|
|
172
|
+
print(
|
|
173
|
+
f"App/Game Frames total: {app_frames_total}/"
|
|
174
|
+
f"{game_frames_total}"
|
|
175
|
+
)
|
|
164
176
|
print(f"Seconds total: {self.seconds_total:.3f}")
|
|
165
177
|
print(
|
|
166
178
|
"Average App/Game FPS: "
|
|
@@ -276,7 +288,9 @@ class MimaEngine(ABC):
|
|
|
276
288
|
def set_player(self, creature: Creature, player: Player = Player.P1):
|
|
277
289
|
self.memory.player[player] = creature
|
|
278
290
|
|
|
279
|
-
def trigger_teleport(
|
|
291
|
+
def trigger_teleport(
|
|
292
|
+
self, active: bool = True, player: Player = Player.P1
|
|
293
|
+
):
|
|
280
294
|
self.memory.teleport_active[player] = active
|
|
281
295
|
|
|
282
296
|
def is_teleport_active(self, player: Player = Player.P1):
|
|
@@ -288,7 +302,9 @@ class MimaEngine(ABC):
|
|
|
288
302
|
def is_dialog_active(self, player: Player = Player.P1):
|
|
289
303
|
return self.memory.dialog_active[player]
|
|
290
304
|
|
|
291
|
-
def trigger_script(
|
|
305
|
+
def trigger_script(
|
|
306
|
+
self, active: bool = True, player: Player = Player.P1
|
|
307
|
+
) -> None:
|
|
292
308
|
self.memory.script_active[player] = active
|
|
293
309
|
|
|
294
310
|
def is_script_active(self, player: Player = Player.P1) -> bool:
|
|
@@ -337,7 +353,10 @@ class MimaEngine(ABC):
|
|
|
337
353
|
|
|
338
354
|
@dialog_active.setter
|
|
339
355
|
def dialog_active(self, val):
|
|
340
|
-
print(
|
|
356
|
+
print(
|
|
357
|
+
"dialog_active is deprecated; use "
|
|
358
|
+
"'trigger_dialog(active)' instead."
|
|
359
|
+
)
|
|
341
360
|
self.memory.dialog_active = val
|
|
342
361
|
|
|
343
362
|
@property
|
mima/core/mode_engine.py
CHANGED
|
@@ -22,7 +22,9 @@ class MimaModeEngine(MimaEngine):
|
|
|
22
22
|
platform="PC",
|
|
23
23
|
caption: str = "MimaEngine",
|
|
24
24
|
):
|
|
25
|
-
super().__init__(
|
|
25
|
+
super().__init__(
|
|
26
|
+
init_file, config_path, default_config, platform, caption
|
|
27
|
+
)
|
|
26
28
|
|
|
27
29
|
self.modes: Dict[Mode, MimaMode] = {}
|
|
28
30
|
self.mode: Optional[MimaMode] = None
|
|
@@ -31,6 +33,7 @@ class MimaModeEngine(MimaEngine):
|
|
|
31
33
|
|
|
32
34
|
self.draw_chunks: bool = False
|
|
33
35
|
self.draw_chunk_info: bool = False
|
|
36
|
+
self.draw_dyn_ids: bool = False
|
|
34
37
|
self.disable_filter: bool = False
|
|
35
38
|
self._timer = 1.0
|
|
36
39
|
|
|
@@ -67,7 +70,9 @@ class MimaModeEngine(MimaEngine):
|
|
|
67
70
|
self.mode.load()
|
|
68
71
|
|
|
69
72
|
def return_mode(self):
|
|
70
|
-
LOG.debug(
|
|
73
|
+
LOG.debug(
|
|
74
|
+
"Returning to previous mode. Stack: %s", str(self.mode_stack)
|
|
75
|
+
)
|
|
71
76
|
self.mode_stack.pop()
|
|
72
77
|
self.mode = self.modes[self.mode_stack[-1]]
|
|
73
78
|
self.mode.load()
|
mima/objects/creature.py
CHANGED
|
@@ -136,6 +136,9 @@ class Creature(Dynamic):
|
|
|
136
136
|
if self.attributes.health <= 0:
|
|
137
137
|
self.change_graphic_state(GraphicState.DEAD)
|
|
138
138
|
|
|
139
|
+
if self.can_act():
|
|
140
|
+
self.behavior(elapsed_time, target)
|
|
141
|
+
|
|
139
142
|
if self.vx < -0.01:
|
|
140
143
|
self.facing_direction = Direction.WEST
|
|
141
144
|
if self.vx > 0.01:
|
|
@@ -147,9 +150,6 @@ class Creature(Dynamic):
|
|
|
147
150
|
|
|
148
151
|
self.speed = self.attributes.speed
|
|
149
152
|
|
|
150
|
-
if self.can_act():
|
|
151
|
-
self.behavior(elapsed_time, target)
|
|
152
|
-
|
|
153
153
|
self.sprite.update(
|
|
154
154
|
elapsed_time, self.facing_direction, self.graphic_state
|
|
155
155
|
)
|
|
@@ -298,6 +298,12 @@ class Creature(Dynamic):
|
|
|
298
298
|
|
|
299
299
|
self.projectiles = []
|
|
300
300
|
|
|
301
|
+
def on_enter_map(self):
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
def on_exit_map(self):
|
|
305
|
+
pass
|
|
306
|
+
|
|
301
307
|
def on_death(self):
|
|
302
308
|
if self.spawn_on_death:
|
|
303
309
|
for do in self.spawn_on_death:
|
|
@@ -21,7 +21,12 @@ class DynamicDebugBox(Projectile):
|
|
|
21
21
|
ids=None,
|
|
22
22
|
) -> None:
|
|
23
23
|
super().__init__(
|
|
24
|
-
0,
|
|
24
|
+
0,
|
|
25
|
+
0,
|
|
26
|
+
"DynamicDebugBox",
|
|
27
|
+
duration=0.0,
|
|
28
|
+
alignment=Alignment.NEUTRAL,
|
|
29
|
+
tilemap=follow.tilemap,
|
|
25
30
|
)
|
|
26
31
|
self.layer = 2
|
|
27
32
|
self.sprite = None
|
|
@@ -76,7 +81,11 @@ class DynamicDebugBox(Projectile):
|
|
|
76
81
|
class StaticDebugBox(Projectile):
|
|
77
82
|
def __init__(self, px, py, width, height, color, n_frames=1, ids=None):
|
|
78
83
|
super().__init__(
|
|
79
|
-
px,
|
|
84
|
+
px,
|
|
85
|
+
py,
|
|
86
|
+
"StaticDebugBox",
|
|
87
|
+
duration=0.0,
|
|
88
|
+
alignment=Alignment.NEUTRAL,
|
|
80
89
|
)
|
|
81
90
|
self.layer = 2
|
|
82
91
|
self._color = color
|
mima/objects/world/container.py
CHANGED
|
@@ -138,7 +138,7 @@ class Container(Dynamic):
|
|
|
138
138
|
CommandParallel(
|
|
139
139
|
[
|
|
140
140
|
CommandShowDialog(
|
|
141
|
-
[f"You received {self.
|
|
141
|
+
[f"You received {self.item.name}"],
|
|
142
142
|
),
|
|
143
143
|
CommandPresentItem(self.item_name, target),
|
|
144
144
|
CommandGiveItem(self.item_name, target),
|
mima/objects/world/oneway.py
CHANGED
|
@@ -35,6 +35,7 @@ class Oneway(Dynamic):
|
|
|
35
35
|
dyn_id=dyn_id,
|
|
36
36
|
)
|
|
37
37
|
self.type = ObjectType.ONEWAY
|
|
38
|
+
self.layer = 0
|
|
38
39
|
self.sprite.width = int(width * self.engine.rtc.tile_width)
|
|
39
40
|
self.sprite.height = int(height * self.engine.rtc.tile_height)
|
|
40
41
|
|
|
@@ -46,24 +47,26 @@ class Oneway(Dynamic):
|
|
|
46
47
|
self.height: float = height
|
|
47
48
|
self.jump_vx: float = 0.0
|
|
48
49
|
self.jump_vy: float = 0.0
|
|
50
|
+
self.jump_direction = Direction.from_velocity(jump_vx, jump_vy)
|
|
49
51
|
self.activation_delay: float = ONEWAY_ACTIVATION_DELAY
|
|
50
52
|
self.triggered: bool = False
|
|
53
|
+
self.is_active: bool = False
|
|
51
54
|
self.cooldown: float = 0.0
|
|
52
55
|
self.target = None
|
|
53
56
|
|
|
54
57
|
if jump_vx < 0:
|
|
55
58
|
self.jump_vx = jump_vx - 1
|
|
56
|
-
self.hitbox_px += 0.1
|
|
59
|
+
# self.hitbox_px += 0.1
|
|
57
60
|
elif jump_vx > 0:
|
|
58
61
|
self.jump_vx = jump_vx + 1
|
|
59
|
-
self.hitbox_px -= 0.1
|
|
62
|
+
# self.hitbox_px -= 0.1
|
|
60
63
|
|
|
61
64
|
if jump_vy < 0:
|
|
62
65
|
self.jump_vy = jump_vy - 1
|
|
63
|
-
self.hitbox_py += 0.1
|
|
66
|
+
# self.hitbox_py += 0.1
|
|
64
67
|
elif jump_vy > 0:
|
|
65
68
|
self.jump_vy = jump_vy + 1
|
|
66
|
-
self.hitbox_py -= 0.1
|
|
69
|
+
# self.hitbox_py -= 0.1
|
|
67
70
|
|
|
68
71
|
def update(self, elapsed_time, target=None):
|
|
69
72
|
self.sprite.update(
|
|
@@ -90,9 +93,15 @@ class Oneway(Dynamic):
|
|
|
90
93
|
# Activation countdown reached 0 and the jump is initiated.
|
|
91
94
|
if self.timer <= 0.0 and self.target is not None:
|
|
92
95
|
self.engine.script.add_command(
|
|
93
|
-
CommandOnewayMove(
|
|
96
|
+
CommandOnewayMove(
|
|
97
|
+
self.target,
|
|
98
|
+
self.jump_vx,
|
|
99
|
+
self.jump_vy,
|
|
100
|
+
target.get_player(),
|
|
101
|
+
)
|
|
94
102
|
)
|
|
95
103
|
self.cooldown = 2.0
|
|
104
|
+
self.is_active
|
|
96
105
|
|
|
97
106
|
# Reset the triggered flag so it has to be activated again
|
|
98
107
|
# by interaction
|
|
@@ -100,11 +109,25 @@ class Oneway(Dynamic):
|
|
|
100
109
|
self.target = None
|
|
101
110
|
|
|
102
111
|
def on_interaction(self, target, nature=Nature.WALK):
|
|
103
|
-
if
|
|
112
|
+
if (
|
|
113
|
+
target.type == ObjectType.PLAYER
|
|
114
|
+
and nature == Nature.WALK
|
|
115
|
+
and self.cooldown <= 0.0
|
|
116
|
+
):
|
|
104
117
|
# No interaction when target is higher than the oneway
|
|
105
118
|
if target.pz > 0:
|
|
106
119
|
return False
|
|
107
120
|
|
|
121
|
+
if self.jump_direction != target.facing_direction:
|
|
122
|
+
return False
|
|
123
|
+
|
|
124
|
+
tcenterx = target.px + (target.hitbox_px + target.hitbox_width) / 2
|
|
125
|
+
tbottomy = target.py + target.hitbox_py + target.hitbox_height
|
|
126
|
+
ttopy = target.py + target.hitbox_py
|
|
127
|
+
tleftx = target.px + target.hitbox_px
|
|
128
|
+
trightx = tleftx + target.hitbox_width
|
|
129
|
+
|
|
130
|
+
# print(tcenterx, tbottomy)
|
|
108
131
|
# We have to check that target is not placed "more" in the
|
|
109
132
|
# target direction than the oneway
|
|
110
133
|
if (
|
|
@@ -119,7 +142,7 @@ class Oneway(Dynamic):
|
|
|
119
142
|
and target.py <= self.py + self.height - target.hitbox_py
|
|
120
143
|
):
|
|
121
144
|
return False
|
|
122
|
-
if self.jump_vy > 0 and
|
|
145
|
+
if self.jump_vy > 0 and tbottomy >= self.py: # FIXME
|
|
123
146
|
return False
|
|
124
147
|
|
|
125
148
|
if self.jump_vx == 0:
|
|
@@ -133,12 +156,15 @@ class Oneway(Dynamic):
|
|
|
133
156
|
return False
|
|
134
157
|
if target.py + 1.0 <= self.py:
|
|
135
158
|
return False
|
|
136
|
-
|
|
137
159
|
self.triggered = True
|
|
138
160
|
self.target = target
|
|
139
161
|
if self.timer <= 0.0:
|
|
140
162
|
self.timer = self.activation_delay
|
|
163
|
+
# return False
|
|
141
164
|
|
|
165
|
+
# print(
|
|
166
|
+
# f"activated {self.timer:.3f}, {self.px, self.py}, {target.px, target.py}, {target.sprite.width, target.sprite.height}"
|
|
167
|
+
# )
|
|
142
168
|
return True
|
|
143
169
|
|
|
144
170
|
return False
|
mima/objects/world/pickup.py
CHANGED
|
@@ -39,6 +39,7 @@ class Pickup(Dynamic):
|
|
|
39
39
|
|
|
40
40
|
self.collected = False
|
|
41
41
|
self.solid_vs_dyn = False
|
|
42
|
+
self.moves_on_collision = True
|
|
42
43
|
# self.sprite = AnimatedSprite(
|
|
43
44
|
# self.item.tileset_name,
|
|
44
45
|
# self.item.image_name,
|
|
@@ -82,6 +83,8 @@ class Pickup(Dynamic):
|
|
|
82
83
|
return
|
|
83
84
|
|
|
84
85
|
if self.pz != 0:
|
|
86
|
+
|
|
87
|
+
# print("Draw item circle")
|
|
85
88
|
self.engine.backend.fill_circle(
|
|
86
89
|
(self.px - ox + 0.5) * self.sprite.width,
|
|
87
90
|
(self.py - oy + 0.7) * self.sprite.height,
|
|
@@ -90,7 +93,10 @@ class Pickup(Dynamic):
|
|
|
90
93
|
camera_name,
|
|
91
94
|
)
|
|
92
95
|
self.sprite.draw_self(
|
|
93
|
-
self.px - ox,
|
|
96
|
+
self.px - ox,
|
|
97
|
+
self.py - oy - self.pz,
|
|
98
|
+
camera_name,
|
|
99
|
+
draw_to_ui=draw_to_ui,
|
|
94
100
|
)
|
|
95
101
|
# self.engine.backend.draw_partial_sprite(
|
|
96
102
|
# (self.px - ox) * self.item.sprite_width,
|
|
@@ -129,7 +135,7 @@ class Pickup(Dynamic):
|
|
|
129
135
|
else:
|
|
130
136
|
eff = WalkingOnWater(self)
|
|
131
137
|
self.effects.append(eff)
|
|
132
|
-
self.engine.
|
|
138
|
+
self.engine.get_view().add_effect(eff, self.tilemap.name)
|
|
133
139
|
# else:
|
|
134
140
|
# self.attributes.speed_mod = 1.0
|
|
135
141
|
|
mima/objects/world/switch.py
CHANGED
|
@@ -46,10 +46,15 @@ class Switch(Dynamic):
|
|
|
46
46
|
self.listener_ids: List[int] = []
|
|
47
47
|
self.listeners: List[Dynamic] = []
|
|
48
48
|
self.send_initial_signal = initial_signal
|
|
49
|
+
self.cooldown = 0.0
|
|
50
|
+
self.cooldown_reset = 0.8
|
|
49
51
|
|
|
50
52
|
# self._gs_map = {False: GraphicState.OPEN, True: GraphicState.CLOSED}
|
|
51
53
|
|
|
52
54
|
def update(self, elapsed_time: float, target: Optional[Dynamic] = None):
|
|
55
|
+
if self.cooldown > 0.0:
|
|
56
|
+
self.cooldown -= elapsed_time
|
|
57
|
+
|
|
53
58
|
if self.send_initial_signal:
|
|
54
59
|
self.send_signal(self.signal)
|
|
55
60
|
self.send_initial_signal = False
|
|
@@ -71,25 +76,36 @@ class Switch(Dynamic):
|
|
|
71
76
|
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
72
77
|
# if target.is_player().value > 0:
|
|
73
78
|
# print(f"{target.is_player()} talked to me({self.name})")
|
|
79
|
+
if self.cooldown > 0.0:
|
|
80
|
+
return False
|
|
81
|
+
|
|
74
82
|
if (
|
|
75
83
|
nature == Nature.TALK
|
|
76
84
|
and target.type == ObjectType.PLAYER
|
|
77
85
|
and self.visible
|
|
78
86
|
):
|
|
79
87
|
self.state_changed = True
|
|
80
|
-
self.engine.audio.play_sound("switch")
|
|
88
|
+
self.engine.audio.play_sound("switch", 0.2)
|
|
89
|
+
self.cooldown = self.cooldown_reset
|
|
90
|
+
print("Player talked")
|
|
81
91
|
|
|
82
92
|
elif nature == Nature.WALK and target.type == ObjectType.PROJECTILE:
|
|
83
93
|
if self.signal:
|
|
84
94
|
# Projectiles from the right will activate the switch
|
|
85
95
|
if target.px > self.px and target.vx < 0:
|
|
86
96
|
self.state_changed = True
|
|
97
|
+
if "body" not in target.name:
|
|
98
|
+
self.engine.audio.play_sound("switch", 0.2)
|
|
99
|
+
self.cooldown = self.cooldown_reset
|
|
87
100
|
else:
|
|
88
101
|
# Projectiles from the left will (de)activate the switch
|
|
89
|
-
if
|
|
102
|
+
if (
|
|
103
|
+
target.px <= self.px and target.vx > 0
|
|
104
|
+
): # Sword does not activate because vx=0
|
|
90
105
|
self.state_changed = True
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
if "body" not in target.name:
|
|
107
|
+
self.engine.audio.play_sound("switch", 0.2)
|
|
108
|
+
self.cooldown = self.cooldown_reset
|
|
93
109
|
|
|
94
110
|
elif nature == Nature.SIGNAL:
|
|
95
111
|
self.visible = False
|