mima-engine 0.1.5__py3-none-any.whl → 0.2.1__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_assets.py +14 -8
- mima/backend/pygame_audio.py +5 -2
- mima/backend/pygame_backend.py +255 -57
- mima/backend/pygame_camera.py +63 -0
- mima/backend/pygame_events.py +369 -120
- mima/collision.py +182 -111
- mima/engine.py +155 -15
- mima/maps/tiled/tiled_map.py +3 -3
- mima/maps/tiled/tiled_tileset.py +1 -0
- mima/maps/tilemap.py +78 -15
- mima/maps/tileset.py +8 -2
- mima/maps/transition_map.py +6 -8
- mima/mode_engine.py +80 -0
- mima/objects/animated_sprite.py +23 -15
- mima/objects/attributes.py +3 -0
- mima/objects/creature.py +54 -17
- mima/objects/dynamic.py +30 -8
- mima/objects/effects/colorize_screen.py +22 -6
- mima/objects/effects/debug_box.py +124 -0
- mima/objects/effects/light.py +21 -30
- mima/objects/effects/show_sprite.py +39 -0
- mima/objects/effects/walking_on_grass.py +25 -7
- mima/objects/effects/walking_on_water.py +17 -6
- mima/objects/loader.py +24 -13
- mima/objects/projectile.py +21 -6
- mima/objects/sprite.py +7 -8
- mima/objects/world/color_gate.py +5 -2
- mima/objects/world/color_switch.py +12 -6
- mima/objects/world/container.py +17 -8
- mima/objects/world/floor_switch.py +8 -4
- mima/objects/world/gate.py +8 -5
- mima/objects/world/light_source.py +11 -9
- mima/objects/world/logic_gate.py +8 -7
- mima/objects/world/movable.py +72 -28
- mima/objects/world/oneway.py +14 -9
- mima/objects/world/pickup.py +10 -5
- mima/objects/world/switch.py +28 -25
- mima/objects/world/teleport.py +76 -55
- mima/scene_engine.py +19 -20
- mima/scripts/command.py +16 -2
- mima/scripts/commands/change_map.py +23 -4
- mima/scripts/commands/equip_weapon.py +23 -0
- mima/scripts/commands/give_item.py +5 -3
- mima/scripts/commands/move_map.py +9 -9
- mima/scripts/commands/parallel.py +16 -3
- mima/scripts/commands/present_item.py +7 -5
- mima/scripts/commands/screen_fade.py +30 -12
- mima/scripts/commands/serial.py +30 -7
- mima/scripts/commands/set_spawn_map.py +6 -3
- mima/scripts/commands/show_choices.py +16 -7
- mima/scripts/commands/show_dialog.py +110 -3
- mima/scripts/script_processor.py +41 -20
- mima/states/game_state.py +2 -0
- mima/states/memory.py +28 -0
- mima/states/quest.py +2 -3
- mima/types/keys.py +48 -0
- mima/types/mode.py +4 -10
- mima/types/player.py +9 -0
- mima/types/position.py +13 -0
- mima/types/tile_collision.py +11 -0
- mima/types/window.py +44 -0
- mima/usables/item.py +1 -0
- mima/util/colors.py +5 -0
- mima/util/constants.py +6 -0
- mima/util/functions.py +27 -0
- mima/util/input_defaults.py +109 -0
- mima/util/runtime_config.py +234 -30
- mima/util/trading_item.py +20 -0
- mima/view/camera.py +160 -19
- mima/view/mima_mode.py +612 -0
- mima/view/mima_scene.py +225 -0
- mima/view/mima_view.py +12 -0
- mima/view/mima_window.py +153 -0
- {mima_engine-0.1.5.dist-info → mima_engine-0.2.1.dist-info}/METADATA +4 -2
- mima_engine-0.2.1.dist-info/RECORD +128 -0
- {mima_engine-0.1.5.dist-info → mima_engine-0.2.1.dist-info}/WHEEL +1 -1
- mima/view/scene.py +0 -322
- mima_engine-0.1.5.dist-info/RECORD +0 -114
- {mima_engine-0.1.5.dist-info → mima_engine-0.2.1.dist-info}/top_level.txt +0 -0
|
@@ -1,27 +1,27 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
1
3
|
from ...maps.transition_map import TransitionMap
|
|
2
4
|
from ...objects.dynamic import Dynamic
|
|
3
|
-
from ...
|
|
4
|
-
|
|
5
|
-
MOVE_MAP_DURATION,
|
|
6
|
-
TILE_HEIGHT,
|
|
7
|
-
TILE_WIDTH,
|
|
8
|
-
WIDTH,
|
|
9
|
-
)
|
|
5
|
+
from ...types.player import Player
|
|
6
|
+
from ...util.constants import HEIGHT, MOVE_MAP_DURATION, WIDTH
|
|
10
7
|
from ..command import Command
|
|
11
8
|
|
|
12
9
|
|
|
13
10
|
class CommandMoveMap(Command):
|
|
14
11
|
def __init__(
|
|
15
12
|
self,
|
|
13
|
+
*,
|
|
16
14
|
new_map_name: str,
|
|
17
15
|
obj: Dynamic,
|
|
18
16
|
target_px: float,
|
|
19
17
|
target_py: float,
|
|
20
18
|
vx: float,
|
|
21
19
|
vy: float,
|
|
20
|
+
players: Optional[List[Player]] = None,
|
|
22
21
|
):
|
|
23
22
|
super().__init__()
|
|
24
23
|
|
|
24
|
+
self.players = [obj.is_player()]
|
|
25
25
|
self.src_map = self.engine.scene.tilemap
|
|
26
26
|
self.dst_map = self.engine.assets.get_map(new_map_name)
|
|
27
27
|
self.obj: Dynamic = obj
|
|
@@ -129,7 +129,7 @@ class CommandMoveMap(Command):
|
|
|
129
129
|
)
|
|
130
130
|
|
|
131
131
|
def _get_offset_x(self, px: float) -> float:
|
|
132
|
-
visible_tiles = WIDTH /
|
|
132
|
+
visible_tiles = WIDTH / self.engine.rtc.tile_width
|
|
133
133
|
offset = px - visible_tiles / 2.0
|
|
134
134
|
|
|
135
135
|
if offset < 0:
|
|
@@ -140,7 +140,7 @@ class CommandMoveMap(Command):
|
|
|
140
140
|
return offset
|
|
141
141
|
|
|
142
142
|
def _get_offset_y(self, py: float) -> float:
|
|
143
|
-
visible_tiles = HEIGHT /
|
|
143
|
+
visible_tiles = HEIGHT / self.engine.rtc.tile_width - 1
|
|
144
144
|
offset = py - visible_tiles / 2.0
|
|
145
145
|
|
|
146
146
|
if offset < 0:
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from typing import List
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from ...types.player import Player
|
|
2
4
|
from ..command import Command
|
|
3
5
|
|
|
4
6
|
|
|
@@ -7,7 +9,12 @@ class CommandParallel(Command):
|
|
|
7
9
|
ANY_COMPLETED: int = 1
|
|
8
10
|
FIRST_COMPLETED: int = 2
|
|
9
11
|
|
|
10
|
-
def __init__(
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
cmds: List[Command],
|
|
15
|
+
completed_when: int = ALL_COMPLETED,
|
|
16
|
+
players: Optional[List[Player]] = None,
|
|
17
|
+
):
|
|
11
18
|
super().__init__()
|
|
12
19
|
self._cmds: List[Command] = cmds
|
|
13
20
|
self._completed_when: int = completed_when
|
|
@@ -28,7 +35,8 @@ class CommandParallel(Command):
|
|
|
28
35
|
self._check_for_first()
|
|
29
36
|
else:
|
|
30
37
|
raise ValueError(
|
|
31
|
-
f"Unknown value {self._completed_when} for "
|
|
38
|
+
f"Unknown value {self._completed_when} for "
|
|
39
|
+
"attribute _completed_when"
|
|
32
40
|
)
|
|
33
41
|
|
|
34
42
|
def finalize(self):
|
|
@@ -51,3 +59,8 @@ class CommandParallel(Command):
|
|
|
51
59
|
|
|
52
60
|
def _check_for_first(self):
|
|
53
61
|
self.completed = self._cmds[0].completed
|
|
62
|
+
|
|
63
|
+
def set_players(self, players: List[Player]):
|
|
64
|
+
self.players = players
|
|
65
|
+
for cmd in self._cmds:
|
|
66
|
+
cmd.set_players(players)
|
|
@@ -14,14 +14,13 @@ class CommandPresentItem(Command):
|
|
|
14
14
|
def __init__(self, item_name: str, dynamic: Optional[Dynamic] = None):
|
|
15
15
|
super().__init__()
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
dynamic = self.engine.player
|
|
19
|
-
|
|
20
|
-
self._dynamic: Dynamic = dynamic
|
|
17
|
+
self._dynamic: Optional[Dynamic] = dynamic
|
|
21
18
|
self._item_name: str = item_name
|
|
22
19
|
self._item_sprite: Optional[Projectile] = None
|
|
23
20
|
|
|
24
21
|
def start(self):
|
|
22
|
+
if self._dynamic is None:
|
|
23
|
+
self._dynamic = self.engine.get_player(self.players[0])
|
|
25
24
|
item = self.engine.get_item(self._item_name)
|
|
26
25
|
self._item_sprite = Projectile(
|
|
27
26
|
self._dynamic.px,
|
|
@@ -30,6 +29,7 @@ class CommandPresentItem(Command):
|
|
|
30
29
|
0,
|
|
31
30
|
3600,
|
|
32
31
|
self._dynamic.alignment,
|
|
32
|
+
self._dynamic.tilemap,
|
|
33
33
|
)
|
|
34
34
|
self._item_sprite.layer = 2
|
|
35
35
|
self._item_sprite.sprite.name = item.sprite_name
|
|
@@ -42,7 +42,9 @@ class CommandPresentItem(Command):
|
|
|
42
42
|
self._item_sprite.one_hit = False
|
|
43
43
|
self._item_sprite.damage = 0
|
|
44
44
|
|
|
45
|
-
self.engine.
|
|
45
|
+
self.engine.get_view().add_projectile(
|
|
46
|
+
self._item_sprite, self._dynamic.tilemap.name
|
|
47
|
+
)
|
|
46
48
|
self._dynamic.lock_graphic_state(GraphicState.CELEBRATING)
|
|
47
49
|
self.completed = True
|
|
48
50
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
3
|
from ...objects.effects.colorize_screen import ColorizeScreen
|
|
4
|
+
from ...util.colors import BLACK, Color
|
|
4
5
|
from ..command import Command
|
|
5
|
-
from ...util.colors import BLACK,Color
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class CommandScreenFade(Command):
|
|
@@ -11,12 +11,13 @@ class CommandScreenFade(Command):
|
|
|
11
11
|
duration: float = 0.5,
|
|
12
12
|
color: Optional[Color] = None,
|
|
13
13
|
fadein: bool = False,
|
|
14
|
+
map_name: Optional[str] = None,
|
|
14
15
|
):
|
|
15
16
|
super().__init__()
|
|
16
17
|
|
|
17
18
|
self.duration: float = duration
|
|
18
19
|
if color is None:
|
|
19
|
-
color = self.engine.rtc.
|
|
20
|
+
color = self.engine.rtc.color_black
|
|
20
21
|
|
|
21
22
|
self.color: Color = color
|
|
22
23
|
self.fadein: bool = fadein
|
|
@@ -30,16 +31,34 @@ class CommandScreenFade(Command):
|
|
|
30
31
|
self._end = 0
|
|
31
32
|
self._iter = -self._iter
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
self._map_name = map_name
|
|
34
35
|
|
|
35
|
-
self._effect =
|
|
36
|
+
self._effect: Optional[ColorizeScreen] = None
|
|
36
37
|
# self.duration -= 0.1
|
|
37
|
-
self._effect.alpha = self._start
|
|
38
38
|
|
|
39
39
|
def start(self):
|
|
40
|
-
|
|
41
|
-
self.
|
|
42
|
-
|
|
40
|
+
|
|
41
|
+
self._effect = ColorizeScreen(
|
|
42
|
+
cameras=[
|
|
43
|
+
self.engine.get_view().get_camera_name(p) for p in self.players
|
|
44
|
+
]
|
|
45
|
+
)
|
|
46
|
+
self._effect.alpha = self._start
|
|
47
|
+
if self._map_name is None:
|
|
48
|
+
map_names = list(
|
|
49
|
+
set(
|
|
50
|
+
[
|
|
51
|
+
self.engine.get_player(p).tilemap.name
|
|
52
|
+
for p in self.players
|
|
53
|
+
]
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
for map_name in map_names:
|
|
57
|
+
self.engine.get_view().add_effect(self._effect, map_name)
|
|
58
|
+
else:
|
|
59
|
+
self.engine.get_view().add_effect(self._effect, self._map_name)
|
|
60
|
+
for p in self.players:
|
|
61
|
+
self.engine.get_player(p).halt()
|
|
43
62
|
|
|
44
63
|
def update(self, elapsed_time: float):
|
|
45
64
|
self.time_so_far += elapsed_time
|
|
@@ -51,10 +70,9 @@ class CommandScreenFade(Command):
|
|
|
51
70
|
alpha = 255 - alpha
|
|
52
71
|
|
|
53
72
|
self._effect.alpha = min(255, max(0, alpha))
|
|
54
|
-
# print(self, self._effect.alpha)
|
|
55
73
|
|
|
56
|
-
self.
|
|
57
|
-
|
|
74
|
+
for p in self.players:
|
|
75
|
+
self.engine.get_player(p).halt()
|
|
58
76
|
|
|
59
77
|
if self.time_so_far >= self.duration:
|
|
60
78
|
self._effect.alpha = self._end
|
|
@@ -62,4 +80,4 @@ class CommandScreenFade(Command):
|
|
|
62
80
|
|
|
63
81
|
def finalize(self):
|
|
64
82
|
self.completed = True
|
|
65
|
-
self._effect.kill()
|
|
83
|
+
self._effect.kill()
|
mima/scripts/commands/serial.py
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
|
-
from typing import List, Union
|
|
2
1
|
import logging
|
|
2
|
+
from typing import List, Optional, Union
|
|
3
|
+
|
|
4
|
+
from ...types.player import Player
|
|
3
5
|
from ..command import Command
|
|
4
6
|
|
|
5
7
|
LOG = logging.getLogger(__name__)
|
|
6
8
|
|
|
9
|
+
|
|
7
10
|
class CommandSerial(Command):
|
|
8
11
|
START_AND_UPDATE: int = 0
|
|
9
12
|
START_WITHOUT_UPDATE: int = 1
|
|
10
13
|
|
|
11
|
-
def __init__(
|
|
12
|
-
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
cmds: List[Command],
|
|
17
|
+
update_when: Union[int, List[int]] = START_AND_UPDATE,
|
|
18
|
+
players: Optional[List[Player]] = None,
|
|
19
|
+
):
|
|
20
|
+
super().__init__(players)
|
|
13
21
|
self._cmds: List[Command] = cmds
|
|
22
|
+
|
|
14
23
|
self._current: int = 0
|
|
15
24
|
self._update_when: List[int]
|
|
16
|
-
|
|
17
25
|
if not isinstance(update_when, list):
|
|
18
|
-
self._update_when = [
|
|
26
|
+
self._update_when = [
|
|
27
|
+
update_when for _ in range(len(self._cmds) - 1)
|
|
28
|
+
]
|
|
19
29
|
else:
|
|
20
30
|
self._update_when = update_when
|
|
21
31
|
|
|
22
|
-
if len(self._update_when) < len(self._cmds):
|
|
32
|
+
if len(self._update_when) + 1 < len(self._cmds):
|
|
23
33
|
LOG.warning(
|
|
24
34
|
"Unsufficient information for 'update_when' of serial command:"
|
|
25
35
|
f"cmds={self._cmds}, update_when={self._update_when}. Using "
|
|
@@ -31,16 +41,29 @@ class CommandSerial(Command):
|
|
|
31
41
|
|
|
32
42
|
def update(self, delta_time):
|
|
33
43
|
if not self._cmds[self._current].completed:
|
|
44
|
+
# Not completed -> Update current command
|
|
34
45
|
self._cmds[self._current].update(delta_time)
|
|
35
46
|
else:
|
|
47
|
+
# Current command completed -> progress to next
|
|
36
48
|
self._current += 1
|
|
37
49
|
if self._current == len(self._cmds):
|
|
50
|
+
# Reached end? -> Finish serial command
|
|
38
51
|
self.completed = True
|
|
39
52
|
else:
|
|
53
|
+
# End not reached -> call start of next command
|
|
40
54
|
self._cmds[self._current].start()
|
|
41
|
-
if
|
|
55
|
+
if (
|
|
56
|
+
self._update_when[self._current - 1]
|
|
57
|
+
== self.START_AND_UPDATE
|
|
58
|
+
):
|
|
59
|
+
# Start the command already with update
|
|
42
60
|
self._cmds[self._current].update(delta_time)
|
|
43
61
|
|
|
44
62
|
def finalize(self):
|
|
45
63
|
for cmd in self._cmds:
|
|
46
64
|
cmd.finalize()
|
|
65
|
+
|
|
66
|
+
def set_players(self, players: List[Player]):
|
|
67
|
+
self.players = players
|
|
68
|
+
for cmd in self._cmds:
|
|
69
|
+
cmd.set_players(players)
|
|
@@ -8,7 +8,10 @@ class CommandSetSavePosition(Command):
|
|
|
8
8
|
self._py = py
|
|
9
9
|
|
|
10
10
|
def start(self):
|
|
11
|
-
|
|
12
|
-
self.engine.player_state.
|
|
13
|
-
|
|
11
|
+
|
|
12
|
+
self.engine.memory.player_state[self.players[0]].save_map = (
|
|
13
|
+
self._map_name
|
|
14
|
+
)
|
|
15
|
+
self.engine.memory.player_state[self.players[0]].save_px = self._px
|
|
16
|
+
self.engine.memory.player_state[self.players[0]].save_py = self._py
|
|
14
17
|
self.completed = True
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import List
|
|
2
|
+
|
|
2
3
|
from ...scripts.command import Command
|
|
3
4
|
from ...types.keys import Key as K
|
|
5
|
+
from ...types.player import Player
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class CommandShowChoices(Command):
|
|
@@ -20,13 +22,13 @@ class CommandShowChoices(Command):
|
|
|
20
22
|
self._cursor_pos: int = 0
|
|
21
23
|
|
|
22
24
|
def update(self, elapsed_time: float):
|
|
23
|
-
if self.engine.keys.new_key_release(K.UP):
|
|
25
|
+
if self.engine.keys.new_key_release(K.UP, self.players[0]):
|
|
24
26
|
self._cursor_pos = (self._cursor_pos - 1) % len(self._options)
|
|
25
|
-
elif self.engine.keys.new_key_release(K.DOWN):
|
|
27
|
+
elif self.engine.keys.new_key_release(K.DOWN, self.players[0]):
|
|
26
28
|
self._cursor_pos = (self._cursor_pos + 1) % len(self._options)
|
|
27
|
-
elif self.engine.keys.new_key_press(K.A):
|
|
29
|
+
elif self.engine.keys.new_key_press(K.A, self.players[0]):
|
|
28
30
|
self.completed = True
|
|
29
|
-
elif self.engine.keys.new_key_release(K.B):
|
|
31
|
+
elif self.engine.keys.new_key_release(K.B, self.players[0]):
|
|
30
32
|
self._cursor_pos = self._default_option
|
|
31
33
|
self.completed = True
|
|
32
34
|
|
|
@@ -36,8 +38,15 @@ class CommandShowChoices(Command):
|
|
|
36
38
|
lines.append(f"> {opt}")
|
|
37
39
|
else:
|
|
38
40
|
lines.append(f" {opt}")
|
|
39
|
-
|
|
40
|
-
self.engine.
|
|
41
|
+
# for p in self.players:
|
|
42
|
+
self.engine.get_view().show_dialog(lines, self.players[0])
|
|
41
43
|
|
|
42
44
|
def finalize(self):
|
|
43
|
-
self.engine.script.add_command(
|
|
45
|
+
self.engine.script.add_command(
|
|
46
|
+
self._replies[self._cursor_pos], players=self.players
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def set_players(self, players: List[Player]):
|
|
50
|
+
for cmd in self._replies:
|
|
51
|
+
cmd.set_players(players)
|
|
52
|
+
self.players = players
|
|
@@ -1,11 +1,118 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, List, Optional
|
|
4
|
+
|
|
2
5
|
from ...scripts.command import Command
|
|
6
|
+
from ...util.constants import DIALOG_CHARS_PER_LINE, DIALOG_N_LINES
|
|
7
|
+
from ...util.functions import wrap_text
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from ...types.player import Player
|
|
3
11
|
|
|
4
12
|
|
|
5
13
|
class CommandShowDialog(Command):
|
|
6
|
-
def __init__(
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
lines: List[str],
|
|
17
|
+
*,
|
|
18
|
+
no_auto_wrap: bool = False,
|
|
19
|
+
chars_per_line: int = DIALOG_CHARS_PER_LINE,
|
|
20
|
+
n_lines: int = DIALOG_N_LINES,
|
|
21
|
+
):
|
|
7
22
|
super().__init__()
|
|
23
|
+
|
|
8
24
|
self.lines: List[str] = lines
|
|
25
|
+
self._current_lines: List[str] = []
|
|
26
|
+
self._no_auto_wrap: bool = no_auto_wrap
|
|
27
|
+
self._chars_per_line: int = chars_per_line
|
|
28
|
+
self._n_lines: int = n_lines
|
|
29
|
+
self._row: int = 0
|
|
30
|
+
self._char: int = 0
|
|
31
|
+
self._first_row: int = 0
|
|
32
|
+
self._last_row: int = self._n_lines
|
|
33
|
+
|
|
34
|
+
self._timer_reset = 0.01
|
|
35
|
+
self._timer = self._timer_reset
|
|
36
|
+
self._auto_scroll: bool = True
|
|
37
|
+
self._progress: bool = False
|
|
38
|
+
self._lines_changed: bool = True
|
|
9
39
|
|
|
10
40
|
def start(self):
|
|
11
|
-
self.
|
|
41
|
+
if not self._no_auto_wrap:
|
|
42
|
+
one_liner = ""
|
|
43
|
+
for line in self.lines:
|
|
44
|
+
one_liner += f"{line.strip()} "
|
|
45
|
+
|
|
46
|
+
self.lines = wrap_text(one_liner, self._chars_per_line)
|
|
47
|
+
self._current_lines = [self.lines[0][0]]
|
|
48
|
+
self._char += 1
|
|
49
|
+
for p in self.players:
|
|
50
|
+
self.engine.get_view().show_dialog(self._current_lines, p)
|
|
51
|
+
|
|
52
|
+
def update(self, elapsed_time: float):
|
|
53
|
+
if self._auto_scroll:
|
|
54
|
+
self._timer -= elapsed_time
|
|
55
|
+
if self._timer <= 0.0:
|
|
56
|
+
self._timer += self._timer_reset
|
|
57
|
+
|
|
58
|
+
self._current_lines = []
|
|
59
|
+
for r in range(self._first_row, self._last_row):
|
|
60
|
+
if r < self._row:
|
|
61
|
+
self._current_lines.append(self.lines[r])
|
|
62
|
+
continue
|
|
63
|
+
|
|
64
|
+
line = ""
|
|
65
|
+
|
|
66
|
+
for c in range(self._char + 1):
|
|
67
|
+
if c + 1 >= self._char or c + 1 >= len(self.lines[r]):
|
|
68
|
+
break
|
|
69
|
+
line += self.lines[r][c]
|
|
70
|
+
|
|
71
|
+
self._current_lines.append(line)
|
|
72
|
+
|
|
73
|
+
if r + 1 >= self._row:
|
|
74
|
+
break
|
|
75
|
+
|
|
76
|
+
self._char += 1
|
|
77
|
+
if self._char >= self._chars_per_line or self._char >= len(
|
|
78
|
+
self.lines[r]
|
|
79
|
+
):
|
|
80
|
+
self._char = 0
|
|
81
|
+
self._row += 1
|
|
82
|
+
|
|
83
|
+
if self._row >= self._n_lines + self._first_row:
|
|
84
|
+
self._first_row += 1
|
|
85
|
+
self._last_row += 1
|
|
86
|
+
if self._row >= len(self.lines):
|
|
87
|
+
self._auto_scroll = False
|
|
88
|
+
|
|
89
|
+
# print(f"'{self._current_lines}'")
|
|
90
|
+
for p in self.players:
|
|
91
|
+
self.engine.get_view().show_dialog(self._current_lines, p)
|
|
92
|
+
else:
|
|
93
|
+
if self._lines_changed:
|
|
94
|
+
self._current_lines = []
|
|
95
|
+
for r in range(self._first_row, self._last_row):
|
|
96
|
+
if r >= len(self.lines):
|
|
97
|
+
break
|
|
98
|
+
self._current_lines.append(self.lines[r])
|
|
99
|
+
for p in self.players:
|
|
100
|
+
self.engine.get_view().show_dialog(self._current_lines, p)
|
|
101
|
+
self._lines_changed = False
|
|
102
|
+
|
|
103
|
+
if self._progress:
|
|
104
|
+
self._first_row += self._n_lines
|
|
105
|
+
self._last_row += self._n_lines
|
|
106
|
+
self._progress = False
|
|
107
|
+
self._lines_changed = True
|
|
108
|
+
|
|
109
|
+
def can_complete(self, force: bool = False) -> bool:
|
|
110
|
+
if force:
|
|
111
|
+
return True
|
|
112
|
+
if self._auto_scroll:
|
|
113
|
+
self._auto_scroll = False
|
|
114
|
+
elif self._last_row >= len(self.lines):
|
|
115
|
+
return True
|
|
116
|
+
else:
|
|
117
|
+
self._progress = True
|
|
118
|
+
return False
|
mima/scripts/script_processor.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, List
|
|
3
|
+
from typing import TYPE_CHECKING, Dict, List, Optional
|
|
4
4
|
|
|
5
|
+
from ..types.player import Player
|
|
5
6
|
from .command import Command
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
@@ -12,29 +13,49 @@ class ScriptProcessor:
|
|
|
12
13
|
engine: MimaEngine
|
|
13
14
|
|
|
14
15
|
def __init__(self):
|
|
15
|
-
self.commands: List[Command] =
|
|
16
|
-
self.user_control_enabled: bool = True
|
|
16
|
+
self.commands: Dict[Player : List[Command]] = {}
|
|
17
17
|
|
|
18
|
-
def add_command(
|
|
19
|
-
self
|
|
18
|
+
def add_command(
|
|
19
|
+
self, cmd: Command, *, players: Optional[List[Player]] = None
|
|
20
|
+
):
|
|
21
|
+
if players is not None and players:
|
|
22
|
+
cmd.set_players(players)
|
|
23
|
+
|
|
24
|
+
for p in cmd.players:
|
|
25
|
+
self.commands.setdefault(p, []).append(cmd)
|
|
26
|
+
# self.commands.append(cmd)
|
|
20
27
|
|
|
21
28
|
def process_command(self, elapsed_time: float):
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
# for p in Player:
|
|
30
|
+
# self.engine.trigger_script(False, p)
|
|
31
|
+
# for cmd in self.commands:
|
|
32
|
+
# if p in cmd.players or Player.P0 in cmd.players:
|
|
33
|
+
# self.engine.trigger_script(True, p)
|
|
34
|
+
# break
|
|
35
|
+
for p in self.commands:
|
|
36
|
+
if self.commands[p]:
|
|
37
|
+
self.engine.trigger_script(True, p)
|
|
38
|
+
if not self.commands[p][0].completed:
|
|
39
|
+
if not self.commands[p][0].started:
|
|
40
|
+
self.commands[p][0].start()
|
|
41
|
+
self.commands[p][0].started = True
|
|
42
|
+
else:
|
|
43
|
+
self.commands[p][0].update(elapsed_time)
|
|
28
44
|
else:
|
|
29
|
-
self.commands[0].
|
|
45
|
+
self.commands[p][0].finalize()
|
|
46
|
+
self.commands[p].pop(0)
|
|
47
|
+
self.engine.trigger_script(False, p)
|
|
30
48
|
else:
|
|
31
|
-
self.
|
|
32
|
-
self.commands.pop(0)
|
|
49
|
+
self.engine.trigger_script(False, p)
|
|
33
50
|
|
|
34
|
-
def complete_command(self, force: bool = False):
|
|
35
|
-
if self.commands:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
def complete_command(self, player: Player, force: bool = False):
|
|
52
|
+
if self.commands[player]:
|
|
53
|
+
# for cmd in self.commands:
|
|
54
|
+
# if player in cmd.players or Player.P0 in cmd.players:
|
|
55
|
+
|
|
56
|
+
if self.commands[player][0].can_complete(force):
|
|
57
|
+
self.commands[player][0].completed = True
|
|
40
58
|
return True
|
|
59
|
+
else:
|
|
60
|
+
return False
|
|
61
|
+
return True
|
mima/states/game_state.py
CHANGED
|
@@ -82,6 +82,7 @@ class GameState:
|
|
|
82
82
|
filename = os.path.join(
|
|
83
83
|
os.path.split(filename)[0], "autosave.json"
|
|
84
84
|
)
|
|
85
|
+
self.save_value("savefile_name", "autosave")
|
|
85
86
|
self.save_value("player__pos_x", 5.0)
|
|
86
87
|
self.save_value("player__pos_y", 5.0)
|
|
87
88
|
self.save_value(
|
|
@@ -131,6 +132,7 @@ def convert(value, astype):
|
|
|
131
132
|
|
|
132
133
|
|
|
133
134
|
def load_saved_games(save_path, save_file_name):
|
|
135
|
+
os.makedirs(save_path, exist_ok=True)
|
|
134
136
|
all_games = {}
|
|
135
137
|
if not os.path.isdir(save_path):
|
|
136
138
|
LOG.warning(f"Save folder does not exist: {save_path}")
|
mima/states/memory.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List
|
|
4
|
+
|
|
5
|
+
from ..types.player import Player
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from ..objects.creature import Creature
|
|
9
|
+
from ..usables.item import Item
|
|
10
|
+
from .quest import Quest
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Memory:
|
|
14
|
+
def __init__(self):
|
|
15
|
+
self.player: Dict[Player, Creature] = {}
|
|
16
|
+
self.items: Dict[str, Any] = {}
|
|
17
|
+
self.quests: List[Quest] = []
|
|
18
|
+
self.teleport_active: Dict[Player, bool] = {p: False for p in Player}
|
|
19
|
+
self.dialog_active: Dict[Player, bool] = {p: False for p in Player}
|
|
20
|
+
self.script_active: Dict[Player, bool] = {p: False for p in Player}
|
|
21
|
+
self.player_collision_active: Dict[Player, bool] = {
|
|
22
|
+
p: False for p in Player
|
|
23
|
+
}
|
|
24
|
+
self.bag: Dict[Player, List[Item]] = {p: [] for p in Player}
|
|
25
|
+
self.map_name: Dict[Player, str] = {}
|
|
26
|
+
|
|
27
|
+
self.last_spawn_px: Dict[Player, float] = {p: 0.0 for p in Player}
|
|
28
|
+
self.last_spawn_py: Dict[Player, float] = {p: 0.0 for p in Player}
|
mima/states/quest.py
CHANGED
|
@@ -8,6 +8,7 @@ if TYPE_CHECKING:
|
|
|
8
8
|
from ..engine.mima_engine import MimaEngine
|
|
9
9
|
from ..objects.dynamic import Dynamic
|
|
10
10
|
from ..types.nature import Nature
|
|
11
|
+
from ..types.player import Player
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class Quest:
|
|
@@ -21,9 +22,7 @@ class Quest:
|
|
|
21
22
|
self.completed: bool = False
|
|
22
23
|
self.state: int = 0
|
|
23
24
|
|
|
24
|
-
def on_interaction(
|
|
25
|
-
self, dynamics: List[Dynamic], target: Dynamic, nature: Nature
|
|
26
|
-
):
|
|
25
|
+
def on_interaction(self, target: Dynamic, nature: Nature, player: Player):
|
|
27
26
|
return False
|
|
28
27
|
|
|
29
28
|
def populate_dynamics(self, dynamics: List[Dynamic], map_name: str):
|
mima/types/keys.py
CHANGED
|
@@ -14,3 +14,51 @@ class Key(Enum):
|
|
|
14
14
|
L = 9
|
|
15
15
|
START = 10
|
|
16
16
|
SELECT = 11
|
|
17
|
+
P1_UP = 12
|
|
18
|
+
P1_DOWN = 13
|
|
19
|
+
P1_LEFT = 14
|
|
20
|
+
P1_RIGHT = 15
|
|
21
|
+
P1_A = 16
|
|
22
|
+
P1_B = 17
|
|
23
|
+
P1_X = 18
|
|
24
|
+
P1_Y = 19
|
|
25
|
+
P1_R = 20
|
|
26
|
+
P1_L = 21
|
|
27
|
+
P1_START = 22
|
|
28
|
+
P1_SELECT = 23
|
|
29
|
+
P2_UP = 24
|
|
30
|
+
P2_DOWN = 25
|
|
31
|
+
P2_LEFT = 26
|
|
32
|
+
P2_RIGHT = 27
|
|
33
|
+
P2_A = 28
|
|
34
|
+
P2_B = 29
|
|
35
|
+
P2_X = 30
|
|
36
|
+
P2_Y = 31
|
|
37
|
+
P2_R = 32
|
|
38
|
+
P2_L = 33
|
|
39
|
+
P2_START = 34
|
|
40
|
+
P2_SELECT = 35
|
|
41
|
+
P3_UP = 36
|
|
42
|
+
P3_DOWN = 37
|
|
43
|
+
P3_LEFT = 38
|
|
44
|
+
P3_RIGHT = 39
|
|
45
|
+
P3_A = 40
|
|
46
|
+
P3_B = 41
|
|
47
|
+
P3_X = 42
|
|
48
|
+
P3_Y = 43
|
|
49
|
+
P3_R = 44
|
|
50
|
+
P3_L = 45
|
|
51
|
+
P3_START = 46
|
|
52
|
+
P3_SELECT = 47
|
|
53
|
+
P4_UP = 48
|
|
54
|
+
P4_DOWN = 49
|
|
55
|
+
P4_LEFT = 50
|
|
56
|
+
P4_RIGHT = 51
|
|
57
|
+
P4_A = 52
|
|
58
|
+
P4_B = 53
|
|
59
|
+
P4_X = 54
|
|
60
|
+
P4_Y = 55
|
|
61
|
+
P4_R = 56
|
|
62
|
+
P4_L = 57
|
|
63
|
+
P4_START = 58
|
|
64
|
+
P4_SELECT = 59
|
mima/types/mode.py
CHANGED
|
@@ -3,13 +3,7 @@ from enum import Enum
|
|
|
3
3
|
|
|
4
4
|
class Mode(Enum):
|
|
5
5
|
LOADING = 0
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
INVENTORY = 5
|
|
11
|
-
SHOP = 6
|
|
12
|
-
GAME_OVER = 7
|
|
13
|
-
TITLE_SETTINGS = 8
|
|
14
|
-
CONTROLS = 9
|
|
15
|
-
COMBAT = 10
|
|
6
|
+
MENU = 1
|
|
7
|
+
SESSION = 2
|
|
8
|
+
COMBAT = 3
|
|
9
|
+
INVENTORY = 4
|