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,217 @@
1
+ import logging
2
+ import math
3
+ from typing import Any, Dict, Optional
4
+
5
+ from ..types.direction import Direction
6
+ from ..types.graphic_state import GraphicState
7
+
8
+ LOG = logging.getLogger(__name__)
9
+
10
+
11
+ class AnimatedSprite:
12
+ engine = None
13
+ sprite_sets = {}
14
+
15
+ def __init__(
16
+ self,
17
+ # tileset_name: str,
18
+ # image_name: str,
19
+ sprite_name: str,
20
+ graphic_state: GraphicState = GraphicState.STANDING,
21
+ facing_direction: Direction = Direction.SOUTH,
22
+ ):
23
+
24
+ self.name = sprite_name
25
+ self._last_direction: Direction = facing_direction
26
+ self._last_graphic_state: GraphicState = graphic_state
27
+ self.sprite_sheet = self.engine.assets.get_sprite_data(sprite_name)
28
+
29
+ if self.name:
30
+ data = self._get_data(
31
+ self._last_graphic_state, self._last_direction
32
+ )
33
+ self._frame_index: int = 0
34
+ self._timer: float = data["duration"][0]
35
+ self._ox = data["ox"][0]
36
+ self._oy = data["oy"][0]
37
+ self._image_name = data["image"][0]
38
+ self.width = data["width"][0]
39
+ self.height = data["height"][0]
40
+ else:
41
+ self.width = self.engine.rtc.tile_width
42
+ self.height = self.engine.rtc.tile_height
43
+ # # TODO: Handle ""
44
+ # if tileset_name and image_name and self._sprite_name:
45
+ # LOG.info(
46
+ # {
47
+ # "operation": "load sprite",
48
+ # "tileset": tileset_name,
49
+ # "image": image_name,
50
+ # "sprite": self._sprite_name,
51
+ # }
52
+ # )
53
+ # tileset = self.engine.assets.get_tileset(tileset_name)
54
+
55
+ # self.width = tileset.tile_width
56
+ # self.height = tileset.tile_height
57
+
58
+ # self._sprites: Dict[GraphicState, Dict[Direction, Dict[str, Any]]] = (
59
+ # self._load_sprites_from_tileset(tileset, self._sprite_name)
60
+ # )
61
+
62
+ # else:
63
+ # LOG.debug(
64
+ # "Sprite information uncomplete. Tileset=%s, Image=%s, Sprite="
65
+ # "%s. Will continue without sprite.",
66
+ # tileset_name,
67
+ # image_name,
68
+ # self._sprite_name,
69
+ # )
70
+ # self.name = self._tileset_name = self._sprite_name = ""
71
+
72
+ def update(
73
+ self,
74
+ elapsed_time: float,
75
+ direction: Direction = Direction.SOUTH,
76
+ graphic_state: GraphicState = GraphicState.STANDING,
77
+ ):
78
+ if not self.name:
79
+ return
80
+
81
+ data = self._get_data(graphic_state, direction)
82
+
83
+ if (
84
+ direction == self._last_direction
85
+ and graphic_state == self._last_graphic_state
86
+ ):
87
+ # No changes, normal case
88
+ self._timer -= elapsed_time
89
+ if self._timer <= 0.0:
90
+ self._frame_index = (self._frame_index + 1) % len(
91
+ data["duration"]
92
+ )
93
+ self._timer += data["duration"][self._frame_index]
94
+ self._ox = data["ox"][self._frame_index]
95
+ self._oy = data["oy"][self._frame_index]
96
+ self._image_name = data["image"][self._frame_index]
97
+ self.width = data["width"][self._frame_index]
98
+ self.height = data["height"][self._frame_index]
99
+ else:
100
+ self._frame_index = 0
101
+ # Something changed
102
+ # if graphic_state != self._last_graphic_state:
103
+ # State changed
104
+
105
+ self._timer = data["duration"][0]
106
+ self._ox = data["ox"][0]
107
+ self._oy = data["oy"][0]
108
+ self._image_name = data["image"][0]
109
+ self.width = data["width"][0]
110
+ self.height = data["height"][0]
111
+
112
+ self._last_direction = direction
113
+ self._last_graphic_state = graphic_state
114
+
115
+ def draw_self(
116
+ self,
117
+ px: float,
118
+ py: float,
119
+ camera_name: str = "display",
120
+ absolute_position: bool = False,
121
+ draw_to_ui: bool = False,
122
+ ):
123
+ if not self.name:
124
+ return
125
+
126
+ if not absolute_position:
127
+ px *= self.engine.rtc.tile_width
128
+ py *= self.engine.rtc.tile_height
129
+ px, py = math.floor(px), math.floor(py)
130
+
131
+ self.engine.backend.draw_partial_sprite(
132
+ px,
133
+ py,
134
+ self._image_name,
135
+ self._ox * self.width,
136
+ self._oy * self.height,
137
+ self.width,
138
+ self.height,
139
+ camera_name,
140
+ draw_to_ui=draw_to_ui,
141
+ )
142
+
143
+ def _load_sprites_from_tileset(self, tileset, sprite_name):
144
+ if sprite_name in AnimatedSprite.sprite_sets:
145
+ # Caching
146
+ return AnimatedSprite.sprite_sets[sprite_name]
147
+
148
+ sprites = {}
149
+
150
+ for tile in tileset.tiles:
151
+ if tile.sprite_name != sprite_name:
152
+ continue
153
+
154
+ if tile.animated:
155
+ data = {"duration": [], "ox": [], "oy": []}
156
+ for frame in tile._frames:
157
+ data["duration"].append(frame.duration)
158
+ data["ox"].append(frame.frame_id % tileset.columns)
159
+ data["oy"].append(frame.frame_id // tileset.columns)
160
+ else:
161
+ data = {
162
+ "duration": [1000],
163
+ "ox": [tile.tile_id % tileset.columns],
164
+ "oy": [tile.tile_id // tileset.columns],
165
+ }
166
+
167
+ sprites.setdefault(tile.graphic_state, {})
168
+ sprites[tile.graphic_state][tile.facing_direction] = data
169
+ LOG.debug(
170
+ {
171
+ "operation": "add frames",
172
+ "image": self.name,
173
+ "sprite": sprite_name,
174
+ "graphic_state": tile.graphic_state.name,
175
+ "direction": tile.facing_direction.name,
176
+ "frame_data": data,
177
+ }
178
+ )
179
+
180
+ AnimatedSprite.sprite_sets[sprite_name] = sprites
181
+ return sprites
182
+ # for tile in tileset.tiles
183
+ # Check non-animated tiles if necessary
184
+
185
+ def reset(self):
186
+ self._frame_index = 0
187
+ self._timer = 0.0
188
+
189
+ def _get_data(self, graphic_state, direction):
190
+ if graphic_state == GraphicState.DEFEATED:
191
+ graphic_state = graphic_state.DEAD
192
+
193
+ data = self.sprite_sheet.get(
194
+ graphic_state, self.sprite_sheet.get(GraphicState.STANDING, {})
195
+ )
196
+ data = data.get(direction, data.get(Direction.SOUTH, {}))
197
+ if not data:
198
+ try:
199
+ LOG.debug(
200
+ "Animation of sprite %s is empty for %s, %s ",
201
+ self.name,
202
+ graphic_state.name,
203
+ direction.name,
204
+ )
205
+ except Exception:
206
+ # print(graphic_state, direction)
207
+ LOG.exception(graphic_state, direction)
208
+ raise
209
+ data = {
210
+ "ox": [0],
211
+ "oy": [0],
212
+ "duration": [1.0],
213
+ "image": [""],
214
+ "width": [0],
215
+ "height": [0],
216
+ }
217
+ return data
@@ -0,0 +1,26 @@
1
+ from .attributes import Attributes
2
+
3
+
4
+ class Effect(Attributes):
5
+ def __init__(self):
6
+ super().__init__()
7
+
8
+ self.effect_id: str = ""
9
+ self.duration: float = 0.0
10
+ self.redundant: bool = False
11
+ self.health_cost: float = 0.0
12
+ self.magic_cost: float = 0.0
13
+ self.stamina_cost: float = 0.0
14
+
15
+ def update(self, elapsed_time: float):
16
+ self.duration -= self.elapsed_time
17
+ if self.duration < 0.0:
18
+ self.redundant = True
19
+
20
+ @staticmethod
21
+ def from_dict(data):
22
+ attr = Effect()
23
+ for key, val in data.items():
24
+ setattr(attr, key, val)
25
+
26
+ return attr
@@ -0,0 +1,126 @@
1
+ from typing import Dict
2
+
3
+ from ..types.damage import Damage
4
+ from ..util.constants import ATTRIBUTE_TIMER
5
+
6
+
7
+ class Attributes:
8
+ """A class holding all the attributes of an object.
9
+
10
+ Attributes
11
+ ----------
12
+
13
+ health: float
14
+ The current health of the object.
15
+ health_max: float
16
+ The maximum health of the object.
17
+ speed: float
18
+ The current speed value of the object. If different run speeds
19
+ are not relevant for the object, this is the only value to
20
+ consider. Otherwise, this value might be changed by objects
21
+ itself to reflect different states.
22
+ speed_mod: float
23
+ A modification of the speed used by the game engine, e.g., when
24
+ walking in shallow water
25
+ walk_speed: float
26
+ The speed value when the objects moves slow, e.g., when it is
27
+ walking.
28
+ run_speed: float
29
+ The speed value when the object moves fast, e.g., when it is
30
+ running.
31
+ acceleration: float
32
+ The acceleration of the object when it starts to move. Ranges
33
+ between 0 and 1
34
+ friction: float
35
+ The friction of the object when it stops moving. Ranges between
36
+ 0 and 1.
37
+
38
+ """
39
+
40
+ def __init__(self):
41
+ self.health: float = 10.0
42
+ self.health_max: float = 10.0
43
+ self.health_per_second: float = 0.0
44
+ self.magic: float = 10.0
45
+ self.magic_max: float = 10.0
46
+ self.magic_per_second: float = 0.1
47
+ self.stamina: float = 10.0
48
+ self.stamina_max: float = 10.0
49
+ self.stamina_per_second: float = 2.0
50
+ self.speed: float = 1.0
51
+ self.speed_mod: float = 1.0
52
+ self.walk_speed: float = 1.0
53
+ self.run_speed: float = 1.0
54
+ # self.current_speed: float = 0.0 # Acceleration and Friction
55
+ self.knock_speed: float = 5.0
56
+ self.acceleration: float = 15.0
57
+ self.friction: float = 15.0
58
+
59
+ self.timer: float = 0.25
60
+ self.gravity_vz: float = 40.0
61
+ self.light_radius: float = 32
62
+
63
+ self.coins: int = 0
64
+ self.coins_max: int = 100_000
65
+ self.keys: int = 0
66
+ self.keys_max: int = 100_000
67
+ self.bombs: int = 0
68
+ self.bombs_max: int = 5
69
+ self.arrows: int = 0
70
+ self.arrows_max: int = 15
71
+
72
+ self.body_damage: int = 0
73
+
74
+ self.strength: int = 0
75
+ self.dexterity: int = 0
76
+ self.intelligence: int = 0
77
+ self.wisdom: int = 0
78
+ self.initiative: int = 0
79
+
80
+ self.sell_factor: float = 1.0
81
+ self.buy_factor: float = 1.0
82
+
83
+ self.experience: int = 0
84
+ self.defense: Dict[Damage, int] = {dt: 0 for dt in Damage}
85
+
86
+ def update(self, elapsed_time: float):
87
+ self.timer -= elapsed_time
88
+ if self.timer <= 0.0:
89
+ self.timer += ATTRIBUTE_TIMER
90
+
91
+ self.health = min(
92
+ self.health + self.health_per_second * ATTRIBUTE_TIMER,
93
+ self.health_max,
94
+ )
95
+ self.magic = min(
96
+ self.magic + self.magic_per_second * ATTRIBUTE_TIMER,
97
+ self.magic_max,
98
+ )
99
+ self.stamina = min(
100
+ self.stamina + self.stamina_per_second * ATTRIBUTE_TIMER,
101
+ self.stamina_max,
102
+ )
103
+
104
+ @staticmethod
105
+ def from_dict(data):
106
+ attr = Attributes()
107
+
108
+ for key, val in data.items():
109
+ if "defense" in key:
110
+ def_key = key.split("_", 1)[1]
111
+ attr.defense[def_key] = val
112
+ setattr(attr, key, val)
113
+
114
+ return attr
115
+
116
+ @property
117
+ def health_percent(self):
118
+ return self.health / self.health_max
119
+
120
+ @property
121
+ def magic_percent(self):
122
+ return self.magic / self.magic_max
123
+
124
+ @property
125
+ def stamina_percent(self):
126
+ return self.stamina / self.stamina_max