mima-engine 0.1.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.
Potentially problematic release.
This version of mima-engine might be problematic. Click here for more details.
- mima/__init__.py +1 -0
- mima/backend/__init__.py +1 -0
- mima/backend/pygame_assets.py +345 -0
- mima/backend/pygame_audio.py +75 -0
- mima/backend/pygame_backend.py +399 -0
- mima/backend/pygame_events.py +430 -0
- mima/collision.py +237 -0
- mima/engine.py +197 -0
- mima/maps/__init__.py +0 -0
- mima/maps/template.py +41 -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 +45 -0
- mima/maps/tilemap.py +159 -0
- mima/maps/tileset.py +32 -0
- mima/maps/tileset_info.py +9 -0
- mima/maps/transition_map.py +148 -0
- mima/objects/__init__.py +0 -0
- mima/objects/animated_sprite.py +198 -0
- mima/objects/attribute_effect.py +26 -0
- mima/objects/attributes.py +123 -0
- mima/objects/creature.py +332 -0
- mima/objects/dynamic.py +182 -0
- mima/objects/effects/__init__.py +0 -0
- mima/objects/effects/colorize_screen.py +36 -0
- mima/objects/effects/light.py +107 -0
- mima/objects/effects/walking_on_grass.py +38 -0
- mima/objects/effects/walking_on_water.py +41 -0
- mima/objects/loader.py +103 -0
- mima/objects/projectile.py +86 -0
- mima/objects/sprite.py +110 -0
- mima/objects/world/__init__.py +0 -0
- mima/objects/world/color_gate.py +68 -0
- mima/objects/world/color_switch.py +105 -0
- mima/objects/world/container.py +171 -0
- mima/objects/world/floor_switch.py +111 -0
- mima/objects/world/gate.py +174 -0
- mima/objects/world/light_source.py +124 -0
- mima/objects/world/logic_gate.py +163 -0
- mima/objects/world/movable.py +338 -0
- mima/objects/world/oneway.py +168 -0
- mima/objects/world/pickup.py +88 -0
- mima/objects/world/switch.py +165 -0
- mima/objects/world/teleport.py +288 -0
- mima/scene_engine.py +79 -0
- mima/scripts/__init__.py +2 -0
- mima/scripts/command.py +24 -0
- mima/scripts/commands/__init__.py +0 -0
- mima/scripts/commands/add_quest.py +19 -0
- mima/scripts/commands/change_map.py +15 -0
- mima/scripts/commands/close_dialog.py +8 -0
- mima/scripts/commands/give_item.py +24 -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 +57 -0
- mima/scripts/commands/parallel.py +53 -0
- mima/scripts/commands/play_sound.py +13 -0
- mima/scripts/commands/present_item.py +51 -0
- mima/scripts/commands/progress_quest.py +12 -0
- mima/scripts/commands/quit_game.py +8 -0
- mima/scripts/commands/save_game.py +13 -0
- mima/scripts/commands/screen_fade.py +65 -0
- mima/scripts/commands/serial.py +46 -0
- mima/scripts/commands/set_facing_direction.py +21 -0
- mima/scripts/commands/set_spawn_map.py +14 -0
- mima/scripts/commands/show_choices.py +43 -0
- mima/scripts/commands/show_dialog.py +11 -0
- mima/scripts/commands/take_coins.py +23 -0
- mima/scripts/script_processor.py +40 -0
- mima/states/__init__.py +0 -0
- mima/states/game_state.py +162 -0
- mima/states/quest.py +72 -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 +22 -0
- mima/types/keys.py +16 -0
- mima/types/mode.py +15 -0
- mima/types/nature.py +12 -0
- mima/types/object.py +22 -0
- mima/types/start.py +7 -0
- mima/types/terrain.py +9 -0
- mima/types/weapon_slot.py +6 -0
- mima/usables/__init__.py +0 -0
- mima/usables/item.py +31 -0
- mima/usables/weapon.py +48 -0
- mima/util/__init__.py +1 -0
- mima/util/colors.py +45 -0
- mima/util/constants.py +47 -0
- mima/util/functions.py +13 -0
- mima/util/input_defaults.py +49 -0
- mima/util/logging.py +51 -0
- mima/util/property.py +8 -0
- mima/util/runtime_config.py +133 -0
- mima/view/__init__.py +0 -0
- mima/view/camera.py +51 -0
- mima/view/scene.py +350 -0
- mima_engine-0.1.0.dist-info/METADATA +14 -0
- mima_engine-0.1.0.dist-info/RECORD +114 -0
- mima_engine-0.1.0.dist-info/WHEEL +5 -0
- mima_engine-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from ...objects.dynamic import Dynamic
|
|
2
|
+
from ...types.nature import Nature
|
|
3
|
+
from ...types.object import ObjectType
|
|
4
|
+
from ...types.terrain import Terrain
|
|
5
|
+
from ...util.colors import BLACK
|
|
6
|
+
from ..effects.walking_on_grass import WalkingOnGrass
|
|
7
|
+
from ..effects.walking_on_water import WalkingOnWater
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Pickup(Dynamic):
|
|
11
|
+
def __init__(self, px: float, py: float, item_name: str, dyn_id=-1):
|
|
12
|
+
super().__init__("Pickup", px, py, dyn_id)
|
|
13
|
+
self.type: ObjectType = ObjectType.PICKUP
|
|
14
|
+
self.item = self.engine.get_item(item_name)
|
|
15
|
+
self.collected = False
|
|
16
|
+
self.solid_vs_dyn = False
|
|
17
|
+
|
|
18
|
+
def update(self, elapsed_time: float, target=None):
|
|
19
|
+
if self.collected:
|
|
20
|
+
self.kill()
|
|
21
|
+
else:
|
|
22
|
+
self._handle_terrain(elapsed_time)
|
|
23
|
+
|
|
24
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
25
|
+
if self.collected:
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
if target.type == ObjectType.PLAYER:
|
|
29
|
+
if self.item.on_interaction(target):
|
|
30
|
+
if self.engine.give_item(self.item):
|
|
31
|
+
self.collected = True
|
|
32
|
+
return True
|
|
33
|
+
else:
|
|
34
|
+
self.collected = True
|
|
35
|
+
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
def draw_self(self, ox: float, oy: float):
|
|
39
|
+
if self.collected:
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
if self.pz != 0:
|
|
43
|
+
self.engine.backend.fill_circle(
|
|
44
|
+
(self.px - ox + 0.5) * self.item.sprite_width,
|
|
45
|
+
(self.py - oy + 0.7) * self.item.sprite_height,
|
|
46
|
+
0.2875 * self.item.sprite_width,
|
|
47
|
+
BLACK,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
self.engine.backend.draw_partial_sprite(
|
|
51
|
+
(self.px - ox) * self.item.sprite_width,
|
|
52
|
+
(self.py - oy - self.pz) * self.item.sprite_height,
|
|
53
|
+
self.item.sprite_name,
|
|
54
|
+
self.item.sprite_ox * self.item.sprite_width,
|
|
55
|
+
self.item.sprite_oy * self.item.sprite_height,
|
|
56
|
+
self.item.sprite_width,
|
|
57
|
+
self.item.sprite_height,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def _handle_terrain(self, elapsed_time: float):
|
|
61
|
+
"""Method is duplicated."""
|
|
62
|
+
e2rm = []
|
|
63
|
+
for effect in self.effects:
|
|
64
|
+
if isinstance(effect, WalkingOnGrass):
|
|
65
|
+
if self.walking_on == Terrain.DEFAULT:
|
|
66
|
+
e2rm.append(effect)
|
|
67
|
+
|
|
68
|
+
for effect in e2rm:
|
|
69
|
+
self.effects.remove(effect)
|
|
70
|
+
|
|
71
|
+
if self.walking_on in [Terrain.GRASS, Terrain.SHALLOW_WATER]:
|
|
72
|
+
# self.attributes.speed_mod = 0.7
|
|
73
|
+
effect_active = False
|
|
74
|
+
for effect in self.effects:
|
|
75
|
+
if isinstance(effect, (WalkingOnGrass, WalkingOnWater)):
|
|
76
|
+
effect_active = True
|
|
77
|
+
effect.renew = True
|
|
78
|
+
break
|
|
79
|
+
|
|
80
|
+
if not effect_active:
|
|
81
|
+
if self.walking_on == Terrain.GRASS:
|
|
82
|
+
eff = WalkingOnGrass(self)
|
|
83
|
+
else:
|
|
84
|
+
eff = WalkingOnWater(self)
|
|
85
|
+
self.effects.append(eff)
|
|
86
|
+
self.engine.scene.add_effect(eff)
|
|
87
|
+
# else:
|
|
88
|
+
# self.attributes.speed_mod = 1.0
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from typing import List, Optional, Union
|
|
2
|
+
|
|
3
|
+
from ...types.alignment import Alignment
|
|
4
|
+
from ...types.direction import Direction
|
|
5
|
+
from ...types.graphic_state import GraphicState
|
|
6
|
+
from ...types.nature import Nature
|
|
7
|
+
from ...types.object import ObjectType
|
|
8
|
+
from ...util.constants import TILE_HEIGHT, TILE_WIDTH
|
|
9
|
+
from ..animated_sprite import AnimatedSprite
|
|
10
|
+
from ..dynamic import Dynamic
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Switch(Dynamic):
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
px: float,
|
|
17
|
+
py: float,
|
|
18
|
+
tileset_name: str,
|
|
19
|
+
image_name: str,
|
|
20
|
+
sprite_name: str,
|
|
21
|
+
facing_direction: Direction,
|
|
22
|
+
graphic_state: GraphicState,
|
|
23
|
+
initial_signal=True,
|
|
24
|
+
dyn_id=-1,
|
|
25
|
+
name="Switch",
|
|
26
|
+
):
|
|
27
|
+
assert graphic_state in [GraphicState.OPEN, GraphicState.CLOSED], (
|
|
28
|
+
f"graphic_state of Switch {name}{dyn_id} must be either 'open'"
|
|
29
|
+
f" or 'closed', but it {graphic_state}"
|
|
30
|
+
)
|
|
31
|
+
super().__init__(name, px, py, dyn_id)
|
|
32
|
+
|
|
33
|
+
self.sprite = AnimatedSprite(
|
|
34
|
+
tileset_name,
|
|
35
|
+
image_name,
|
|
36
|
+
sprite_name,
|
|
37
|
+
graphic_state,
|
|
38
|
+
facing_direction,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
self.type = ObjectType.SWITCH
|
|
42
|
+
self.alignment = Alignment.NEUTRAL
|
|
43
|
+
self.graphic_state = graphic_state
|
|
44
|
+
self.facing_direction = facing_direction
|
|
45
|
+
self.signal = self.graphic_state == GraphicState.CLOSED
|
|
46
|
+
self.listener_ids: List[int] = []
|
|
47
|
+
self.listeners: List[Dynamic] = []
|
|
48
|
+
self.send_initial_signal = initial_signal
|
|
49
|
+
|
|
50
|
+
# self._gs_map = {False: GraphicState.OPEN, True: GraphicState.CLOSED}
|
|
51
|
+
|
|
52
|
+
def update(self, elapsed_time: float, target: Optional[Dynamic] = None):
|
|
53
|
+
if self.send_initial_signal:
|
|
54
|
+
self.send_signal(self.signal)
|
|
55
|
+
self.send_initial_signal = False
|
|
56
|
+
|
|
57
|
+
self.solid_vs_dyn = self.visible
|
|
58
|
+
self.graphic_state = (
|
|
59
|
+
GraphicState.CLOSED if self.signal else GraphicState.OPEN
|
|
60
|
+
)
|
|
61
|
+
self.sprite.update(
|
|
62
|
+
elapsed_time, self.facing_direction, self.graphic_state
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def draw_self(self, ox: float, oy: float):
|
|
66
|
+
if not self.visible:
|
|
67
|
+
# print(f"{self.name} is not visible")
|
|
68
|
+
return
|
|
69
|
+
self.sprite.draw_self(self.px - ox, self.py - oy)
|
|
70
|
+
|
|
71
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
72
|
+
if (
|
|
73
|
+
nature == Nature.TALK
|
|
74
|
+
and target.type == ObjectType.PLAYER
|
|
75
|
+
and self.visible
|
|
76
|
+
):
|
|
77
|
+
self.state_changed = True
|
|
78
|
+
self.engine.audio.play_sound("switch")
|
|
79
|
+
|
|
80
|
+
elif nature == Nature.WALK and target.type == ObjectType.PROJECTILE:
|
|
81
|
+
if self.signal:
|
|
82
|
+
# Projectiles from the right will activate the switch
|
|
83
|
+
if target.px > self.px and target.vx < 0:
|
|
84
|
+
self.state_changed = True
|
|
85
|
+
else:
|
|
86
|
+
# Projectiles from the left will (de)activate the switch
|
|
87
|
+
if target.px <= self.px and target.vx > 0:
|
|
88
|
+
self.state_changed = True
|
|
89
|
+
if "body" not in target.name:
|
|
90
|
+
self.engine.audio.play_sound("switch")
|
|
91
|
+
|
|
92
|
+
elif nature == Nature.SIGNAL:
|
|
93
|
+
self.visible = False
|
|
94
|
+
return True
|
|
95
|
+
|
|
96
|
+
elif nature == Nature.NO_SIGNAL:
|
|
97
|
+
self.visible = True
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
if self.state_changed:
|
|
101
|
+
self.signal = not self.signal
|
|
102
|
+
self.send_signal(self.signal)
|
|
103
|
+
|
|
104
|
+
if target.type == ObjectType.PROJECTILE:
|
|
105
|
+
target.kill()
|
|
106
|
+
return True
|
|
107
|
+
return False
|
|
108
|
+
|
|
109
|
+
def send_signal(self, nature: Union[Nature, bool]):
|
|
110
|
+
if isinstance(nature, bool):
|
|
111
|
+
nature = Nature.SIGNAL if nature else Nature.NO_SIGNAL
|
|
112
|
+
|
|
113
|
+
for listener in self.listeners:
|
|
114
|
+
listener.on_interaction(self, nature)
|
|
115
|
+
|
|
116
|
+
if (
|
|
117
|
+
not self.send_initial_signal
|
|
118
|
+
and abs(self.engine.player.px - self.px)
|
|
119
|
+
< (self.engine.backend.render_width // (TILE_WIDTH * 2))
|
|
120
|
+
and abs(self.engine.player.py - self.py)
|
|
121
|
+
< (self.engine.backend.render_height // (TILE_HEIGHT * 2))
|
|
122
|
+
):
|
|
123
|
+
print(
|
|
124
|
+
(
|
|
125
|
+
self.engine.player.px - self.px,
|
|
126
|
+
self.engine.player.py - self.py,
|
|
127
|
+
),
|
|
128
|
+
(
|
|
129
|
+
self.engine.backend.render_width // (TILE_WIDTH * 2),
|
|
130
|
+
self.engine.backend.render_height // (TILE_HEIGHT * 2),
|
|
131
|
+
),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
@staticmethod
|
|
135
|
+
def load_from_tiled_object(obj, px, py, width, height):
|
|
136
|
+
switch = Switch(
|
|
137
|
+
px=px,
|
|
138
|
+
py=py,
|
|
139
|
+
tileset_name=obj.get_string("tileset_name"),
|
|
140
|
+
image_name=obj.get_string("tileset_name"),
|
|
141
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
142
|
+
graphic_state=GraphicState[
|
|
143
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
144
|
+
],
|
|
145
|
+
facing_direction=Direction[
|
|
146
|
+
obj.get_string("facing_direction", "south").upper()
|
|
147
|
+
],
|
|
148
|
+
initial_signal=obj.get_bool("initial_signal", True),
|
|
149
|
+
dyn_id=obj.object_id,
|
|
150
|
+
name=obj.name,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
switch.sprite.width = int(width * TILE_WIDTH)
|
|
154
|
+
switch.sprite.height = int(height * TILE_HEIGHT)
|
|
155
|
+
|
|
156
|
+
ctr = 1
|
|
157
|
+
while True:
|
|
158
|
+
key = f"output{ctr}"
|
|
159
|
+
listener_id = obj.get_int(key, -1)
|
|
160
|
+
if listener_id < 0:
|
|
161
|
+
break
|
|
162
|
+
switch.listener_ids.append(listener_id)
|
|
163
|
+
ctr += 1
|
|
164
|
+
|
|
165
|
+
return [switch]
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import logging
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
from ...scripts.commands.change_map import CommandChangeMap
|
|
6
|
+
from ...scripts.commands.move_map import CommandMoveMap
|
|
7
|
+
from ...scripts.commands.parallel import CommandParallel
|
|
8
|
+
from ...scripts.commands.screen_fade import CommandScreenFade
|
|
9
|
+
from ...scripts.commands.serial import CommandSerial
|
|
10
|
+
from ...scripts.commands.set_facing_direction import CommandSetFacingDirection
|
|
11
|
+
from ...types.direction import Direction
|
|
12
|
+
from ...types.graphic_state import GraphicState
|
|
13
|
+
from ...types.nature import Nature
|
|
14
|
+
from ...types.object import ObjectType
|
|
15
|
+
from ...util.colors import RED
|
|
16
|
+
from ...util.constants import TILE_HEIGHT, TILE_WIDTH
|
|
17
|
+
from ..animated_sprite import AnimatedSprite
|
|
18
|
+
from ..dynamic import Dynamic
|
|
19
|
+
|
|
20
|
+
LOG = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Teleport(Dynamic):
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
px: float,
|
|
27
|
+
py: float,
|
|
28
|
+
tileset_name: str,
|
|
29
|
+
image_name: str,
|
|
30
|
+
sprite_name: str,
|
|
31
|
+
facing_direction: Direction,
|
|
32
|
+
graphic_state: GraphicState,
|
|
33
|
+
dst_map_name: str,
|
|
34
|
+
dst_px: float,
|
|
35
|
+
dst_py: float,
|
|
36
|
+
direction: Direction,
|
|
37
|
+
invert_exit_direction: bool = False,
|
|
38
|
+
relative: bool = False,
|
|
39
|
+
sliding: bool = False,
|
|
40
|
+
vertical: bool = False,
|
|
41
|
+
dyn_id: int = -1,
|
|
42
|
+
name="Teleport",
|
|
43
|
+
):
|
|
44
|
+
super().__init__(name, px, py, dyn_id)
|
|
45
|
+
|
|
46
|
+
self.sprite = AnimatedSprite(
|
|
47
|
+
tileset_name, image_name, sprite_name, graphic_state, facing_direction
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
self.type = ObjectType.TELEPORT
|
|
51
|
+
self.graphic_state = graphic_state
|
|
52
|
+
self.facing_direction = facing_direction
|
|
53
|
+
self.solid_vs_dyn = False
|
|
54
|
+
self.solid_vs_map = False
|
|
55
|
+
|
|
56
|
+
self.dst_px: float = dst_px
|
|
57
|
+
self.dst_py: float = dst_py
|
|
58
|
+
self.dst_map_name: str = dst_map_name
|
|
59
|
+
self.has_sprite = self.sprite.name != ""
|
|
60
|
+
self.teleport_direction: Direction = direction
|
|
61
|
+
|
|
62
|
+
self.visible = True
|
|
63
|
+
self.invert_exit_direction = invert_exit_direction
|
|
64
|
+
self.relative = relative
|
|
65
|
+
self.sliding = sliding
|
|
66
|
+
self.vertical = vertical
|
|
67
|
+
self.triggered = False
|
|
68
|
+
self.sfx_on_trigger: str = ""
|
|
69
|
+
|
|
70
|
+
def update(self, elapsed_time: float, target: Optional[Dynamic] = None):
|
|
71
|
+
self.sprite.update(elapsed_time, self.facing_direction, self.graphic_state)
|
|
72
|
+
|
|
73
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
74
|
+
if nature == Nature.SIGNAL:
|
|
75
|
+
self.visible = True
|
|
76
|
+
return True
|
|
77
|
+
if nature == Nature.NO_SIGNAL:
|
|
78
|
+
self.visible = False
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
if self.has_sprite and not self.visible:
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
nature == Nature.WALK
|
|
86
|
+
and target.type == ObjectType.PLAYER
|
|
87
|
+
and not self.engine.teleport_triggered
|
|
88
|
+
):
|
|
89
|
+
self.engine.teleport_triggered = True
|
|
90
|
+
dst_px = self.dst_px
|
|
91
|
+
dst_py = self.dst_py
|
|
92
|
+
dst_vx = 0
|
|
93
|
+
dst_vy = 0
|
|
94
|
+
|
|
95
|
+
dst_vx, dst_vy = Direction.to_velocity(self.teleport_direction)
|
|
96
|
+
|
|
97
|
+
# if self.relative:
|
|
98
|
+
# if self.vertical:
|
|
99
|
+
# dst_py += target.py
|
|
100
|
+
# else:
|
|
101
|
+
# dst_px += target.px
|
|
102
|
+
|
|
103
|
+
if self.sliding:
|
|
104
|
+
if dst_vx != 0:
|
|
105
|
+
dst_py = target.py
|
|
106
|
+
elif dst_vy != 0:
|
|
107
|
+
dst_px = target.px
|
|
108
|
+
|
|
109
|
+
self.engine.script.add_command(
|
|
110
|
+
CommandMoveMap(
|
|
111
|
+
self.dst_map_name,
|
|
112
|
+
target,
|
|
113
|
+
dst_px,
|
|
114
|
+
dst_py,
|
|
115
|
+
dst_vx,
|
|
116
|
+
dst_vy,
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
else:
|
|
120
|
+
if self.triggered:
|
|
121
|
+
return False
|
|
122
|
+
|
|
123
|
+
new_direction = target.facing_direction
|
|
124
|
+
if self.invert_exit_direction:
|
|
125
|
+
new_direction = Direction((target.facing_direction.value + 2) % 4)
|
|
126
|
+
|
|
127
|
+
self.engine.script.add_command(
|
|
128
|
+
CommandSerial(
|
|
129
|
+
[
|
|
130
|
+
CommandScreenFade(),
|
|
131
|
+
CommandParallel(
|
|
132
|
+
[
|
|
133
|
+
CommandChangeMap(self.dst_map_name, dst_px, dst_py),
|
|
134
|
+
CommandSetFacingDirection(target, new_direction),
|
|
135
|
+
CommandScreenFade(fadein=True),
|
|
136
|
+
]
|
|
137
|
+
),
|
|
138
|
+
],
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
if self.sfx_on_trigger:
|
|
142
|
+
self.engine.audio.play_sound(self.sfx_on_trigger)
|
|
143
|
+
|
|
144
|
+
self.triggered = True
|
|
145
|
+
return True
|
|
146
|
+
|
|
147
|
+
return False
|
|
148
|
+
|
|
149
|
+
def draw_self(self, ox: float, oy: float):
|
|
150
|
+
if not self.visible:
|
|
151
|
+
self.engine.backend.draw_circle(
|
|
152
|
+
(self.px + 0.5 - ox) * TILE_WIDTH,
|
|
153
|
+
(self.py + 0.5 - oy) * TILE_HEIGHT,
|
|
154
|
+
0.5 * TILE_WIDTH,
|
|
155
|
+
RED,
|
|
156
|
+
)
|
|
157
|
+
return
|
|
158
|
+
|
|
159
|
+
if self.has_sprite:
|
|
160
|
+
self.sprite.draw_self(self.px - ox, self.py - oy)
|
|
161
|
+
|
|
162
|
+
@staticmethod
|
|
163
|
+
def load_from_tiled_object(obj, px, py, width, height) -> List[Teleport]:
|
|
164
|
+
sprite_name = obj.get_string("sprite_name")
|
|
165
|
+
tileset_name = obj.get_string("tileset_name")
|
|
166
|
+
image_name = obj.get_string("tileset_name")
|
|
167
|
+
graphic_state = GraphicState[obj.get_string("graphic_state", "closed").upper()]
|
|
168
|
+
facing_direction = Direction[obj.get_string("facing_direction", "south").upper()]
|
|
169
|
+
target_map = obj.get_string("target_map", "map1_c1")
|
|
170
|
+
invert_exit_direction = obj.get_bool("invert_exit_direction")
|
|
171
|
+
relative = obj.get_bool("relative", False)
|
|
172
|
+
sliding = obj.get_bool("sliding", False)
|
|
173
|
+
vertical = obj.get_bool("vertical", False)
|
|
174
|
+
layer = obj.get_int("layer", 1)
|
|
175
|
+
target_px = obj.get_float("target_px")
|
|
176
|
+
target_py = obj.get_float("target_py")
|
|
177
|
+
direction = Direction[obj.get_string("direction", "south").upper()]
|
|
178
|
+
teleports = []
|
|
179
|
+
if width > height and int(width) > 1:
|
|
180
|
+
num_horizontal = int(width)
|
|
181
|
+
for idx in range(num_horizontal):
|
|
182
|
+
from_px = px + idx
|
|
183
|
+
from_py = py
|
|
184
|
+
to_px = target_px + idx
|
|
185
|
+
to_py = target_py
|
|
186
|
+
|
|
187
|
+
LOG.debug(
|
|
188
|
+
"Adding a teleport at (%f, %f) to map %s (%f, %f).",
|
|
189
|
+
from_px,
|
|
190
|
+
from_py,
|
|
191
|
+
target_map,
|
|
192
|
+
to_px,
|
|
193
|
+
to_py,
|
|
194
|
+
)
|
|
195
|
+
teleports.append(
|
|
196
|
+
Teleport(
|
|
197
|
+
px=from_px,
|
|
198
|
+
py=from_py,
|
|
199
|
+
tileset_name=tileset_name,
|
|
200
|
+
image_name=image_name,
|
|
201
|
+
sprite_name=sprite_name,
|
|
202
|
+
graphic_state=graphic_state,
|
|
203
|
+
facing_direction=facing_direction,
|
|
204
|
+
dst_map_name=target_map,
|
|
205
|
+
dst_px=to_px,
|
|
206
|
+
dst_py=to_py,
|
|
207
|
+
direction=direction,
|
|
208
|
+
invert_exit_direction=invert_exit_direction,
|
|
209
|
+
relative=relative,
|
|
210
|
+
sliding=sliding,
|
|
211
|
+
vertical=False,
|
|
212
|
+
dyn_id=obj.object_id,
|
|
213
|
+
name=obj.name,
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
teleports[-1].layer = layer
|
|
217
|
+
elif height > width and int(height) > 1:
|
|
218
|
+
num_vertical = int(height)
|
|
219
|
+
for idx in range(num_vertical):
|
|
220
|
+
from_px = px
|
|
221
|
+
from_py = py + idx
|
|
222
|
+
to_px = target_px
|
|
223
|
+
to_py = target_py if relative else from_py
|
|
224
|
+
|
|
225
|
+
LOG.debug(
|
|
226
|
+
"Adding a teleport at (%f, %f) to map %s (%f, %f).",
|
|
227
|
+
from_px,
|
|
228
|
+
from_py,
|
|
229
|
+
target_map,
|
|
230
|
+
to_px,
|
|
231
|
+
to_py,
|
|
232
|
+
)
|
|
233
|
+
teleports.append(
|
|
234
|
+
Teleport(
|
|
235
|
+
px=from_px,
|
|
236
|
+
py=from_py,
|
|
237
|
+
tileset_name=tileset_name,
|
|
238
|
+
image_name=image_name,
|
|
239
|
+
sprite_name=sprite_name,
|
|
240
|
+
graphic_state=graphic_state,
|
|
241
|
+
facing_direction=facing_direction,
|
|
242
|
+
dst_map_name=target_map,
|
|
243
|
+
dst_px=to_px,
|
|
244
|
+
dst_py=to_py,
|
|
245
|
+
direction=direction,
|
|
246
|
+
invert_exit_direction=invert_exit_direction,
|
|
247
|
+
relative=relative,
|
|
248
|
+
sliding=sliding,
|
|
249
|
+
vertical=True,
|
|
250
|
+
dyn_id=obj.object_id,
|
|
251
|
+
name=obj.name,
|
|
252
|
+
)
|
|
253
|
+
)
|
|
254
|
+
teleports[-1].layer = layer
|
|
255
|
+
else:
|
|
256
|
+
LOG.debug(
|
|
257
|
+
"Adding a teleport at (%f, %f) to map %s (%f, %f).",
|
|
258
|
+
px,
|
|
259
|
+
py,
|
|
260
|
+
target_map,
|
|
261
|
+
target_px,
|
|
262
|
+
target_py,
|
|
263
|
+
)
|
|
264
|
+
teleports.append(
|
|
265
|
+
Teleport(
|
|
266
|
+
px=px,
|
|
267
|
+
py=py,
|
|
268
|
+
tileset_name=tileset_name,
|
|
269
|
+
image_name=image_name,
|
|
270
|
+
sprite_name=sprite_name,
|
|
271
|
+
graphic_state=graphic_state,
|
|
272
|
+
facing_direction=facing_direction,
|
|
273
|
+
dst_map_name=target_map,
|
|
274
|
+
dst_px=target_px,
|
|
275
|
+
dst_py=target_py,
|
|
276
|
+
direction=direction,
|
|
277
|
+
invert_exit_direction=invert_exit_direction,
|
|
278
|
+
relative=relative,
|
|
279
|
+
sliding=sliding,
|
|
280
|
+
vertical=vertical,
|
|
281
|
+
dyn_id=obj.object_id,
|
|
282
|
+
name=obj.name,
|
|
283
|
+
)
|
|
284
|
+
)
|
|
285
|
+
teleports[-1].sfx_on_trigger = obj.get_string("sfx_name")
|
|
286
|
+
teleports[-1].layer = layer
|
|
287
|
+
|
|
288
|
+
return teleports
|
mima/scene_engine.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Union
|
|
2
|
+
|
|
3
|
+
from .engine import MimaEngine
|
|
4
|
+
from .states.game_state import GameState
|
|
5
|
+
from .types.keys import Key as K
|
|
6
|
+
from .types.nature import Nature
|
|
7
|
+
from .view.scene import Scene
|
|
8
|
+
from .types.mode import Mode
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MimaSceneEngine(MimaEngine):
|
|
12
|
+
def __init__(
|
|
13
|
+
self, init_file: str, platform: str = "PC", caption: str = "MimaEngine"
|
|
14
|
+
):
|
|
15
|
+
super().__init__(init_file, platform, caption)
|
|
16
|
+
|
|
17
|
+
self.scene_stack: List[str] = []
|
|
18
|
+
self._scenes: Dict[str, Scene] = {}
|
|
19
|
+
self._current_scene: Scene
|
|
20
|
+
|
|
21
|
+
self.all_games: Dict[str, GameState] = {}
|
|
22
|
+
self.current_game: str = ""
|
|
23
|
+
self.save_timer_reset = 1.0
|
|
24
|
+
self._save_timer = self.save_timer_reset
|
|
25
|
+
self.teleport_triggered: bool = False
|
|
26
|
+
self.dialog_active: bool = False
|
|
27
|
+
|
|
28
|
+
def on_user_create(self):
|
|
29
|
+
return True
|
|
30
|
+
|
|
31
|
+
def on_user_update(self, elapsed_time: float):
|
|
32
|
+
self.audio.update(elapsed_time)
|
|
33
|
+
self._current_scene = self._scenes[self.scene_stack[-1]]
|
|
34
|
+
|
|
35
|
+
# self._current_scene = self.mode.name.lower()
|
|
36
|
+
|
|
37
|
+
self._save_timer -= elapsed_time
|
|
38
|
+
if self._save_timer <= 0.0:
|
|
39
|
+
self._save_timer += self.save_timer_reset
|
|
40
|
+
if self._current_scene.autosave:
|
|
41
|
+
for quest in self.quests:
|
|
42
|
+
for obj in self.scene.dynamics:
|
|
43
|
+
quest.on_interaction(
|
|
44
|
+
self.scene.dynamics, obj, Nature.SAVE
|
|
45
|
+
)
|
|
46
|
+
quest.save_state()
|
|
47
|
+
if self.keys.new_key_press(K.SELECT):
|
|
48
|
+
self.game_state.save_to_disk()
|
|
49
|
+
|
|
50
|
+
self.scene.update(elapsed_time)
|
|
51
|
+
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
def change_map(self, map_name: str, px: float, py: float):
|
|
55
|
+
type_string = (
|
|
56
|
+
self.get_map(map_name).get_string("type", "local").upper()
|
|
57
|
+
)
|
|
58
|
+
if type_string == "WORLD":
|
|
59
|
+
type_string = "WORLD_MAP"
|
|
60
|
+
if type_string == "LOCAL":
|
|
61
|
+
type_string = "LOCAL_MAP"
|
|
62
|
+
mode = Mode[type_string]
|
|
63
|
+
|
|
64
|
+
self.scene_stack.append(mode)
|
|
65
|
+
self._scenes[self.scene_stack[-1]].change_map(map_name, px, py)
|
|
66
|
+
# print(self.scene_stack)
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def scene(self) -> Scene:
|
|
70
|
+
# return self._scenes[self._current_scene]
|
|
71
|
+
return self._current_scene
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def previous_scene(self) -> Scene:
|
|
75
|
+
return self._scenes[self.scene_stack[-2]]
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def game_state(self) -> GameState:
|
|
79
|
+
return self.all_games[self.current_game]
|
mima/scripts/__init__.py
ADDED
mima/scripts/command.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from ..engine import MimaEngine
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Command:
|
|
10
|
+
engine: MimaEngine
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
self.started: bool = False
|
|
14
|
+
self.completed: bool = False
|
|
15
|
+
self.uninterruptible: bool = False
|
|
16
|
+
|
|
17
|
+
def start(self):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
def update(self, elapsed_time: float):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
def finalize(self):
|
|
24
|
+
pass
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from ..command import Command
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from ...states.quest import Quest
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CommandAddQuest(Command):
|
|
12
|
+
def __init__(self, quest: Quest):
|
|
13
|
+
super().__init__()
|
|
14
|
+
|
|
15
|
+
self._quest: Quest = quest
|
|
16
|
+
|
|
17
|
+
def start(self):
|
|
18
|
+
self.engine.add_quest(self._quest)
|
|
19
|
+
self.completed = True
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from ..command import Command
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CommandChangeMap(Command):
|
|
5
|
+
def __init__(self, map_name: str, spawn_px: float, spawn_py):
|
|
6
|
+
super().__init__()
|
|
7
|
+
|
|
8
|
+
self._map_name: str = map_name
|
|
9
|
+
self._spawn_px: float = spawn_px
|
|
10
|
+
self._spawn_py: float = spawn_py
|
|
11
|
+
|
|
12
|
+
def start(self):
|
|
13
|
+
self.engine.scene_stack.pop()
|
|
14
|
+
self.engine.change_map(self._map_name, self._spawn_px, self._spawn_py)
|
|
15
|
+
self.completed = True
|