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.
Files changed (153) hide show
  1. mima/__init__.py +4 -0
  2. mima/backend/__init__.py +1 -0
  3. mima/backend/pygame_assets.py +401 -0
  4. mima/backend/pygame_audio.py +78 -0
  5. mima/backend/pygame_backend.py +603 -0
  6. mima/backend/pygame_camera.py +63 -0
  7. mima/backend/pygame_events.py +695 -0
  8. mima/backend/touch_control_scheme_a.py +126 -0
  9. mima/backend/touch_control_scheme_b.py +132 -0
  10. mima/core/__init__.py +0 -0
  11. mima/core/collision.py +325 -0
  12. mima/core/database.py +58 -0
  13. mima/core/engine.py +367 -0
  14. mima/core/mode_engine.py +81 -0
  15. mima/core/scene_engine.py +81 -0
  16. mima/integrated/__init__.py +0 -0
  17. mima/integrated/entity.py +183 -0
  18. mima/integrated/layered_map.py +351 -0
  19. mima/integrated/sprite.py +156 -0
  20. mima/layered/__init__.py +0 -0
  21. mima/layered/assets.py +56 -0
  22. mima/layered/scene.py +415 -0
  23. mima/layered/shape.py +99 -0
  24. mima/layered/shaped_sprite.py +78 -0
  25. mima/layered/virtual_input.py +302 -0
  26. mima/maps/__init__.py +0 -0
  27. mima/maps/template.py +71 -0
  28. mima/maps/tile.py +20 -0
  29. mima/maps/tile_animation.py +7 -0
  30. mima/maps/tile_info.py +10 -0
  31. mima/maps/tile_layer.py +52 -0
  32. mima/maps/tiled/__init__.py +0 -0
  33. mima/maps/tiled/tiled_layer.py +48 -0
  34. mima/maps/tiled/tiled_map.py +95 -0
  35. mima/maps/tiled/tiled_object.py +79 -0
  36. mima/maps/tiled/tiled_objectgroup.py +25 -0
  37. mima/maps/tiled/tiled_template.py +49 -0
  38. mima/maps/tiled/tiled_tile.py +90 -0
  39. mima/maps/tiled/tiled_tileset.py +51 -0
  40. mima/maps/tilemap.py +216 -0
  41. mima/maps/tileset.py +39 -0
  42. mima/maps/tileset_info.py +9 -0
  43. mima/maps/transition_map.py +146 -0
  44. mima/objects/__init__.py +0 -0
  45. mima/objects/animated_sprite.py +217 -0
  46. mima/objects/attribute_effect.py +26 -0
  47. mima/objects/attributes.py +126 -0
  48. mima/objects/creature.py +384 -0
  49. mima/objects/dynamic.py +206 -0
  50. mima/objects/effects/__init__.py +0 -0
  51. mima/objects/effects/colorize_screen.py +60 -0
  52. mima/objects/effects/debug_box.py +133 -0
  53. mima/objects/effects/light.py +103 -0
  54. mima/objects/effects/show_sprite.py +50 -0
  55. mima/objects/effects/walking_on_grass.py +70 -0
  56. mima/objects/effects/walking_on_water.py +57 -0
  57. mima/objects/loader.py +111 -0
  58. mima/objects/projectile.py +111 -0
  59. mima/objects/sprite.py +116 -0
  60. mima/objects/world/__init__.py +0 -0
  61. mima/objects/world/color_gate.py +67 -0
  62. mima/objects/world/color_switch.py +101 -0
  63. mima/objects/world/container.py +175 -0
  64. mima/objects/world/floor_switch.py +109 -0
  65. mima/objects/world/gate.py +178 -0
  66. mima/objects/world/light_source.py +121 -0
  67. mima/objects/world/logic_gate.py +157 -0
  68. mima/objects/world/movable.py +399 -0
  69. mima/objects/world/oneway.py +195 -0
  70. mima/objects/world/pickup.py +157 -0
  71. mima/objects/world/switch.py +179 -0
  72. mima/objects/world/teleport.py +308 -0
  73. mima/py.typed +0 -0
  74. mima/scripts/__init__.py +2 -0
  75. mima/scripts/command.py +38 -0
  76. mima/scripts/commands/__init__.py +0 -0
  77. mima/scripts/commands/add_quest.py +19 -0
  78. mima/scripts/commands/change_map.py +34 -0
  79. mima/scripts/commands/close_dialog.py +9 -0
  80. mima/scripts/commands/equip_weapon.py +23 -0
  81. mima/scripts/commands/give_item.py +26 -0
  82. mima/scripts/commands/give_resource.py +51 -0
  83. mima/scripts/commands/move_map.py +152 -0
  84. mima/scripts/commands/move_to.py +49 -0
  85. mima/scripts/commands/oneway_move.py +58 -0
  86. mima/scripts/commands/parallel.py +66 -0
  87. mima/scripts/commands/play_sound.py +13 -0
  88. mima/scripts/commands/present_item.py +53 -0
  89. mima/scripts/commands/progress_quest.py +12 -0
  90. mima/scripts/commands/quit_game.py +8 -0
  91. mima/scripts/commands/save_game.py +14 -0
  92. mima/scripts/commands/screen_fade.py +83 -0
  93. mima/scripts/commands/serial.py +69 -0
  94. mima/scripts/commands/set_facing_direction.py +21 -0
  95. mima/scripts/commands/set_spawn_map.py +17 -0
  96. mima/scripts/commands/show_choices.py +52 -0
  97. mima/scripts/commands/show_dialog.py +118 -0
  98. mima/scripts/commands/take_coins.py +23 -0
  99. mima/scripts/script_processor.py +61 -0
  100. mima/standalone/__init__.py +0 -0
  101. mima/standalone/camera.py +153 -0
  102. mima/standalone/geometry.py +1318 -0
  103. mima/standalone/multicolumn_list.py +54 -0
  104. mima/standalone/pixel_font.py +84 -0
  105. mima/standalone/scripting.py +145 -0
  106. mima/standalone/spatial.py +186 -0
  107. mima/standalone/sprite.py +158 -0
  108. mima/standalone/tiled_map.py +1247 -0
  109. mima/standalone/transformed_view.py +433 -0
  110. mima/standalone/user_input.py +563 -0
  111. mima/states/__init__.py +0 -0
  112. mima/states/game_state.py +189 -0
  113. mima/states/memory.py +28 -0
  114. mima/states/quest.py +71 -0
  115. mima/types/__init__.py +0 -0
  116. mima/types/alignment.py +7 -0
  117. mima/types/blend.py +8 -0
  118. mima/types/damage.py +42 -0
  119. mima/types/direction.py +44 -0
  120. mima/types/gate_color.py +7 -0
  121. mima/types/graphic_state.py +23 -0
  122. mima/types/keys.py +64 -0
  123. mima/types/mode.py +9 -0
  124. mima/types/nature.py +12 -0
  125. mima/types/object.py +22 -0
  126. mima/types/player.py +9 -0
  127. mima/types/position.py +13 -0
  128. mima/types/start.py +7 -0
  129. mima/types/terrain.py +9 -0
  130. mima/types/tile_collision.py +11 -0
  131. mima/types/weapon_slot.py +6 -0
  132. mima/types/window.py +44 -0
  133. mima/usables/__init__.py +0 -0
  134. mima/usables/item.py +51 -0
  135. mima/usables/weapon.py +68 -0
  136. mima/util/__init__.py +1 -0
  137. mima/util/colors.py +50 -0
  138. mima/util/constants.py +55 -0
  139. mima/util/functions.py +38 -0
  140. mima/util/input_defaults.py +170 -0
  141. mima/util/logging.py +51 -0
  142. mima/util/property.py +8 -0
  143. mima/util/runtime_config.py +327 -0
  144. mima/util/trading_item.py +23 -0
  145. mima/view/__init__.py +0 -0
  146. mima/view/camera.py +192 -0
  147. mima/view/mima_mode.py +618 -0
  148. mima/view/mima_scene.py +231 -0
  149. mima/view/mima_view.py +12 -0
  150. mima/view/mima_window.py +244 -0
  151. mima_engine-0.4.0.dist-info/METADATA +47 -0
  152. mima_engine-0.4.0.dist-info/RECORD +153 -0
  153. 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,9 @@
1
+ from dataclasses import dataclass
2
+
3
+ from .tileset import Tileset
4
+
5
+
6
+ @dataclass
7
+ class TilesetInfo:
8
+ tileset: Tileset
9
+ first_gid: int
@@ -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
File without changes