mima-engine 0.4.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.
- mima/__init__.py +4 -0
- mima/backend/__init__.py +1 -0
- mima/backend/pygame_assets.py +401 -0
- mima/backend/pygame_audio.py +78 -0
- mima/backend/pygame_backend.py +603 -0
- mima/backend/pygame_camera.py +63 -0
- mima/backend/pygame_events.py +695 -0
- mima/backend/touch_control_scheme_a.py +126 -0
- mima/backend/touch_control_scheme_b.py +132 -0
- mima/core/__init__.py +0 -0
- mima/core/collision.py +325 -0
- mima/core/database.py +58 -0
- mima/core/engine.py +367 -0
- mima/core/mode_engine.py +81 -0
- mima/core/scene_engine.py +81 -0
- mima/integrated/__init__.py +0 -0
- mima/integrated/entity.py +183 -0
- mima/integrated/layered_map.py +351 -0
- mima/integrated/sprite.py +156 -0
- mima/layered/__init__.py +0 -0
- mima/layered/assets.py +56 -0
- mima/layered/scene.py +415 -0
- mima/layered/shape.py +99 -0
- mima/layered/shaped_sprite.py +78 -0
- mima/layered/virtual_input.py +302 -0
- mima/maps/__init__.py +0 -0
- mima/maps/template.py +71 -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 +51 -0
- mima/maps/tilemap.py +216 -0
- mima/maps/tileset.py +39 -0
- mima/maps/tileset_info.py +9 -0
- mima/maps/transition_map.py +146 -0
- mima/objects/__init__.py +0 -0
- mima/objects/animated_sprite.py +217 -0
- mima/objects/attribute_effect.py +26 -0
- mima/objects/attributes.py +126 -0
- mima/objects/creature.py +384 -0
- mima/objects/dynamic.py +206 -0
- mima/objects/effects/__init__.py +0 -0
- mima/objects/effects/colorize_screen.py +60 -0
- mima/objects/effects/debug_box.py +133 -0
- mima/objects/effects/light.py +103 -0
- mima/objects/effects/show_sprite.py +50 -0
- mima/objects/effects/walking_on_grass.py +70 -0
- mima/objects/effects/walking_on_water.py +57 -0
- mima/objects/loader.py +111 -0
- mima/objects/projectile.py +111 -0
- mima/objects/sprite.py +116 -0
- mima/objects/world/__init__.py +0 -0
- mima/objects/world/color_gate.py +67 -0
- mima/objects/world/color_switch.py +101 -0
- mima/objects/world/container.py +175 -0
- mima/objects/world/floor_switch.py +109 -0
- mima/objects/world/gate.py +178 -0
- mima/objects/world/light_source.py +121 -0
- mima/objects/world/logic_gate.py +157 -0
- mima/objects/world/movable.py +399 -0
- mima/objects/world/oneway.py +195 -0
- mima/objects/world/pickup.py +157 -0
- mima/objects/world/switch.py +179 -0
- mima/objects/world/teleport.py +308 -0
- mima/py.typed +0 -0
- mima/scripts/__init__.py +2 -0
- mima/scripts/command.py +38 -0
- mima/scripts/commands/__init__.py +0 -0
- mima/scripts/commands/add_quest.py +19 -0
- mima/scripts/commands/change_map.py +34 -0
- mima/scripts/commands/close_dialog.py +9 -0
- mima/scripts/commands/equip_weapon.py +23 -0
- mima/scripts/commands/give_item.py +26 -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 +58 -0
- mima/scripts/commands/parallel.py +66 -0
- mima/scripts/commands/play_sound.py +13 -0
- mima/scripts/commands/present_item.py +53 -0
- mima/scripts/commands/progress_quest.py +12 -0
- mima/scripts/commands/quit_game.py +8 -0
- mima/scripts/commands/save_game.py +14 -0
- mima/scripts/commands/screen_fade.py +83 -0
- mima/scripts/commands/serial.py +69 -0
- mima/scripts/commands/set_facing_direction.py +21 -0
- mima/scripts/commands/set_spawn_map.py +17 -0
- mima/scripts/commands/show_choices.py +52 -0
- mima/scripts/commands/show_dialog.py +118 -0
- mima/scripts/commands/take_coins.py +23 -0
- mima/scripts/script_processor.py +61 -0
- mima/standalone/__init__.py +0 -0
- mima/standalone/camera.py +153 -0
- mima/standalone/geometry.py +1318 -0
- mima/standalone/multicolumn_list.py +54 -0
- mima/standalone/pixel_font.py +84 -0
- mima/standalone/scripting.py +145 -0
- mima/standalone/spatial.py +186 -0
- mima/standalone/sprite.py +158 -0
- mima/standalone/tiled_map.py +1247 -0
- mima/standalone/transformed_view.py +433 -0
- mima/standalone/user_input.py +563 -0
- mima/states/__init__.py +0 -0
- mima/states/game_state.py +189 -0
- mima/states/memory.py +28 -0
- mima/states/quest.py +71 -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 +23 -0
- mima/types/keys.py +64 -0
- mima/types/mode.py +9 -0
- mima/types/nature.py +12 -0
- mima/types/object.py +22 -0
- mima/types/player.py +9 -0
- mima/types/position.py +13 -0
- mima/types/start.py +7 -0
- mima/types/terrain.py +9 -0
- mima/types/tile_collision.py +11 -0
- mima/types/weapon_slot.py +6 -0
- mima/types/window.py +44 -0
- mima/usables/__init__.py +0 -0
- mima/usables/item.py +51 -0
- mima/usables/weapon.py +68 -0
- mima/util/__init__.py +1 -0
- mima/util/colors.py +50 -0
- mima/util/constants.py +55 -0
- mima/util/functions.py +38 -0
- mima/util/input_defaults.py +170 -0
- mima/util/logging.py +51 -0
- mima/util/property.py +8 -0
- mima/util/runtime_config.py +327 -0
- mima/util/trading_item.py +23 -0
- mima/view/__init__.py +0 -0
- mima/view/camera.py +192 -0
- mima/view/mima_mode.py +618 -0
- mima/view/mima_scene.py +231 -0
- mima/view/mima_view.py +12 -0
- mima/view/mima_window.py +244 -0
- mima_engine-0.4.0.dist-info/METADATA +47 -0
- mima_engine-0.4.0.dist-info/RECORD +153 -0
- mima_engine-0.4.0.dist-info/WHEEL +4 -0
mima/objects/sprite.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from ..types.direction import Direction
|
|
2
|
+
from ..types.graphic_state import GraphicState
|
|
3
|
+
from ..util.constants import (
|
|
4
|
+
DEFAULT_GRAPHIC_TIMER,
|
|
5
|
+
DEFAULT_GRAPHIC_TIMER_DAMAGED,
|
|
6
|
+
DEFAULT_GRAPHIC_TIMER_DEAD,
|
|
7
|
+
DEFAULT_GRAPHIC_TIMER_STANDING,
|
|
8
|
+
DEFAULT_GRAPHIC_TIMER_WALKING,
|
|
9
|
+
DEFAULT_SPRITE_HEIGHT,
|
|
10
|
+
DEFAULT_SPRITE_WIDTH,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Sprite:
|
|
15
|
+
engine = None
|
|
16
|
+
|
|
17
|
+
def __init__(self, name: str = "", *, ox=0, oy=0, width=0, height=0):
|
|
18
|
+
self.name = name
|
|
19
|
+
self.ox: int = 0
|
|
20
|
+
self.oy: int = 0
|
|
21
|
+
self.width: int = DEFAULT_SPRITE_WIDTH if width == 0 else width
|
|
22
|
+
self.height: int = DEFAULT_SPRITE_HEIGHT if height == 0 else height
|
|
23
|
+
self.num_frames: int = 1
|
|
24
|
+
self.frame_index: int = 0
|
|
25
|
+
|
|
26
|
+
self.timer: float = 0.25
|
|
27
|
+
self.timer_reset: float = 0.5
|
|
28
|
+
|
|
29
|
+
self.last_direction: Direction = Direction.SOUTH
|
|
30
|
+
self.last_graphic_state: GraphicState = GraphicState.STANDING
|
|
31
|
+
|
|
32
|
+
def update(
|
|
33
|
+
self,
|
|
34
|
+
elapsed_time: float,
|
|
35
|
+
direction: Direction = Direction.SOUTH,
|
|
36
|
+
graphic_state: GraphicState = GraphicState.STANDING,
|
|
37
|
+
):
|
|
38
|
+
if (
|
|
39
|
+
direction == self.last_direction
|
|
40
|
+
and graphic_state == self.last_graphic_state
|
|
41
|
+
):
|
|
42
|
+
# Nothing has changed, normal case
|
|
43
|
+
self.timer -= elapsed_time
|
|
44
|
+
|
|
45
|
+
if self.timer <= 0.0:
|
|
46
|
+
self.timer += self.timer_reset
|
|
47
|
+
self.frame_index = (self.frame_index + 1) % self.num_frames
|
|
48
|
+
|
|
49
|
+
else:
|
|
50
|
+
# Something changed
|
|
51
|
+
if graphic_state != self.last_graphic_state:
|
|
52
|
+
# State changed
|
|
53
|
+
if graphic_state == GraphicState.STANDING:
|
|
54
|
+
self.timer_reset = DEFAULT_GRAPHIC_TIMER_STANDING
|
|
55
|
+
elif graphic_state == GraphicState.WALKING:
|
|
56
|
+
self.timer_reset = DEFAULT_GRAPHIC_TIMER_WALKING
|
|
57
|
+
elif graphic_state == GraphicState.DAMAGED:
|
|
58
|
+
self.timer_reset = DEFAULT_GRAPHIC_TIMER_DAMAGED
|
|
59
|
+
elif graphic_state == GraphicState.DEAD:
|
|
60
|
+
self.timer_reset = DEFAULT_GRAPHIC_TIMER_DEAD
|
|
61
|
+
elif graphic_state == GraphicState.PUSHING:
|
|
62
|
+
self.timer_reset = DEFAULT_GRAPHIC_TIMER_WALKING
|
|
63
|
+
else:
|
|
64
|
+
self.timer_reset = DEFAULT_GRAPHIC_TIMER
|
|
65
|
+
|
|
66
|
+
# self.timer = self.timer_reset
|
|
67
|
+
# self.frame_index = 0
|
|
68
|
+
|
|
69
|
+
self.timer = self.timer_reset
|
|
70
|
+
self.frame_index = 0
|
|
71
|
+
|
|
72
|
+
self.last_direction = direction
|
|
73
|
+
self.last_graphic_state = graphic_state
|
|
74
|
+
|
|
75
|
+
def draw_self(
|
|
76
|
+
self,
|
|
77
|
+
px: float,
|
|
78
|
+
py: float,
|
|
79
|
+
camera_name: str = "display",
|
|
80
|
+
draw_to_ui: bool = False,
|
|
81
|
+
):
|
|
82
|
+
if self.name == "":
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
sheet_ox = sheet_oy = 0
|
|
86
|
+
state_value = self.last_graphic_state.value
|
|
87
|
+
|
|
88
|
+
if self.last_graphic_state == GraphicState.CELEBRATING:
|
|
89
|
+
sheet_ox = (self.ox + self.frame_index) * self.width
|
|
90
|
+
sheet_oy = (self.oy + state_value) * self.height
|
|
91
|
+
elif self.last_graphic_state == GraphicState.DEAD:
|
|
92
|
+
sheet_ox = (self.ox + 2 + self.frame_index) * self.width
|
|
93
|
+
sheet_oy = (self.oy + state_value) * self.height
|
|
94
|
+
else:
|
|
95
|
+
if self.last_graphic_state == GraphicState.PUSHING:
|
|
96
|
+
state_value -= 1
|
|
97
|
+
sheet_ox = (
|
|
98
|
+
self.ox + 2 * self.last_direction.value + self.frame_index
|
|
99
|
+
) * self.width
|
|
100
|
+
sheet_oy = (self.oy + state_value) * self.height
|
|
101
|
+
|
|
102
|
+
self.engine.backend.draw_partial_sprite(
|
|
103
|
+
px * self.engine.rtc.tile_width,
|
|
104
|
+
py * self.engine.rtc.tile_height,
|
|
105
|
+
self.name,
|
|
106
|
+
sheet_ox,
|
|
107
|
+
sheet_oy,
|
|
108
|
+
self.width,
|
|
109
|
+
self.height,
|
|
110
|
+
camera_name,
|
|
111
|
+
draw_to_ui=draw_to_ui,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def reset(self):
|
|
115
|
+
self.frame_index = 0
|
|
116
|
+
self.timer = 0.0
|
|
File without changes
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from typing import List, Optional, Union
|
|
2
|
+
|
|
3
|
+
from ...maps.tilemap import Tilemap
|
|
4
|
+
from ...types.direction import Direction
|
|
5
|
+
from ...types.gate_color import GateColor
|
|
6
|
+
from ...types.graphic_state import GraphicState
|
|
7
|
+
from ...types.nature import Nature
|
|
8
|
+
from ...types.object import ObjectType
|
|
9
|
+
from ..dynamic import Dynamic
|
|
10
|
+
from .gate import Gate
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ColorGate(Gate):
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
px: float,
|
|
18
|
+
py: float,
|
|
19
|
+
name: str = "ColorGate",
|
|
20
|
+
*,
|
|
21
|
+
sprite_name: str = "",
|
|
22
|
+
tilemap: Optional[Tilemap] = None,
|
|
23
|
+
dyn_id: int = -1,
|
|
24
|
+
graphic_state: GraphicState = GraphicState.STANDING,
|
|
25
|
+
facing_direction: Direction = Direction.SOUTH,
|
|
26
|
+
color: GateColor = GateColor.RED,
|
|
27
|
+
):
|
|
28
|
+
super().__init__(
|
|
29
|
+
px,
|
|
30
|
+
py,
|
|
31
|
+
name,
|
|
32
|
+
sprite_name=sprite_name,
|
|
33
|
+
tilemap=tilemap,
|
|
34
|
+
dyn_id=dyn_id,
|
|
35
|
+
graphic_state=graphic_state,
|
|
36
|
+
facing_direction=facing_direction,
|
|
37
|
+
bombable=False,
|
|
38
|
+
)
|
|
39
|
+
self.color = color
|
|
40
|
+
self.type = ObjectType.COLOR_GATE
|
|
41
|
+
|
|
42
|
+
def update(self, elapsed_time, float, target: Optional[Dynamic] = None):
|
|
43
|
+
self.open = self.engine.gate_color == self.color
|
|
44
|
+
super().update(elapsed_time, target)
|
|
45
|
+
|
|
46
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def load_from_tiled_object(obj, px, py, width, height, tilemap):
|
|
51
|
+
gate = ColorGate(
|
|
52
|
+
px=px,
|
|
53
|
+
py=py,
|
|
54
|
+
name=obj.name,
|
|
55
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
56
|
+
tilemap=tilemap,
|
|
57
|
+
dyn_id=obj.object_id,
|
|
58
|
+
graphic_state=GraphicState[
|
|
59
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
60
|
+
],
|
|
61
|
+
facing_direction=Direction[
|
|
62
|
+
obj.get_string("facing_direction", "south").upper()
|
|
63
|
+
],
|
|
64
|
+
color=GateColor[obj.get_string("color", "red").upper()],
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return [gate]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, List, Optional, Union
|
|
4
|
+
|
|
5
|
+
from ...types.direction import Direction
|
|
6
|
+
from ...types.gate_color import GateColor
|
|
7
|
+
from ...types.graphic_state import GraphicState
|
|
8
|
+
from ...types.nature import Nature
|
|
9
|
+
from ...types.object import ObjectType
|
|
10
|
+
from ..dynamic import Dynamic
|
|
11
|
+
from .switch import Switch
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from ...maps.tilemap import Tilemap
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ColorSwitch(Switch):
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
px: float,
|
|
21
|
+
py: float,
|
|
22
|
+
name="ColorSwitch",
|
|
23
|
+
*,
|
|
24
|
+
sprite_name: str = "",
|
|
25
|
+
tilemap: Optional[Tilemap] = None,
|
|
26
|
+
dyn_id=-1,
|
|
27
|
+
graphic_state: GraphicState = GraphicState.OPEN,
|
|
28
|
+
initial_signal=False,
|
|
29
|
+
color: GateColor = GateColor.RED,
|
|
30
|
+
):
|
|
31
|
+
super().__init__(
|
|
32
|
+
px,
|
|
33
|
+
py,
|
|
34
|
+
name,
|
|
35
|
+
sprite_name=sprite_name,
|
|
36
|
+
tilemap=tilemap,
|
|
37
|
+
dyn_id=dyn_id,
|
|
38
|
+
graphic_state=graphic_state,
|
|
39
|
+
initial_signal=initial_signal,
|
|
40
|
+
)
|
|
41
|
+
self.type = ObjectType.COLOR_SWITCH
|
|
42
|
+
|
|
43
|
+
self.color = color
|
|
44
|
+
self.graphic_state = (
|
|
45
|
+
GraphicState.CLOSED
|
|
46
|
+
if color == self.engine.gate_color
|
|
47
|
+
else GraphicState.OPEN
|
|
48
|
+
)
|
|
49
|
+
# self.signal = self.graphic_state == GraphicState.CLOSED
|
|
50
|
+
# self.send_initial_signal = False
|
|
51
|
+
|
|
52
|
+
def update(self, elapsed_time: float, target: Optional[Dynamic] = None):
|
|
53
|
+
self.graphic_state = (
|
|
54
|
+
GraphicState.CLOSED
|
|
55
|
+
if self.color == self.engine.gate_color
|
|
56
|
+
else GraphicState.OPEN
|
|
57
|
+
)
|
|
58
|
+
# self.signal = self.graphic_state == GraphicState.CLOSED
|
|
59
|
+
#
|
|
60
|
+
self.sprite.update(
|
|
61
|
+
elapsed_time, self.facing_direction, self.graphic_state
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
65
|
+
if (
|
|
66
|
+
nature == Nature.TALK
|
|
67
|
+
and target.type == ObjectType.PLAYER
|
|
68
|
+
and self.visible
|
|
69
|
+
):
|
|
70
|
+
if self.engine.gate_color != self.color:
|
|
71
|
+
self.engine.gate_color = self.color
|
|
72
|
+
else:
|
|
73
|
+
self.engine.gate_color = GateColor(
|
|
74
|
+
(self.color.value + 1) % self.engine.n_gate_colors
|
|
75
|
+
)
|
|
76
|
+
self.state_changed = True
|
|
77
|
+
self.engine.audio.play_sound("switch")
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def load_from_tiled_object(obj, px, py, width, height, tilemap):
|
|
84
|
+
switch = ColorSwitch(
|
|
85
|
+
px=px,
|
|
86
|
+
py=py,
|
|
87
|
+
name=obj.name,
|
|
88
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
89
|
+
tilemap=tilemap,
|
|
90
|
+
dyn_id=obj.object_id,
|
|
91
|
+
graphic_state=GraphicState[
|
|
92
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
93
|
+
],
|
|
94
|
+
color=GateColor[obj.get_string("color", "red").upper()],
|
|
95
|
+
initial_signal=False,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# switch.sprite.width = int(width * ColorSwitch.engine.rtc.tile_width)
|
|
99
|
+
# switch.sprite.height = int(height * ColorSwitch.engine.rtc.tile_height)
|
|
100
|
+
|
|
101
|
+
return [switch]
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import List, Optional
|
|
5
|
+
|
|
6
|
+
from ...maps.tilemap import Tilemap
|
|
7
|
+
from ...scripts.commands.give_item import CommandGiveItem
|
|
8
|
+
from ...scripts.commands.give_resource import CommandGiveResource
|
|
9
|
+
from ...scripts.commands.parallel import CommandParallel
|
|
10
|
+
from ...scripts.commands.present_item import CommandPresentItem
|
|
11
|
+
from ...scripts.commands.show_dialog import CommandShowDialog
|
|
12
|
+
from ...types.direction import Direction
|
|
13
|
+
from ...types.graphic_state import GraphicState
|
|
14
|
+
from ...types.nature import Nature
|
|
15
|
+
from ...types.object import ObjectType
|
|
16
|
+
from ..animated_sprite import AnimatedSprite
|
|
17
|
+
from ..dynamic import Dynamic
|
|
18
|
+
|
|
19
|
+
LOG = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Container(Dynamic):
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
px: float,
|
|
26
|
+
py: float,
|
|
27
|
+
name: str = "Container",
|
|
28
|
+
*,
|
|
29
|
+
sprite_name: str = "",
|
|
30
|
+
tilemap: Optional[Tilemap] = None,
|
|
31
|
+
dyn_id: int = -1,
|
|
32
|
+
graphic_state: GraphicState = GraphicState.CLOSED,
|
|
33
|
+
item_name: str = "",
|
|
34
|
+
):
|
|
35
|
+
if graphic_state not in [
|
|
36
|
+
GraphicState.OPEN,
|
|
37
|
+
GraphicState.CLOSED,
|
|
38
|
+
]:
|
|
39
|
+
msg = (
|
|
40
|
+
f"graphic_state of Container {name}{dyn_id} must be either "
|
|
41
|
+
f"'open' or 'closed', but it is {graphic_state}"
|
|
42
|
+
)
|
|
43
|
+
raise ValueError(msg)
|
|
44
|
+
super().__init__(
|
|
45
|
+
px,
|
|
46
|
+
py,
|
|
47
|
+
name,
|
|
48
|
+
tilemap=tilemap,
|
|
49
|
+
sprite_name=sprite_name,
|
|
50
|
+
dyn_id=dyn_id,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
self.type = ObjectType.CONTAINER
|
|
54
|
+
self.graphic_state = graphic_state
|
|
55
|
+
self.closed: bool = self.graphic_state != GraphicState.OPEN
|
|
56
|
+
|
|
57
|
+
self.item_name: str = item_name
|
|
58
|
+
self.item = self.engine.get_item(item_name)
|
|
59
|
+
self.solid_vs_dyn: bool = True
|
|
60
|
+
self.solid_vs_map: bool = True
|
|
61
|
+
self.visible: bool = True
|
|
62
|
+
|
|
63
|
+
self.is_resource: bool = False
|
|
64
|
+
self.amount: int = 1
|
|
65
|
+
|
|
66
|
+
self._gs_map = {False: GraphicState.OPEN, True: GraphicState.CLOSED}
|
|
67
|
+
|
|
68
|
+
def update(self, elapsed_time: float, target: Optional[Dynamic] = None):
|
|
69
|
+
if self.visible:
|
|
70
|
+
self.solid_vs_dyn = True
|
|
71
|
+
else:
|
|
72
|
+
self.solid_vs_dyn = False
|
|
73
|
+
|
|
74
|
+
self.graphic_state = (
|
|
75
|
+
GraphicState.CLOSED if self.closed else GraphicState.OPEN
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
self.sprite.update(
|
|
79
|
+
elapsed_time, self.facing_direction, self.graphic_state
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def draw_self(self, ox: float, oy: float, camera_name: str = "display"):
|
|
83
|
+
if not self.visible:
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
self.sprite.draw_self(self.px - ox, self.py - oy, camera_name)
|
|
87
|
+
|
|
88
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
89
|
+
if nature == Nature.SIGNAL:
|
|
90
|
+
self.visible = True
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
if nature == Nature.NO_SIGNAL:
|
|
94
|
+
self.visible = False
|
|
95
|
+
return True
|
|
96
|
+
|
|
97
|
+
if not self.visible:
|
|
98
|
+
return False
|
|
99
|
+
|
|
100
|
+
if nature == Nature.TALK:
|
|
101
|
+
if self.closed:
|
|
102
|
+
if self.is_resource:
|
|
103
|
+
text = "You received "
|
|
104
|
+
if self.amount > 1:
|
|
105
|
+
text += f"{self.amount} {self.item.name}s!"
|
|
106
|
+
elif self.amount == 1:
|
|
107
|
+
text += f"one {self.item.name}!"
|
|
108
|
+
else:
|
|
109
|
+
text += "nothing. The chest was empty!"
|
|
110
|
+
|
|
111
|
+
if self.item_name == "coin":
|
|
112
|
+
cgr = CommandGiveResource(target, coins=self.amount)
|
|
113
|
+
elif self.item_name == "bomb_refill":
|
|
114
|
+
cgr = CommandGiveResource(target, bombs=self.amount)
|
|
115
|
+
elif self.item_name == "arrow_refill":
|
|
116
|
+
cgr = CommandGiveResource(target, arrows=self.amount)
|
|
117
|
+
elif self.item_name == "key":
|
|
118
|
+
cgr = CommandGiveResource(target, keys=self.amount)
|
|
119
|
+
else:
|
|
120
|
+
LOG.error(f"Invalid resource type: {self.item_name}")
|
|
121
|
+
return False
|
|
122
|
+
|
|
123
|
+
self.engine.script.add_command(
|
|
124
|
+
CommandParallel(
|
|
125
|
+
[
|
|
126
|
+
CommandShowDialog([text]),
|
|
127
|
+
CommandPresentItem(self.item_name, target),
|
|
128
|
+
cgr,
|
|
129
|
+
],
|
|
130
|
+
CommandParallel.FIRST_COMPLETED,
|
|
131
|
+
),
|
|
132
|
+
players=[target.get_player()],
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
else:
|
|
136
|
+
|
|
137
|
+
self.engine.script.add_command(
|
|
138
|
+
CommandParallel(
|
|
139
|
+
[
|
|
140
|
+
CommandShowDialog(
|
|
141
|
+
[f"You received {self.item.name}"],
|
|
142
|
+
),
|
|
143
|
+
CommandPresentItem(self.item_name, target),
|
|
144
|
+
CommandGiveItem(self.item_name, target),
|
|
145
|
+
],
|
|
146
|
+
CommandParallel.FIRST_COMPLETED,
|
|
147
|
+
),
|
|
148
|
+
players=[target.get_player()],
|
|
149
|
+
)
|
|
150
|
+
self.closed = False
|
|
151
|
+
self.state_changed = True
|
|
152
|
+
return True
|
|
153
|
+
|
|
154
|
+
return False
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
def load_from_tiled_object(
|
|
158
|
+
obj, px, py, width, height, tilemap
|
|
159
|
+
) -> List[Container]:
|
|
160
|
+
container = Container(
|
|
161
|
+
px=px,
|
|
162
|
+
py=py,
|
|
163
|
+
name=obj.name,
|
|
164
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
165
|
+
tilemap=tilemap,
|
|
166
|
+
dyn_id=obj.object_id,
|
|
167
|
+
graphic_state=GraphicState[
|
|
168
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
169
|
+
],
|
|
170
|
+
item_name=obj.get_string("item_name"),
|
|
171
|
+
)
|
|
172
|
+
container.is_resource = obj.get_bool("is_resource", False)
|
|
173
|
+
container.amount = obj.get_int("amount", 1)
|
|
174
|
+
|
|
175
|
+
return [container]
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from ...maps.tilemap import Tilemap
|
|
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 ..dynamic import Dynamic
|
|
9
|
+
from .switch import Switch
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FloorSwitch(Switch):
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
px: float,
|
|
16
|
+
py: float,
|
|
17
|
+
name="Floor Switch",
|
|
18
|
+
*,
|
|
19
|
+
sprite_name: str = "",
|
|
20
|
+
tilemap: Optional[Tilemap] = None,
|
|
21
|
+
dyn_id: int = -1,
|
|
22
|
+
graphic_state: GraphicState = GraphicState.OPEN,
|
|
23
|
+
initial_signal: bool = True,
|
|
24
|
+
):
|
|
25
|
+
super().__init__(
|
|
26
|
+
px,
|
|
27
|
+
py,
|
|
28
|
+
name,
|
|
29
|
+
sprite_name=sprite_name,
|
|
30
|
+
tilemap=tilemap,
|
|
31
|
+
dyn_id=dyn_id,
|
|
32
|
+
graphic_state=graphic_state,
|
|
33
|
+
initial_signal=initial_signal,
|
|
34
|
+
)
|
|
35
|
+
self.layer = 0
|
|
36
|
+
|
|
37
|
+
self.type = ObjectType.FLOOR_SWITCH
|
|
38
|
+
self.interacted = False
|
|
39
|
+
self.interacted_before = False
|
|
40
|
+
self.solid_vs_dyn = False
|
|
41
|
+
|
|
42
|
+
def update(self, elapsed_time: float, target: Dynamic):
|
|
43
|
+
if self.send_initial_signal:
|
|
44
|
+
self.send_signal(self.signal)
|
|
45
|
+
self.send_initial_signal = False
|
|
46
|
+
self.state_changed = False
|
|
47
|
+
if not self.interacted:
|
|
48
|
+
if self.interacted_before:
|
|
49
|
+
self.state_changed = True
|
|
50
|
+
self.interacted_before = False
|
|
51
|
+
|
|
52
|
+
else:
|
|
53
|
+
if not self.interacted_before:
|
|
54
|
+
self.state_changed = True
|
|
55
|
+
self.interacted_before = True
|
|
56
|
+
|
|
57
|
+
self.interacted = False
|
|
58
|
+
|
|
59
|
+
if self.state_changed:
|
|
60
|
+
self.signal = not self.signal
|
|
61
|
+
self.send_signal(self.signal)
|
|
62
|
+
|
|
63
|
+
self.graphic_state = (
|
|
64
|
+
GraphicState.CLOSED if self.signal else GraphicState.OPEN
|
|
65
|
+
)
|
|
66
|
+
self.sprite.update(
|
|
67
|
+
elapsed_time, self.facing_direction, self.graphic_state
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def on_interaction(self, target: Dynamic, nature: Nature):
|
|
71
|
+
if nature == Nature.WALK and not target.type == ObjectType.PROJECTILE:
|
|
72
|
+
if target.type == ObjectType.MOVABLE:
|
|
73
|
+
if not target.visible:
|
|
74
|
+
return False
|
|
75
|
+
self.interacted = True
|
|
76
|
+
return True
|
|
77
|
+
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def load_from_tiled_object(obj, px, py, width, height, tilemap):
|
|
82
|
+
fswitch = FloorSwitch(
|
|
83
|
+
px=px,
|
|
84
|
+
py=py,
|
|
85
|
+
name=obj.name,
|
|
86
|
+
sprite_name=obj.get_string("sprite_name"),
|
|
87
|
+
tilemap=tilemap,
|
|
88
|
+
dyn_id=obj.object_id,
|
|
89
|
+
graphic_state=GraphicState[
|
|
90
|
+
obj.get_string("graphic_state", "closed").upper()
|
|
91
|
+
],
|
|
92
|
+
initial_signal=obj.get_bool("initial_signal", True),
|
|
93
|
+
)
|
|
94
|
+
# TODO: Why was this used?
|
|
95
|
+
# fswitch.sprite.width = int(width * FloorSwitch.engine.rtc.tile_width)
|
|
96
|
+
# fswitch.sprite.height = int(
|
|
97
|
+
# height * FloorSwitch.engine.rtc.tile_height
|
|
98
|
+
# )
|
|
99
|
+
|
|
100
|
+
ctr = 1
|
|
101
|
+
while True:
|
|
102
|
+
key = f"output{ctr}"
|
|
103
|
+
listener_id = obj.get_int(key, -1)
|
|
104
|
+
if listener_id < 0:
|
|
105
|
+
break
|
|
106
|
+
fswitch.listener_ids.append(listener_id)
|
|
107
|
+
ctr += 1
|
|
108
|
+
|
|
109
|
+
return [fswitch]
|