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
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, List
|
|
4
|
+
|
|
5
|
+
from .tiled_object import TiledObject
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from xml.etree.ElementTree import Element
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TiledObjectgroup:
|
|
12
|
+
def __init__(self, o_xtree: Element):
|
|
13
|
+
self.name: str = o_xtree.attrib["name"]
|
|
14
|
+
self.layer_id: int = int(o_xtree.attrib["id"])
|
|
15
|
+
|
|
16
|
+
self._objects: List[TiledObject] = []
|
|
17
|
+
|
|
18
|
+
objects = o_xtree.findall("object")
|
|
19
|
+
|
|
20
|
+
for obj in objects:
|
|
21
|
+
self._objects.append(TiledObject(obj))
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def objects(self):
|
|
25
|
+
return self._objects
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from xml.etree import ElementTree
|
|
4
|
+
|
|
5
|
+
from ...util.property import Property
|
|
6
|
+
from ..template import Template
|
|
7
|
+
|
|
8
|
+
LOG = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TiledTemplate(Template):
|
|
12
|
+
def __init__(self, name: str, filename: str):
|
|
13
|
+
super().__init__(name)
|
|
14
|
+
|
|
15
|
+
LOG.info(
|
|
16
|
+
"Loading template %s from TX file at '%s' ...",
|
|
17
|
+
name,
|
|
18
|
+
filename,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
tree = ElementTree.parse(filename)
|
|
22
|
+
LOG.debug("Loaded file %s successfully.", filename)
|
|
23
|
+
|
|
24
|
+
root = tree.getroot()
|
|
25
|
+
tileset = root.findall("tileset")[0]
|
|
26
|
+
LOG.debug("Loading tileset properties ...")
|
|
27
|
+
self.first_gid = int(tileset.attrib["firstgid"])
|
|
28
|
+
self.tileset_name = os.path.split(tileset.attrib["source"])[-1].split(
|
|
29
|
+
"."
|
|
30
|
+
)[0]
|
|
31
|
+
|
|
32
|
+
obj = root.findall("object")[0]
|
|
33
|
+
self.oname = obj.attrib.get("name", "Unnamed")
|
|
34
|
+
self.otype = obj.attrib.get("type", obj.attrib.get("class", "Untyped"))
|
|
35
|
+
self.gid = int(obj.attrib["gid"])
|
|
36
|
+
self.width = int(obj.attrib["width"])
|
|
37
|
+
self.height = int(obj.attrib["height"])
|
|
38
|
+
|
|
39
|
+
props = obj.findall("properties")
|
|
40
|
+
if props:
|
|
41
|
+
props = props[0].findall("property")
|
|
42
|
+
|
|
43
|
+
for p in props:
|
|
44
|
+
pname = p.attrib["name"]
|
|
45
|
+
self.properties[pname] = Property(
|
|
46
|
+
name=pname,
|
|
47
|
+
dtype=p.attrib.get("type", "str"),
|
|
48
|
+
value=p.attrib["value"],
|
|
49
|
+
)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, List
|
|
4
|
+
|
|
5
|
+
from ...types.direction import Direction
|
|
6
|
+
from ...types.graphic_state import GraphicState
|
|
7
|
+
from ...types.terrain import Terrain
|
|
8
|
+
from ...util.functions import strtobool
|
|
9
|
+
from ..tile import Tile
|
|
10
|
+
from ..tile_animation import TileAnimation
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from xml.etree.ElementTree import Element
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TiledTile(Tile):
|
|
17
|
+
def __init__(self, t_xtree: Element):
|
|
18
|
+
super().__init__()
|
|
19
|
+
|
|
20
|
+
self.tile_type: str = t_xtree.attrib.get(
|
|
21
|
+
"class", t_xtree.attrib.get("type", "tile")
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
self.basic_tile_id: int = int(t_xtree.attrib["id"])
|
|
25
|
+
self.tile_id: int = self.basic_tile_id
|
|
26
|
+
|
|
27
|
+
self._frames: List[TileAnimation] = []
|
|
28
|
+
self._frame: int = 0
|
|
29
|
+
self._num_frames: int = 0
|
|
30
|
+
self._frame_timer: float = 0.0
|
|
31
|
+
|
|
32
|
+
animation = t_xtree.findall("animation")
|
|
33
|
+
|
|
34
|
+
if animation:
|
|
35
|
+
frames = animation[0].findall("frame")
|
|
36
|
+
for frame in frames:
|
|
37
|
+
self._frames.append(
|
|
38
|
+
TileAnimation(
|
|
39
|
+
frame_id=int(frame.attrib["tileid"]),
|
|
40
|
+
duration=int(frame.attrib["duration"]) / 1000.0,
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
self.animated = True
|
|
44
|
+
else:
|
|
45
|
+
self._frames.append(
|
|
46
|
+
TileAnimation(frame_id=self.basic_tile_id, duration=0.0)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
self._num_frames = len(self._frames)
|
|
50
|
+
|
|
51
|
+
self.tile_id = self._frames[0].frame_id
|
|
52
|
+
self._frame_timer = self._frames[0].duration
|
|
53
|
+
|
|
54
|
+
properties = t_xtree.findall("properties")
|
|
55
|
+
if properties:
|
|
56
|
+
properties = properties[0].findall("property")
|
|
57
|
+
for prop in properties:
|
|
58
|
+
if prop.attrib["name"] == "solid":
|
|
59
|
+
self.solid = strtobool(prop.attrib["value"])
|
|
60
|
+
if prop.attrib["name"] == "ground_type":
|
|
61
|
+
try:
|
|
62
|
+
self.terrain = Terrain[prop.attrib["value"].upper()]
|
|
63
|
+
except:
|
|
64
|
+
self.terrain = Terrain.DEFAULT
|
|
65
|
+
if prop.attrib["name"] == "z_height":
|
|
66
|
+
self.z_height = float(prop.attrib["value"])
|
|
67
|
+
if prop.attrib["name"] == "facing_direction":
|
|
68
|
+
self.facing_direction = Direction[
|
|
69
|
+
prop.attrib.get("value", "south").upper()
|
|
70
|
+
]
|
|
71
|
+
if prop.attrib["name"] == "graphic_state":
|
|
72
|
+
self.graphic_state = GraphicState[
|
|
73
|
+
prop.attrib.get("value", "standing").upper()
|
|
74
|
+
]
|
|
75
|
+
if prop.attrib["name"] == "sprite_name":
|
|
76
|
+
self.sprite_name = prop.attrib.get("value", "")
|
|
77
|
+
|
|
78
|
+
def update(self, elapsed_time: float) -> bool:
|
|
79
|
+
if self._num_frames <= 1:
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
self._frame_timer -= elapsed_time
|
|
83
|
+
if self._frame_timer <= 0:
|
|
84
|
+
self._frame = (self._frame + 1) % self._num_frames
|
|
85
|
+
self.tile_id = self._frames[self._frame].frame_id
|
|
86
|
+
self._frame_timer += self._frames[self._frame].duration
|
|
87
|
+
|
|
88
|
+
return True
|
|
89
|
+
|
|
90
|
+
return False
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
from xml.etree import ElementTree
|
|
6
|
+
|
|
7
|
+
from ..tileset import Tileset
|
|
8
|
+
from .tiled_tile import TiledTile
|
|
9
|
+
|
|
10
|
+
LOG = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TiledTileset(Tileset):
|
|
14
|
+
def __init__(self, name: str, filename: str):
|
|
15
|
+
super().__init__()
|
|
16
|
+
|
|
17
|
+
self.name = name
|
|
18
|
+
|
|
19
|
+
LOG.info(
|
|
20
|
+
"Loading tileset %s from TSX file at '%s' ...",
|
|
21
|
+
name,
|
|
22
|
+
filename,
|
|
23
|
+
)
|
|
24
|
+
tree = ElementTree.parse(filename)
|
|
25
|
+
LOG.debug("Loaded file %s successfully.", filename)
|
|
26
|
+
|
|
27
|
+
root = tree.getroot()
|
|
28
|
+
LOG.debug("Loading tileset properties ...")
|
|
29
|
+
self.tile_width: int = int(root.attrib["tilewidth"])
|
|
30
|
+
self.tile_height: int = int(root.attrib["tileheight"])
|
|
31
|
+
self.tile_count: int = int(root.attrib["tilecount"])
|
|
32
|
+
self.columns: int = int(root.attrib["columns"])
|
|
33
|
+
|
|
34
|
+
LOG.debug("Loading image properties ...")
|
|
35
|
+
image = root.findall("image")[0]
|
|
36
|
+
self.image_name: str = os.path.split(image.attrib["source"])[-1][:-4]
|
|
37
|
+
self.sprite_width: int = int(image.attrib["width"])
|
|
38
|
+
self.sprite_height: int = int(image.attrib["height"])
|
|
39
|
+
|
|
40
|
+
LOG.debug("Loading tiles ...")
|
|
41
|
+
tiles = root.findall("tile")
|
|
42
|
+
|
|
43
|
+
for tile in tiles:
|
|
44
|
+
t_obj = TiledTile(tile)
|
|
45
|
+
self.tiles.append(t_obj)
|
|
46
|
+
if t_obj.animated:
|
|
47
|
+
self.animated_tiles.append(t_obj)
|
|
48
|
+
if t_obj.sprite_name:
|
|
49
|
+
self.sprite_names.setdefault(t_obj.sprite_name, []).append(
|
|
50
|
+
t_obj.tile_id
|
|
51
|
+
)
|
mima/maps/tilemap.py
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import math
|
|
5
|
+
from typing import TYPE_CHECKING, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from ..types.tile_collision import TileCollision
|
|
8
|
+
from .template import Template
|
|
9
|
+
from .tile_info import TileInfo
|
|
10
|
+
from .tile_layer import TileLayer
|
|
11
|
+
from .tileset_info import TilesetInfo
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from ..objects.dynamic import Dynamic
|
|
15
|
+
from ..types.nature import Nature
|
|
16
|
+
from .tile import Tile
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
LOG = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Tilemap(Template):
|
|
23
|
+
def __init__(self, name: str):
|
|
24
|
+
super().__init__(name)
|
|
25
|
+
self.width: int = 0
|
|
26
|
+
self.height: int = 0
|
|
27
|
+
self.tile_width = self.engine.rtc.tile_width
|
|
28
|
+
self.tile_height = self.engine.rtc.tile_height
|
|
29
|
+
|
|
30
|
+
self._layers: List[TileLayer] = []
|
|
31
|
+
self._tilesets: List[TilesetInfo] = []
|
|
32
|
+
self._cache: Dict[int, TileInfo] = {}
|
|
33
|
+
self._objects: List[Template] = []
|
|
34
|
+
|
|
35
|
+
def populate_dynamics(self, dynamics: List[Dynamic]) -> bool:
|
|
36
|
+
"""Load all map-related objects into the game."""
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
def update(self, elapsed_time: float) -> bool:
|
|
40
|
+
for info in self._tilesets:
|
|
41
|
+
info.tileset.update(elapsed_time)
|
|
42
|
+
|
|
43
|
+
for layer in self._layers:
|
|
44
|
+
layer.update(elapsed_time)
|
|
45
|
+
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
def draw_self(
|
|
49
|
+
self,
|
|
50
|
+
ox: float,
|
|
51
|
+
oy: float,
|
|
52
|
+
visible_tiles_sx: int,
|
|
53
|
+
visible_tiles_sy: int,
|
|
54
|
+
visible_tiles_ex: int,
|
|
55
|
+
visible_tiles_ey: int,
|
|
56
|
+
layer_pos: int = 0,
|
|
57
|
+
camera_name: str = "display",
|
|
58
|
+
):
|
|
59
|
+
# Get offsets for smooth movement
|
|
60
|
+
tile_ox = (ox - math.floor(ox)) * self.tile_width
|
|
61
|
+
tile_oy = (oy - math.floor(oy)) * self.tile_height
|
|
62
|
+
|
|
63
|
+
for layer in self._layers:
|
|
64
|
+
if layer.layer_pos != layer_pos:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
layer_ox = (layer.layer_ox - math.floor(layer.layer_ox)) * self.tile_width
|
|
68
|
+
layer_oy = (layer.layer_oy - math.floor(layer.layer_oy)) * self.tile_height
|
|
69
|
+
|
|
70
|
+
layer_visible_tiles_sx = int(visible_tiles_sx)
|
|
71
|
+
layer_visible_tiles_sy = int(visible_tiles_sy)
|
|
72
|
+
|
|
73
|
+
if layer.speed_x != 0.0:
|
|
74
|
+
layer_visible_tiles_sx -= 1
|
|
75
|
+
if layer.speed_y != 0.0:
|
|
76
|
+
layer_visible_tiles_sy -= 1
|
|
77
|
+
|
|
78
|
+
# Draw visible tiles of the map
|
|
79
|
+
for x in range(layer_visible_tiles_sx, int(visible_tiles_ex) + 2):
|
|
80
|
+
for y in range(layer_visible_tiles_sy, int(visible_tiles_ey) + 2):
|
|
81
|
+
tile_index = layer.get_index(
|
|
82
|
+
int(x + math.floor(ox)), int(y + math.floor(oy))
|
|
83
|
+
)
|
|
84
|
+
if tile_index <= 0:
|
|
85
|
+
# Zero means the tile was not set in Tiled
|
|
86
|
+
continue
|
|
87
|
+
|
|
88
|
+
if tile_index not in self._cache:
|
|
89
|
+
if not self._load_to_cache(tile_index):
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
info = self._cache[tile_index]
|
|
93
|
+
|
|
94
|
+
sx = info.tile.tile_id % info.tileset.columns
|
|
95
|
+
sy = info.tile.tile_id // info.tileset.columns
|
|
96
|
+
|
|
97
|
+
self.engine.backend.draw_partial_sprite(
|
|
98
|
+
math.floor(x * self.tile_width - tile_ox + layer_ox),
|
|
99
|
+
math.floor(y * self.tile_height - tile_oy + layer_oy),
|
|
100
|
+
info.tileset.image_name,
|
|
101
|
+
sx * self.tile_width,
|
|
102
|
+
sy * self.tile_height,
|
|
103
|
+
self.tile_width,
|
|
104
|
+
self.tile_height,
|
|
105
|
+
camera_name,
|
|
106
|
+
)
|
|
107
|
+
return True
|
|
108
|
+
|
|
109
|
+
def on_interaction(self, target: Dynamic, nature: Nature) -> bool:
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
def is_solid(
|
|
113
|
+
self,
|
|
114
|
+
px: int,
|
|
115
|
+
py: int,
|
|
116
|
+
layer_pos: Optional[int] = None,
|
|
117
|
+
collision: TileCollision = TileCollision.TOP,
|
|
118
|
+
) -> bool:
|
|
119
|
+
if collision in (TileCollision.TOP, TileCollision.BOTTOM):
|
|
120
|
+
tile = self.get_tile(
|
|
121
|
+
px,
|
|
122
|
+
py,
|
|
123
|
+
layer_pos,
|
|
124
|
+
ascending=(collision == TileCollision.BOTTOM),
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
if tile is not None and tile.solid:
|
|
128
|
+
return True
|
|
129
|
+
return False
|
|
130
|
+
|
|
131
|
+
tiles = self.get_tiles(px, py, layer_pos)
|
|
132
|
+
if collision in (TileCollision.TOP_2, TileCollision.TOP_3):
|
|
133
|
+
tiles = tiles[::-1]
|
|
134
|
+
|
|
135
|
+
for idx, tile in enumerate(self.get_tiles(px, py, layer_pos)):
|
|
136
|
+
if tile.solid:
|
|
137
|
+
return True
|
|
138
|
+
if idx == 1 and collision in (
|
|
139
|
+
TileCollision.TOP_2,
|
|
140
|
+
TileCollision.BOTTOM_2,
|
|
141
|
+
):
|
|
142
|
+
break
|
|
143
|
+
elif idx == 2 and collision in (
|
|
144
|
+
TileCollision.TOP_3,
|
|
145
|
+
TileCollision.BOTTOM_3,
|
|
146
|
+
):
|
|
147
|
+
break
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
def get_tile(
|
|
151
|
+
self,
|
|
152
|
+
px: int,
|
|
153
|
+
py: int,
|
|
154
|
+
layer_pos: Optional[int] = None,
|
|
155
|
+
ascending=False,
|
|
156
|
+
) -> Optional[Tile]:
|
|
157
|
+
if ascending:
|
|
158
|
+
layers = self._layers
|
|
159
|
+
else:
|
|
160
|
+
layers = self._layers[::-1]
|
|
161
|
+
|
|
162
|
+
for layer in layers:
|
|
163
|
+
if layer_pos is not None and layer_pos != layer.layer_pos:
|
|
164
|
+
continue
|
|
165
|
+
tile_index = layer.get_index(math.floor(px), math.floor(py))
|
|
166
|
+
if tile_index not in self._cache:
|
|
167
|
+
if not self._load_to_cache(tile_index):
|
|
168
|
+
continue
|
|
169
|
+
|
|
170
|
+
info = self._cache[tile_index]
|
|
171
|
+
if info.tile is not None:
|
|
172
|
+
return info.tile
|
|
173
|
+
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
def get_tiles(self, px: int, py: int, layer_pos: Optional[int] = None):
|
|
177
|
+
tiles = []
|
|
178
|
+
for layer in self._layers:
|
|
179
|
+
if layer_pos is not None and layer_pos != layer.layer_pos:
|
|
180
|
+
continue
|
|
181
|
+
tile_index = layer.get_index(math.floor(px), math.floor(py))
|
|
182
|
+
if tile_index not in self._cache:
|
|
183
|
+
if not self._load_to_cache(tile_index):
|
|
184
|
+
continue
|
|
185
|
+
info = self._cache[tile_index]
|
|
186
|
+
if info.tile is not None:
|
|
187
|
+
tiles.append(info.tile)
|
|
188
|
+
|
|
189
|
+
return tiles
|
|
190
|
+
|
|
191
|
+
def _load_to_cache(self, tile_index: int) -> bool:
|
|
192
|
+
tileset = None
|
|
193
|
+
firstgid = 0
|
|
194
|
+
for tsinfo in self._tilesets:
|
|
195
|
+
if tile_index < tsinfo.first_gid:
|
|
196
|
+
break
|
|
197
|
+
|
|
198
|
+
firstgid = tsinfo.first_gid
|
|
199
|
+
tileset = tsinfo.tileset
|
|
200
|
+
|
|
201
|
+
if tileset is None:
|
|
202
|
+
return False
|
|
203
|
+
|
|
204
|
+
tidx = tile_index - firstgid
|
|
205
|
+
tile = tileset.get_tile(tidx)
|
|
206
|
+
|
|
207
|
+
self._cache[tile_index] = TileInfo(tileset=tileset, tile=tile)
|
|
208
|
+
return True
|
|
209
|
+
|
|
210
|
+
def trigger_new_frame(self):
|
|
211
|
+
for tsinfo in self._tilesets:
|
|
212
|
+
tsinfo.tileset.trigger_new_frame()
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def objects(self) -> List[Template]:
|
|
216
|
+
return []
|
mima/maps/tileset.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from typing import Dict, List
|
|
2
|
+
|
|
3
|
+
from .tile import Tile
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Tileset:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.name: str = "Unnamed Tileset"
|
|
9
|
+
self.image_name: str = ""
|
|
10
|
+
# self.filename: str = ""
|
|
11
|
+
self.image_width: int = 0
|
|
12
|
+
self.image_height: int = 0
|
|
13
|
+
self.tile_width: int = 0
|
|
14
|
+
self.tile_height: int = 0
|
|
15
|
+
self.tile_count: int = 0
|
|
16
|
+
self.columns: int = 0
|
|
17
|
+
|
|
18
|
+
self.tiles: List[Tile] = []
|
|
19
|
+
self.animated_tiles: List[Tile] = []
|
|
20
|
+
self.sprite_names: Dict[str, List[int]] = {}
|
|
21
|
+
self._is_new_frame: bool = False
|
|
22
|
+
|
|
23
|
+
def update(self, elapsed_time: float) -> bool:
|
|
24
|
+
if self._is_new_frame:
|
|
25
|
+
for tile in self.animated_tiles:
|
|
26
|
+
tile.update(elapsed_time)
|
|
27
|
+
self._is_new_frame = False
|
|
28
|
+
|
|
29
|
+
return True
|
|
30
|
+
|
|
31
|
+
def get_tile(self, tile_id: int) -> Tile:
|
|
32
|
+
for tile in self.tiles:
|
|
33
|
+
if tile.basic_tile_id == tile_id:
|
|
34
|
+
return tile
|
|
35
|
+
|
|
36
|
+
return self.tiles[0]
|
|
37
|
+
|
|
38
|
+
def trigger_new_frame(self):
|
|
39
|
+
self._is_new_frame = True
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
|
+
|
|
5
|
+
from ..util.constants import (
|
|
6
|
+
MAP_TRANSITION_DURATION_FACTOR,
|
|
7
|
+
MOVE_MAP_DURATION,
|
|
8
|
+
UI_HIGHT,
|
|
9
|
+
)
|
|
10
|
+
from .tilemap import Tilemap
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from .tile import Tile
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TransitionMap(Tilemap):
|
|
17
|
+
def __init__(
|
|
18
|
+
self, src_map: Tilemap, dst_map: Tilemap, dst_vx: int, dst_vy: int
|
|
19
|
+
):
|
|
20
|
+
super().__init__(src_map.name)
|
|
21
|
+
|
|
22
|
+
self.src_map: Tilemap = src_map
|
|
23
|
+
self.dst_map: Tilemap = dst_map
|
|
24
|
+
self.vx: int = int(dst_vx)
|
|
25
|
+
self.vy: int = int(dst_vy)
|
|
26
|
+
self.progress: float = 0.0
|
|
27
|
+
self.duration: float = (
|
|
28
|
+
MOVE_MAP_DURATION * MAP_TRANSITION_DURATION_FACTOR
|
|
29
|
+
)
|
|
30
|
+
self.time_so_far: float = 0.0
|
|
31
|
+
self.step_size: float = 1.0
|
|
32
|
+
self._extra_oy = UI_HIGHT
|
|
33
|
+
|
|
34
|
+
self.width: int = self.src_map.width
|
|
35
|
+
self.height: int = self.src_map.height
|
|
36
|
+
self.tiles_nx = (
|
|
37
|
+
self.engine.backend.render_width / self.engine.rtc.tile_width
|
|
38
|
+
)
|
|
39
|
+
self.tiles_ny = (
|
|
40
|
+
self.engine.backend.render_height / self.engine.rtc.tile_height
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if self.vx != 0:
|
|
44
|
+
self.step_size = self.duration / (self.tiles_nx * 0.75)
|
|
45
|
+
elif self.vy != 0:
|
|
46
|
+
self.step_size = self.duration / ((self.tiles_ny - 1) * 0.75)
|
|
47
|
+
|
|
48
|
+
def update(self, elapsed_time: float) -> bool:
|
|
49
|
+
self.progress = self.time_so_far / self.step_size
|
|
50
|
+
self.time_so_far += elapsed_time
|
|
51
|
+
|
|
52
|
+
return self.src_map.update(elapsed_time)
|
|
53
|
+
|
|
54
|
+
def draw_self(
|
|
55
|
+
self,
|
|
56
|
+
ox: float,
|
|
57
|
+
oy: float,
|
|
58
|
+
visible_tiles_sx: int,
|
|
59
|
+
visible_tiles_sy: int,
|
|
60
|
+
visible_tiles_ex: int,
|
|
61
|
+
visible_tiles_ey: int,
|
|
62
|
+
layer_pos: int = 0,
|
|
63
|
+
) -> bool:
|
|
64
|
+
src_tiles_sx = dst_tiles_sx = int(visible_tiles_sx)
|
|
65
|
+
src_tiles_sy = dst_tiles_sy = int(visible_tiles_sy)
|
|
66
|
+
src_tiles_ex = dst_tiles_ex = int(visible_tiles_ex)
|
|
67
|
+
src_tiles_ey = dst_tiles_ey = int(visible_tiles_ey)
|
|
68
|
+
src_ox = dst_ox = ox
|
|
69
|
+
src_oy = dst_oy = oy
|
|
70
|
+
|
|
71
|
+
if self.vx < 0: # Transition west
|
|
72
|
+
src_tiles_sx += int(self.progress)
|
|
73
|
+
src_tiles_ex += int(self.progress)
|
|
74
|
+
dst_tiles_ex = src_tiles_sx + 1
|
|
75
|
+
src_ox = max(-self.tiles_nx, -self.progress)
|
|
76
|
+
dst_ox = (
|
|
77
|
+
self.dst_map.width - self.tiles_nx + visible_tiles_ex + src_ox
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
elif self.vx > 0: # Transition east
|
|
81
|
+
src_tiles_sx -= int(self.progress)
|
|
82
|
+
src_tiles_ex -= int(self.progress)
|
|
83
|
+
dst_tiles_sx = src_tiles_ex
|
|
84
|
+
src_ox = self.src_map.width + min(0, self.progress - self.tiles_nx)
|
|
85
|
+
dst_ox = src_ox - self.src_map.width
|
|
86
|
+
|
|
87
|
+
elif self.vy < 0: # Transition north
|
|
88
|
+
src_tiles_sy += int(self.progress)
|
|
89
|
+
src_tiles_ey += int(self.progress)
|
|
90
|
+
dst_tiles_ey = src_tiles_sy + 1
|
|
91
|
+
src_oy = max(-self.tiles_ny, -self.progress - self._extra_oy)
|
|
92
|
+
dst_oy = (
|
|
93
|
+
self.dst_map.height - self.tiles_ny + visible_tiles_ey + src_oy
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
elif self.vy > 0: # Transition south
|
|
97
|
+
src_tiles_sy -= int(self.progress)
|
|
98
|
+
src_tiles_ey -= int(self.progress)
|
|
99
|
+
dst_tiles_sy = src_tiles_ey
|
|
100
|
+
src_oy = self.src_map.height + min(
|
|
101
|
+
0, self.progress - self.tiles_ny
|
|
102
|
+
)
|
|
103
|
+
dst_oy = -visible_tiles_ey + self.progress
|
|
104
|
+
|
|
105
|
+
# if layer_pos == 0:
|
|
106
|
+
# print(
|
|
107
|
+
# f"o({ox:.2f}),t({self.tiles_nx}),"
|
|
108
|
+
# f"ss({self.src_map.width}),so({src_ox:.2f}),"
|
|
109
|
+
# f"ts({src_tiles_sx}),te({src_tiles_ex}) -> "
|
|
110
|
+
# f"ds({self.dst_map.width}),do({dst_ox:.2f}),"
|
|
111
|
+
# f"ts({dst_tiles_sx}),te({dst_tiles_ex})"
|
|
112
|
+
# )
|
|
113
|
+
# print(
|
|
114
|
+
# f"o({ox:.2f},{oy:.2f}),"
|
|
115
|
+
# f"ss({self.src_map.width},{self.src_map.height}),so({src_ox:.2f},{src_oy:.2f}),"
|
|
116
|
+
# f"ts({src_tiles_sx},{src_tiles_sy}),te{src_tiles_ex,src_tiles_ey} -> "
|
|
117
|
+
# f"ds({self.dst_map.width},{self.dst_map.height}),do({dst_ox:.2f},{dst_oy:.2f}),"
|
|
118
|
+
# f"ts({dst_tiles_sx},{dst_tiles_sy}),te({dst_tiles_ex},{dst_tiles_ey})"
|
|
119
|
+
# )
|
|
120
|
+
# print(src_oy, dst_oy, self.map_screen_oy)
|
|
121
|
+
self.src_map.draw_self(
|
|
122
|
+
src_ox,
|
|
123
|
+
src_oy,
|
|
124
|
+
src_tiles_sx,
|
|
125
|
+
src_tiles_sy,
|
|
126
|
+
src_tiles_ex,
|
|
127
|
+
src_tiles_ey,
|
|
128
|
+
layer_pos,
|
|
129
|
+
)
|
|
130
|
+
self.dst_map.draw_self(
|
|
131
|
+
dst_ox,
|
|
132
|
+
dst_oy,
|
|
133
|
+
dst_tiles_sx,
|
|
134
|
+
dst_tiles_sy,
|
|
135
|
+
dst_tiles_ex,
|
|
136
|
+
dst_tiles_ey,
|
|
137
|
+
layer_pos,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
return True
|
|
141
|
+
|
|
142
|
+
def is_solid(self, px: int, py: int) -> bool:
|
|
143
|
+
return False
|
|
144
|
+
|
|
145
|
+
def get_tile(self, px: int, py: int) -> Optional[Tile]:
|
|
146
|
+
return None
|
mima/objects/__init__.py
ADDED
|
File without changes
|