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,171 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
from ...scripts.commands.give_item import CommandGiveItem
|
|
6
|
+
from ...scripts.commands.give_resource import CommandGiveResource
|
|
7
|
+
from ...scripts.commands.parallel import CommandParallel
|
|
8
|
+
from ...scripts.commands.present_item import CommandPresentItem
|
|
9
|
+
from ...scripts.commands.show_dialog import CommandShowDialog
|
|
10
|
+
from ...types.direction import Direction
|
|
11
|
+
from ...types.graphic_state import GraphicState
|
|
12
|
+
from ...types.nature import Nature
|
|
13
|
+
from ...types.object import ObjectType
|
|
14
|
+
from ..animated_sprite import AnimatedSprite
|
|
15
|
+
from ..dynamic import Dynamic
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Container(Dynamic):
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
px: float,
|
|
22
|
+
py: float,
|
|
23
|
+
tileset_name: str,
|
|
24
|
+
image_name: str,
|
|
25
|
+
sprite_name: str,
|
|
26
|
+
graphic_state: GraphicState,
|
|
27
|
+
facing_direction: Direction,
|
|
28
|
+
item_name: str,
|
|
29
|
+
dyn_id: int = -1,
|
|
30
|
+
name: str = "Container",
|
|
31
|
+
):
|
|
32
|
+
assert graphic_state in [
|
|
33
|
+
GraphicState.OPEN,
|
|
34
|
+
GraphicState.CLOSED,
|
|
35
|
+
], (
|
|
36
|
+
f"graphic_state of Container {name}{dyn_id} must be either 'open'"
|
|
37
|
+
f" or 'closed', but it {graphic_state}"
|
|
38
|
+
)
|
|
39
|
+
super().__init__(name, px, py, dyn_id)
|
|
40
|
+
|
|
41
|
+
self.sprite = AnimatedSprite(
|
|
42
|
+
tileset_name,
|
|
43
|
+
image_name,
|
|
44
|
+
sprite_name,
|
|
45
|
+
graphic_state,
|
|
46
|
+
facing_direction,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
self.type = ObjectType.CONTAINER
|
|
50
|
+
self.graphic_state = graphic_state
|
|
51
|
+
self.facing_direction = facing_direction
|
|
52
|
+
self.closed: bool = self.graphic_state != GraphicState.OPEN
|
|
53
|
+
|
|
54
|
+
self.item_name: str = item_name
|
|
55
|
+
self.solid_vs_dyn: bool = True
|
|
56
|
+
self.solid_vs_map: bool = True
|
|
57
|
+
self.visible: bool = True
|
|
58
|
+
|
|
59
|
+
self.is_resource: bool = False
|
|
60
|
+
self.amount: int = 1
|
|
61
|
+
|
|
62
|
+
# self.sprite = AnimatedSprite("simple_sheet", "simple_sheet", "chest01")
|
|
63
|
+
self._gs_map = {False: GraphicState.OPEN, True: GraphicState.CLOSED}
|
|
64
|
+
|
|
65
|
+
def update(self, elapsed_time: float, target: Optional[Dynamic] = None):
|
|
66
|
+
if self.visible:
|
|
67
|
+
self.solid_vs_dyn = True
|
|
68
|
+
else:
|
|
69
|
+
self.solid_vs_dyn = False
|
|
70
|
+
|
|
71
|
+
self.graphic_state = (
|
|
72
|
+
GraphicState.CLOSED if self.closed else GraphicState.OPEN
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
self.sprite.update(
|
|
76
|
+
elapsed_time, self.facing_direction, self.graphic_state
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def draw_self(self, ox: float, oy: float):
|
|
80
|
+
if not self.visible:
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
self.sprite.draw_self(self.px - ox, self.py - oy)
|
|
84
|
+
|
|
85
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
86
|
+
if nature == Nature.SIGNAL:
|
|
87
|
+
self.visible = True
|
|
88
|
+
return True
|
|
89
|
+
|
|
90
|
+
if nature == Nature.NO_SIGNAL:
|
|
91
|
+
self.visible = False
|
|
92
|
+
return True
|
|
93
|
+
|
|
94
|
+
if not self.visible:
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
if nature == Nature.TALK:
|
|
98
|
+
if self.closed:
|
|
99
|
+
if self.is_resource:
|
|
100
|
+
text = "You received "
|
|
101
|
+
if self.amount > 1:
|
|
102
|
+
text += f"{self.amount} {self.item_name}s!"
|
|
103
|
+
elif self.amount == 1:
|
|
104
|
+
text += f"one {self.item_name}!"
|
|
105
|
+
else:
|
|
106
|
+
text += "nothing. The chest was empty!"
|
|
107
|
+
|
|
108
|
+
if self.item_name == "Coin":
|
|
109
|
+
cgr = CommandGiveResource(target, coins=self.amount)
|
|
110
|
+
elif self.item_name == "Bomb Refill":
|
|
111
|
+
cgr = CommandGiveResource(target, bombs=self.amount)
|
|
112
|
+
elif self.item_name == "Arrow Refill":
|
|
113
|
+
cgr = CommandGiveResource(target, arrows=self.amount)
|
|
114
|
+
elif self.item_name == "Key":
|
|
115
|
+
cgr = CommandGiveResource(target, keys=self.amount)
|
|
116
|
+
else:
|
|
117
|
+
print(f"Invalid resource type: {self.item_name}")
|
|
118
|
+
return False
|
|
119
|
+
|
|
120
|
+
self.engine.script.add_command(
|
|
121
|
+
CommandParallel(
|
|
122
|
+
[
|
|
123
|
+
CommandShowDialog([text]),
|
|
124
|
+
CommandPresentItem(self.item_name, target),
|
|
125
|
+
cgr,
|
|
126
|
+
],
|
|
127
|
+
CommandParallel.FIRST_COMPLETED,
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
else:
|
|
132
|
+
self.engine.script.add_command(
|
|
133
|
+
CommandParallel(
|
|
134
|
+
[
|
|
135
|
+
CommandShowDialog(
|
|
136
|
+
[f"You received {self.item_name}"],
|
|
137
|
+
),
|
|
138
|
+
CommandPresentItem(self.item_name, target),
|
|
139
|
+
CommandGiveItem(self.item_name, target),
|
|
140
|
+
],
|
|
141
|
+
CommandParallel.FIRST_COMPLETED,
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
self.closed = False
|
|
145
|
+
self.state_changed = True
|
|
146
|
+
return True
|
|
147
|
+
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
@staticmethod
|
|
151
|
+
def load_from_tiled_object(obj, px, py, width, height) -> List[Container]:
|
|
152
|
+
container = Container(
|
|
153
|
+
px=px,
|
|
154
|
+
py=py,
|
|
155
|
+
tileset_name=obj.get_string("tileset_name"),
|
|
156
|
+
image_name=obj.get_string("tileset_name"),
|
|
157
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
158
|
+
graphic_state=GraphicState[
|
|
159
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
160
|
+
],
|
|
161
|
+
facing_direction=Direction[
|
|
162
|
+
obj.get_string("facing_direction", "south").upper()
|
|
163
|
+
],
|
|
164
|
+
item_name=obj.get_string("item_name"),
|
|
165
|
+
dyn_id=obj.object_id,
|
|
166
|
+
name=obj.name,
|
|
167
|
+
)
|
|
168
|
+
container.is_resource = obj.get_bool("is_resource", False)
|
|
169
|
+
container.amount = obj.get_int("amount", 1)
|
|
170
|
+
|
|
171
|
+
return [container]
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from ...types.direction import Direction
|
|
2
|
+
from ...types.graphic_state import GraphicState
|
|
3
|
+
from ...types.nature import Nature
|
|
4
|
+
from ...types.object import ObjectType
|
|
5
|
+
from ...util.constants import TILE_HEIGHT, TILE_WIDTH
|
|
6
|
+
from ..dynamic import Dynamic
|
|
7
|
+
from .switch import Switch
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FloorSwitch(Switch):
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
px: float,
|
|
14
|
+
py: float,
|
|
15
|
+
tileset_name: str,
|
|
16
|
+
image_name: str,
|
|
17
|
+
sprite_name: str,
|
|
18
|
+
facing_direction: Direction,
|
|
19
|
+
graphic_state: GraphicState,
|
|
20
|
+
initial_signal=True,
|
|
21
|
+
dyn_id=-1,
|
|
22
|
+
name="Floor Switch",
|
|
23
|
+
):
|
|
24
|
+
super().__init__(
|
|
25
|
+
px,
|
|
26
|
+
py,
|
|
27
|
+
tileset_name,
|
|
28
|
+
image_name,
|
|
29
|
+
sprite_name,
|
|
30
|
+
facing_direction,
|
|
31
|
+
graphic_state,
|
|
32
|
+
initial_signal,
|
|
33
|
+
dyn_id,
|
|
34
|
+
name,
|
|
35
|
+
)
|
|
36
|
+
self.layer = 0
|
|
37
|
+
|
|
38
|
+
self.type = ObjectType.FLOOR_SWITCH
|
|
39
|
+
self.interacted = False
|
|
40
|
+
self.interacted_before = False
|
|
41
|
+
self.solid_vs_dyn = False
|
|
42
|
+
|
|
43
|
+
def update(self, elapsed_time: float, target: Dynamic):
|
|
44
|
+
if self.send_initial_signal:
|
|
45
|
+
self.send_signal(self.signal)
|
|
46
|
+
self.send_initial_signal = False
|
|
47
|
+
self.state_changed = False
|
|
48
|
+
if not self.interacted:
|
|
49
|
+
if self.interacted_before:
|
|
50
|
+
self.state_changed = True
|
|
51
|
+
self.interacted_before = False
|
|
52
|
+
|
|
53
|
+
else:
|
|
54
|
+
if not self.interacted_before:
|
|
55
|
+
self.state_changed = True
|
|
56
|
+
self.interacted_before = True
|
|
57
|
+
|
|
58
|
+
self.interacted = False
|
|
59
|
+
|
|
60
|
+
if self.state_changed:
|
|
61
|
+
self.signal = not self.signal
|
|
62
|
+
self.send_signal(self.signal)
|
|
63
|
+
|
|
64
|
+
self.graphic_state = (
|
|
65
|
+
GraphicState.CLOSED if self.signal else GraphicState.OPEN
|
|
66
|
+
)
|
|
67
|
+
self.sprite.update(
|
|
68
|
+
elapsed_time, self.facing_direction, self.graphic_state
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
72
|
+
if nature == Nature.WALK and not target.type == ObjectType.PROJECTILE:
|
|
73
|
+
if target.type == ObjectType.MOVABLE:
|
|
74
|
+
if not target.visible:
|
|
75
|
+
return False
|
|
76
|
+
self.interacted = True
|
|
77
|
+
return True
|
|
78
|
+
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def load_from_tiled_object(obj, px, py, width, height):
|
|
83
|
+
fswitch = FloorSwitch(
|
|
84
|
+
px=px,
|
|
85
|
+
py=py,
|
|
86
|
+
tileset_name=obj.get_string("tileset_name"),
|
|
87
|
+
image_name=obj.get_string("tileset_name"),
|
|
88
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
89
|
+
graphic_state=GraphicState[
|
|
90
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
91
|
+
],
|
|
92
|
+
facing_direction=Direction[
|
|
93
|
+
obj.get_string("facing_direction", "south").upper()
|
|
94
|
+
],
|
|
95
|
+
initial_signal=obj.get_bool("initial_signal", True),
|
|
96
|
+
dyn_id=obj.object_id,
|
|
97
|
+
name=obj.name,
|
|
98
|
+
)
|
|
99
|
+
fswitch.sprite.width = int(width * TILE_WIDTH)
|
|
100
|
+
fswitch.sprite.height = int(height * TILE_HEIGHT)
|
|
101
|
+
|
|
102
|
+
ctr = 1
|
|
103
|
+
while True:
|
|
104
|
+
key = f"output{ctr}"
|
|
105
|
+
listener_id = obj.get_int(key, -1)
|
|
106
|
+
if listener_id < 0:
|
|
107
|
+
break
|
|
108
|
+
fswitch.listener_ids.append(listener_id)
|
|
109
|
+
ctr += 1
|
|
110
|
+
|
|
111
|
+
return [fswitch]
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ...types.damage import Damage
|
|
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 ..animated_sprite import AnimatedSprite
|
|
9
|
+
from ..dynamic import Dynamic
|
|
10
|
+
from .teleport import Teleport
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Gate(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
|
+
graphic_state: GraphicState,
|
|
22
|
+
facing_direction: Direction,
|
|
23
|
+
bombable: bool = False,
|
|
24
|
+
dyn_id: int = -1,
|
|
25
|
+
name: str = "Gate",
|
|
26
|
+
):
|
|
27
|
+
assert graphic_state in [
|
|
28
|
+
GraphicState.OPEN,
|
|
29
|
+
GraphicState.CLOSED,
|
|
30
|
+
GraphicState.LOCKED,
|
|
31
|
+
], (
|
|
32
|
+
f"graphic_state of Gate {name}{dyn_id} must be either 'open'"
|
|
33
|
+
f", 'closed', or 'locked', but it {graphic_state}"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
super().__init__(name, px, py, dyn_id)
|
|
37
|
+
|
|
38
|
+
self.sprite = AnimatedSprite(
|
|
39
|
+
tileset_name,
|
|
40
|
+
image_name,
|
|
41
|
+
sprite_name,
|
|
42
|
+
graphic_state,
|
|
43
|
+
facing_direction,
|
|
44
|
+
)
|
|
45
|
+
self.type = ObjectType.GATE
|
|
46
|
+
|
|
47
|
+
self.graphic_state = graphic_state
|
|
48
|
+
self.facing_direction = facing_direction
|
|
49
|
+
self.open = self.graphic_state == GraphicState.OPEN
|
|
50
|
+
|
|
51
|
+
# self.closed_sprite_name = closed_sprite_name
|
|
52
|
+
# self.open_sprite_name = open_sprite_name
|
|
53
|
+
# self.closed_sprite_ox: float = closed_sprite_ox
|
|
54
|
+
# self.closed_sprite_oy: float = closed_sprite_oy
|
|
55
|
+
# self.open_sprite_ox: float = open_sprite_ox
|
|
56
|
+
# self.open_sprite_oy: float = open_sprite_oy
|
|
57
|
+
|
|
58
|
+
# self.open = open
|
|
59
|
+
self.bombable = bombable
|
|
60
|
+
self.requires_key = self.graphic_state == GraphicState.LOCKED
|
|
61
|
+
self.unlocked = False
|
|
62
|
+
self.solid_vs_map = False
|
|
63
|
+
self.layer = 0
|
|
64
|
+
self.hitbox_px = self.hitbox_py = 0.0
|
|
65
|
+
self.hitbox_width = self.hitbox_height = 1.0
|
|
66
|
+
# self._set_sprite_state()
|
|
67
|
+
|
|
68
|
+
def update(self, elapsed_time: float, target: Dynamic):
|
|
69
|
+
self.solid_vs_dyn = not self.open
|
|
70
|
+
self.graphic_state = (
|
|
71
|
+
GraphicState.OPEN
|
|
72
|
+
if self.open
|
|
73
|
+
else (
|
|
74
|
+
GraphicState.LOCKED
|
|
75
|
+
if self.requires_key
|
|
76
|
+
else GraphicState.CLOSED
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
self.sprite.update(
|
|
81
|
+
elapsed_time, self.facing_direction, self.graphic_state
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
85
|
+
if nature == Nature.TALK:
|
|
86
|
+
if target.type == ObjectType.PLAYER:
|
|
87
|
+
if (
|
|
88
|
+
not self.open
|
|
89
|
+
and self.requires_key
|
|
90
|
+
and target.attributes.keys > 0
|
|
91
|
+
):
|
|
92
|
+
target.attributes.keys -= 1
|
|
93
|
+
self.open = True
|
|
94
|
+
self.state_changed = True
|
|
95
|
+
self.unlocked = True
|
|
96
|
+
return True
|
|
97
|
+
|
|
98
|
+
if nature == Nature.SIGNAL:
|
|
99
|
+
self.open = True
|
|
100
|
+
self.state_changed = True
|
|
101
|
+
return True
|
|
102
|
+
|
|
103
|
+
if nature == Nature.NO_SIGNAL and not self.unlocked:
|
|
104
|
+
self.open = False
|
|
105
|
+
self.state_changed = True
|
|
106
|
+
return True
|
|
107
|
+
|
|
108
|
+
if self.bombable and target.type == ObjectType.PROJECTILE:
|
|
109
|
+
if target.dtype == Damage.EXPLOSION:
|
|
110
|
+
self.open = True
|
|
111
|
+
self.state_changed = True
|
|
112
|
+
if target.one_hit:
|
|
113
|
+
target.kill()
|
|
114
|
+
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
def draw_self(self, ox: float, oy: float):
|
|
118
|
+
self.sprite.draw_self(self.px - ox, self.py - oy)
|
|
119
|
+
|
|
120
|
+
@staticmethod
|
|
121
|
+
def load_from_tiled_object(
|
|
122
|
+
obj, px: float, py: float, width: float, height: float
|
|
123
|
+
) -> Gate:
|
|
124
|
+
gate = [
|
|
125
|
+
Gate(
|
|
126
|
+
px=px,
|
|
127
|
+
py=py,
|
|
128
|
+
tileset_name=obj.get_string("tileset_name"),
|
|
129
|
+
image_name=obj.get_string("tileset_name"),
|
|
130
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
131
|
+
graphic_state=GraphicState[
|
|
132
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
133
|
+
],
|
|
134
|
+
facing_direction=Direction[
|
|
135
|
+
obj.get_string("facing_direction", "south").upper()
|
|
136
|
+
],
|
|
137
|
+
bombable=obj.get_bool("bombable"),
|
|
138
|
+
dyn_id=obj.object_id,
|
|
139
|
+
name=obj.name,
|
|
140
|
+
)
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
if obj.get_bool("has_teleport"):
|
|
144
|
+
if gate[0].facing_direction == Direction.NORTH:
|
|
145
|
+
py += 0.4
|
|
146
|
+
elif gate[0].facing_direction == Direction.SOUTH:
|
|
147
|
+
py -= 0.1
|
|
148
|
+
|
|
149
|
+
teleport = Teleport(
|
|
150
|
+
px=px,
|
|
151
|
+
py=py,
|
|
152
|
+
tileset_name="",
|
|
153
|
+
image_name="",
|
|
154
|
+
sprite_name="",
|
|
155
|
+
dst_map_name=obj.get_string("target_map"),
|
|
156
|
+
dst_px=obj.get_float("target_px"),
|
|
157
|
+
dst_py=obj.get_float("target_py"),
|
|
158
|
+
facing_direction=gate[0].facing_direction,
|
|
159
|
+
graphic_state=GraphicState.STANDING,
|
|
160
|
+
direction=gate[0].facing_direction,
|
|
161
|
+
invert_exit_direction=False,
|
|
162
|
+
relative=False,
|
|
163
|
+
sliding=False,
|
|
164
|
+
vertical=False,
|
|
165
|
+
dyn_id=gate[0].dyn_id + 2000,
|
|
166
|
+
name=f"Teleport of {gate[0].name}",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
teleport.visible = False
|
|
170
|
+
teleport.sfx_on_trigger = "pass_door"
|
|
171
|
+
|
|
172
|
+
gate.append(teleport)
|
|
173
|
+
|
|
174
|
+
return gate
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from ...types.direction import Direction
|
|
4
|
+
from ...types.graphic_state import GraphicState
|
|
5
|
+
from ...types.nature import Nature
|
|
6
|
+
from ...types.object import ObjectType
|
|
7
|
+
from ...util.constants import TILE_HEIGHT, TILE_WIDTH
|
|
8
|
+
from ..animated_sprite import AnimatedSprite
|
|
9
|
+
from ..dynamic import Dynamic
|
|
10
|
+
from ..effects.light import Light
|
|
11
|
+
from ..projectile import Projectile
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LightSource(Dynamic):
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
px: float,
|
|
18
|
+
py: float,
|
|
19
|
+
tileset_name: str,
|
|
20
|
+
image_name: str,
|
|
21
|
+
sprite_name: str,
|
|
22
|
+
graphic_state: GraphicState,
|
|
23
|
+
facing_direction: Direction,
|
|
24
|
+
max_size: int,
|
|
25
|
+
dyn_id: int = -1,
|
|
26
|
+
name: str = "LightSource",
|
|
27
|
+
):
|
|
28
|
+
assert graphic_state in [GraphicState.OFF, GraphicState.ON], (
|
|
29
|
+
f"graphic_state of LightSource {name}{dyn_id} must be either "
|
|
30
|
+
f"'off' or 'on', but it {graphic_state}"
|
|
31
|
+
)
|
|
32
|
+
super().__init__(name, px, py, dyn_id)
|
|
33
|
+
|
|
34
|
+
self.sprite = AnimatedSprite(
|
|
35
|
+
tileset_name,
|
|
36
|
+
image_name,
|
|
37
|
+
sprite_name,
|
|
38
|
+
graphic_state,
|
|
39
|
+
facing_direction,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
self.type = ObjectType.LIGHT_SOURCE
|
|
43
|
+
self.graphic_state = graphic_state
|
|
44
|
+
self.facing_direction = facing_direction
|
|
45
|
+
self._max_size = max_size
|
|
46
|
+
self.active = self.graphic_state == GraphicState.ON
|
|
47
|
+
self._light: Optional[Projectile] = None
|
|
48
|
+
|
|
49
|
+
self.hitbox_px = 0.0
|
|
50
|
+
self.hitbox_py = 0.0
|
|
51
|
+
self.hitbox_width = 1.0
|
|
52
|
+
self.hitbox_height = 1.0
|
|
53
|
+
self.solid_vs_dyn = True
|
|
54
|
+
self.solid_vs_map = False
|
|
55
|
+
self.onscreen_collision_skippable = True
|
|
56
|
+
self._state_changed = True
|
|
57
|
+
|
|
58
|
+
def update(self, elapsed_time: float, target: Optional[Dynamic] = None):
|
|
59
|
+
if self._state_changed:
|
|
60
|
+
# self._set_sprite_state()
|
|
61
|
+
self._state_changed = False
|
|
62
|
+
|
|
63
|
+
if self.active:
|
|
64
|
+
if self._light is None:
|
|
65
|
+
self._light = Light(self, self._max_size)
|
|
66
|
+
self.engine.scene.add_effect(self._light)
|
|
67
|
+
else:
|
|
68
|
+
if self._light is not None:
|
|
69
|
+
self._light.kill()
|
|
70
|
+
self._light = None
|
|
71
|
+
|
|
72
|
+
self.graphic_state = (
|
|
73
|
+
GraphicState.ON if self.active else GraphicState.OFF
|
|
74
|
+
)
|
|
75
|
+
self.sprite.update(
|
|
76
|
+
elapsed_time, self.facing_direction, self.graphic_state
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
80
|
+
if nature == Nature.SIGNAL:
|
|
81
|
+
self.active = True
|
|
82
|
+
self._state_changed = True
|
|
83
|
+
return True
|
|
84
|
+
|
|
85
|
+
if nature == Nature.NO_SIGNAL:
|
|
86
|
+
self.active = False
|
|
87
|
+
self._state_changed = True
|
|
88
|
+
return True
|
|
89
|
+
|
|
90
|
+
if nature == Nature.TALK:
|
|
91
|
+
self.active = not self.active
|
|
92
|
+
self._state_changed = True
|
|
93
|
+
return True
|
|
94
|
+
|
|
95
|
+
def draw_self(self, ox: float, oy: float):
|
|
96
|
+
self.sprite.draw_self(self.px - ox, self.py - oy)
|
|
97
|
+
|
|
98
|
+
def on_death(self) -> bool:
|
|
99
|
+
self._light.kill()
|
|
100
|
+
return True
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def load_from_tiled_object(obj, px, py, width, height):
|
|
104
|
+
light = LightSource(
|
|
105
|
+
px=px,
|
|
106
|
+
py=py,
|
|
107
|
+
tileset_name=obj.get_string("tileset_name"),
|
|
108
|
+
image_name=obj.get_string("tileset_name"),
|
|
109
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
110
|
+
graphic_state=GraphicState[
|
|
111
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
112
|
+
],
|
|
113
|
+
facing_direction=Direction[
|
|
114
|
+
obj.get_string("facing_direction", "south").upper()
|
|
115
|
+
],
|
|
116
|
+
max_size=obj.get_int("max_size", 32),
|
|
117
|
+
dyn_id=obj.object_id,
|
|
118
|
+
name=obj.name,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
light.sprite.width = int(width * TILE_WIDTH)
|
|
122
|
+
light.sprite.height = int(height * TILE_HEIGHT)
|
|
123
|
+
|
|
124
|
+
return [light]
|