mima-engine 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mima-engine might be problematic. Click here for more details.

Files changed (114) hide show
  1. mima/__init__.py +1 -0
  2. mima/backend/__init__.py +1 -0
  3. mima/backend/pygame_assets.py +345 -0
  4. mima/backend/pygame_audio.py +75 -0
  5. mima/backend/pygame_backend.py +399 -0
  6. mima/backend/pygame_events.py +430 -0
  7. mima/collision.py +237 -0
  8. mima/engine.py +197 -0
  9. mima/maps/__init__.py +0 -0
  10. mima/maps/template.py +41 -0
  11. mima/maps/tile.py +20 -0
  12. mima/maps/tile_animation.py +7 -0
  13. mima/maps/tile_info.py +10 -0
  14. mima/maps/tile_layer.py +52 -0
  15. mima/maps/tiled/__init__.py +0 -0
  16. mima/maps/tiled/tiled_layer.py +48 -0
  17. mima/maps/tiled/tiled_map.py +95 -0
  18. mima/maps/tiled/tiled_object.py +79 -0
  19. mima/maps/tiled/tiled_objectgroup.py +25 -0
  20. mima/maps/tiled/tiled_template.py +49 -0
  21. mima/maps/tiled/tiled_tile.py +90 -0
  22. mima/maps/tiled/tiled_tileset.py +45 -0
  23. mima/maps/tilemap.py +159 -0
  24. mima/maps/tileset.py +32 -0
  25. mima/maps/tileset_info.py +9 -0
  26. mima/maps/transition_map.py +148 -0
  27. mima/objects/__init__.py +0 -0
  28. mima/objects/animated_sprite.py +198 -0
  29. mima/objects/attribute_effect.py +26 -0
  30. mima/objects/attributes.py +123 -0
  31. mima/objects/creature.py +332 -0
  32. mima/objects/dynamic.py +182 -0
  33. mima/objects/effects/__init__.py +0 -0
  34. mima/objects/effects/colorize_screen.py +36 -0
  35. mima/objects/effects/light.py +107 -0
  36. mima/objects/effects/walking_on_grass.py +38 -0
  37. mima/objects/effects/walking_on_water.py +41 -0
  38. mima/objects/loader.py +103 -0
  39. mima/objects/projectile.py +86 -0
  40. mima/objects/sprite.py +110 -0
  41. mima/objects/world/__init__.py +0 -0
  42. mima/objects/world/color_gate.py +68 -0
  43. mima/objects/world/color_switch.py +105 -0
  44. mima/objects/world/container.py +171 -0
  45. mima/objects/world/floor_switch.py +111 -0
  46. mima/objects/world/gate.py +174 -0
  47. mima/objects/world/light_source.py +124 -0
  48. mima/objects/world/logic_gate.py +163 -0
  49. mima/objects/world/movable.py +338 -0
  50. mima/objects/world/oneway.py +168 -0
  51. mima/objects/world/pickup.py +88 -0
  52. mima/objects/world/switch.py +165 -0
  53. mima/objects/world/teleport.py +288 -0
  54. mima/scene_engine.py +79 -0
  55. mima/scripts/__init__.py +2 -0
  56. mima/scripts/command.py +24 -0
  57. mima/scripts/commands/__init__.py +0 -0
  58. mima/scripts/commands/add_quest.py +19 -0
  59. mima/scripts/commands/change_map.py +15 -0
  60. mima/scripts/commands/close_dialog.py +8 -0
  61. mima/scripts/commands/give_item.py +24 -0
  62. mima/scripts/commands/give_resource.py +51 -0
  63. mima/scripts/commands/move_map.py +152 -0
  64. mima/scripts/commands/move_to.py +49 -0
  65. mima/scripts/commands/oneway_move.py +57 -0
  66. mima/scripts/commands/parallel.py +53 -0
  67. mima/scripts/commands/play_sound.py +13 -0
  68. mima/scripts/commands/present_item.py +51 -0
  69. mima/scripts/commands/progress_quest.py +12 -0
  70. mima/scripts/commands/quit_game.py +8 -0
  71. mima/scripts/commands/save_game.py +13 -0
  72. mima/scripts/commands/screen_fade.py +65 -0
  73. mima/scripts/commands/serial.py +46 -0
  74. mima/scripts/commands/set_facing_direction.py +21 -0
  75. mima/scripts/commands/set_spawn_map.py +14 -0
  76. mima/scripts/commands/show_choices.py +43 -0
  77. mima/scripts/commands/show_dialog.py +11 -0
  78. mima/scripts/commands/take_coins.py +23 -0
  79. mima/scripts/script_processor.py +40 -0
  80. mima/states/__init__.py +0 -0
  81. mima/states/game_state.py +162 -0
  82. mima/states/quest.py +72 -0
  83. mima/types/__init__.py +0 -0
  84. mima/types/alignment.py +7 -0
  85. mima/types/blend.py +8 -0
  86. mima/types/damage.py +42 -0
  87. mima/types/direction.py +44 -0
  88. mima/types/gate_color.py +7 -0
  89. mima/types/graphic_state.py +22 -0
  90. mima/types/keys.py +16 -0
  91. mima/types/mode.py +15 -0
  92. mima/types/nature.py +12 -0
  93. mima/types/object.py +22 -0
  94. mima/types/start.py +7 -0
  95. mima/types/terrain.py +9 -0
  96. mima/types/weapon_slot.py +6 -0
  97. mima/usables/__init__.py +0 -0
  98. mima/usables/item.py +31 -0
  99. mima/usables/weapon.py +48 -0
  100. mima/util/__init__.py +1 -0
  101. mima/util/colors.py +45 -0
  102. mima/util/constants.py +47 -0
  103. mima/util/functions.py +13 -0
  104. mima/util/input_defaults.py +49 -0
  105. mima/util/logging.py +51 -0
  106. mima/util/property.py +8 -0
  107. mima/util/runtime_config.py +133 -0
  108. mima/view/__init__.py +0 -0
  109. mima/view/camera.py +51 -0
  110. mima/view/scene.py +350 -0
  111. mima_engine-0.1.0.dist-info/METADATA +14 -0
  112. mima_engine-0.1.0.dist-info/RECORD +114 -0
  113. mima_engine-0.1.0.dist-info/WHEEL +5 -0
  114. mima_engine-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,11 @@
1
+ from typing import List
2
+ from ...scripts.command import Command
3
+
4
+
5
+ class CommandShowDialog(Command):
6
+ def __init__(self, lines: List[str]):
7
+ super().__init__()
8
+ self.lines: List[str] = lines
9
+
10
+ def start(self):
11
+ self.engine.scene.show_dialog(self.lines)
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ from ...scripts.command import Command
6
+
7
+ if TYPE_CHECKING:
8
+ from ...objects.dynamic import Dynamic
9
+
10
+
11
+ class CommandTakeCoins(Command):
12
+ def __init__(self, amount: int = 0, dynamic: Optional[Dynamic] = None):
13
+ super().__init__()
14
+
15
+ if dynamic is None:
16
+ dynamic = self.engine.player
17
+
18
+ self._amount: int = amount
19
+ self._dynamic: Dynamic = dynamic
20
+
21
+ def start(self):
22
+ self._dynamic.attributes.coins -= self._amount
23
+ self.completed = True
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, List
4
+
5
+ from .command import Command
6
+
7
+ if TYPE_CHECKING:
8
+ from ..engine import MimaEngine
9
+
10
+
11
+ class ScriptProcessor:
12
+ engine: MimaEngine
13
+
14
+ def __init__(self):
15
+ self.commands: List[Command] = []
16
+ self.user_control_enabled: bool = True
17
+
18
+ def add_command(self, cmd: Command):
19
+ self.commands.append(cmd)
20
+
21
+ def process_command(self, elapsed_time: float):
22
+ self.user_control_enabled = len(self.commands) == 0
23
+ if self.commands:
24
+ if not self.commands[0].completed:
25
+ if not self.commands[0].started:
26
+ self.commands[0].start()
27
+ self.commands[0].started = True
28
+ else:
29
+ self.commands[0].update(elapsed_time)
30
+ else:
31
+ self.commands[0].finalize()
32
+ self.commands.pop(0)
33
+
34
+ def complete_command(self, force: bool = False):
35
+ if self.commands:
36
+ if self.commands[0].uninterruptible and not force:
37
+ return False
38
+ else:
39
+ self.commands[0].completed = True
40
+ return True
File without changes
@@ -0,0 +1,162 @@
1
+ import json
2
+ import logging
3
+ import os
4
+ from os import PathLike
5
+ from typing import Any, Dict, List, Optional, Union
6
+
7
+ from ..util.functions import strtobool
8
+
9
+ LOG = logging.getLogger(__name__)
10
+
11
+
12
+ class GameState:
13
+ def __init__(self, filename: PathLike):
14
+ self.filename = filename
15
+ self._state: Dict[str, Any] = {
16
+ "savefile_name": os.path.split(self.filename)[-1].split(".")[0]
17
+ }
18
+
19
+ def save_value(
20
+ self, key: str, value: Union[int, float, bool, str, dict, list]
21
+ ):
22
+ parts = key.split("__")
23
+ state = self._state
24
+ for idx, part in enumerate(parts):
25
+ if idx < len(parts) - 1:
26
+ state = state.setdefault(part, {})
27
+ else:
28
+ state[part] = value
29
+
30
+ def load_value(
31
+ self,
32
+ key: str,
33
+ default: Optional[Union[int, float, bool, str, dict, list]] = None,
34
+ astype: Optional[str] = None,
35
+ ) -> Optional[Union[int, float, bool, str, dict, list]]:
36
+ parts = key.split("__")
37
+ state = self._state
38
+ for idx, part in enumerate(parts):
39
+ if idx >= len(parts) - 1:
40
+ # state = state.get(part)
41
+ if state is None:
42
+ return default
43
+ else:
44
+ state = state.get(part)
45
+ if state is None:
46
+ return default
47
+ if astype is not None:
48
+ return convert(state, astype)
49
+ return state
50
+
51
+ state = state.get(part)
52
+
53
+ def load_group(self, key: str, *more_keys: str):
54
+ data = self._state.get(key, {})
55
+ for key in more_keys:
56
+ data = data.get(key, {})
57
+ return data
58
+
59
+ def load_from_disk(self, autosave: bool = False):
60
+ filename = self.filename
61
+ if autosave:
62
+ filename = os.path.join(
63
+ os.path.split(filename)[0], "autosave.json"
64
+ )
65
+ try:
66
+ with open(filename, "r") as fp:
67
+ self._state = json.load(fp)
68
+ except FileNotFoundError:
69
+ LOG.info("No saved state found!")
70
+ except json.decoder.JSONDecodeError:
71
+ LOG.info("No saved state found or state corrupted.")
72
+
73
+ if autosave:
74
+ self.filename = os.path.join(
75
+ os.path.split(filename)[0],
76
+ f"{self._state['savefile_name']}.json",
77
+ )
78
+
79
+ def save_to_disk(self, autosave: bool = False):
80
+ filename = self.filename
81
+ if autosave:
82
+ filename = os.path.join(
83
+ os.path.split(filename)[0], "autosave.json"
84
+ )
85
+ self.save_value("player__pos_x", 5.0)
86
+ self.save_value("player__pos_y", 5.0)
87
+ self.save_value(
88
+ "player__map_name", self.load_value("player__spawn_map")
89
+ )
90
+ else:
91
+ self._state["savefile_name"] = os.path.split(filename)[-1].split(
92
+ "."
93
+ )[0]
94
+ # Auto save file will be removed after a successful save
95
+ try:
96
+ os.remove(
97
+ os.path.join(os.path.split(filename)[0], "autosave.json")
98
+ )
99
+ except FileNotFoundError:
100
+ pass
101
+
102
+ with open(filename, "w") as fp:
103
+ json.dump(self._state, fp, sort_keys=False, indent=4)
104
+
105
+ def delete_keys(self, scope, keypart, exceptions):
106
+ k2d = []
107
+ for k in self._state[scope]:
108
+ if keypart in k and k not in exceptions:
109
+ k2d.append(k)
110
+ for k in k2d:
111
+ del self._state[scope][k]
112
+
113
+
114
+ def convert(value, astype):
115
+ if astype == "int":
116
+ try:
117
+ return int(value)
118
+ except TypeError:
119
+ return value
120
+ if astype == "float":
121
+ try:
122
+ return float(value)
123
+ except TypeError:
124
+ return value
125
+ if astype == "bool":
126
+ try:
127
+ return strtobool(value)
128
+ except AttributeError:
129
+ value
130
+ return value
131
+
132
+
133
+ def load_saved_games(save_path, save_file_name):
134
+ all_games = {}
135
+ if not os.path.isdir(save_path):
136
+ LOG.warning(f"Save folder does not exist: {save_path}")
137
+ return all_games
138
+
139
+ files = os.listdir(save_path)
140
+ if not files:
141
+ LOG.info(f"No save files found at {save_path}")
142
+ return all_games
143
+
144
+ if "autosave.json" in files:
145
+ all_games["autosave"] = GameState(
146
+ os.path.join(save_path, "autosave.json")
147
+ )
148
+ all_games["autosave"].load_from_disk(autosave=True)
149
+ LOG.debug("Loading saved game from autosave.json")
150
+
151
+ game_idx = 0
152
+ while True:
153
+ savegame = f"{save_file_name}{game_idx:03d}.json"
154
+ if savegame in files:
155
+ all_games[savegame] = GameState(os.path.join(save_path, savegame))
156
+ all_games[savegame].load_from_disk()
157
+ LOG.debug(f"Loading saved game from {savegame}")
158
+ game_idx += 1
159
+ if game_idx >= len(files):
160
+ break
161
+
162
+ return all_games
mima/states/quest.py ADDED
@@ -0,0 +1,72 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, List
4
+
5
+ from ..util.functions import strtobool
6
+
7
+ if TYPE_CHECKING:
8
+ from ..engine.mima_engine import MimaEngine
9
+ from ..objects.dynamic import Dynamic
10
+ from ..types.nature import Nature
11
+
12
+
13
+ class Quest:
14
+ engine: MimaEngine
15
+
16
+ def __init__(self):
17
+ self.name: str = "Unnamed Quest"
18
+ self.accepted: bool = False
19
+ self.reward_unlocked: bool = False
20
+ self.reward_received: bool = False
21
+ self.completed: bool = False
22
+ self.state: int = 0
23
+
24
+ def on_interaction(
25
+ self, dynamics: List[Dynamic], target: Dynamic, nature: Nature
26
+ ):
27
+ return False
28
+
29
+ def populate_dynamics(self, dynamics: List[Dynamic], map_name: str):
30
+ return False
31
+
32
+ def load_state(self):
33
+ state = self.engine.game_state.load_group("quest", self.name)
34
+ # key = f"quest__{self.name}__"
35
+ self.accepted = state.get("accepted", False)
36
+ self.reward_unlocked = state.get("reward_unlocked", False)
37
+ self.reward_received = state.get("reward_received", False)
38
+ self.completed = state.get("completed", False)
39
+ self.state = state.get("state", 0)
40
+
41
+ def save_state(self):
42
+ key = f"quest__{self.name}__"
43
+ self.clean_up()
44
+ self.engine.game_state.save_value(f"{key}accepted", self.accepted)
45
+ self.engine.game_state.save_value(f"{key}completed", self.completed)
46
+ self.engine.game_state.save_value(
47
+ f"{key}reward_received", self.reward_received
48
+ )
49
+ self.engine.game_state.save_value(
50
+ f"{key}reward_unlocked", self.reward_unlocked
51
+ )
52
+ self.engine.game_state.save_value(f"{key}state", self.state)
53
+
54
+ def clean_up(self):
55
+ if self.accepted is None or not isinstance(self.accepted, bool):
56
+ self.accepted = False
57
+
58
+ if self.completed is None or not isinstance(self.completed, bool):
59
+ self.completed = False
60
+
61
+ if self.reward_unlocked is None or not isinstance(
62
+ self.reward_unlocked, bool
63
+ ):
64
+ self.reward_unlocked = False
65
+
66
+ if self.reward_received is None or not isinstance(
67
+ self.reward_received, bool
68
+ ):
69
+ self.reward_received = False
70
+
71
+ if self.state is None or not isinstance(self.state, int):
72
+ self.state = 0
mima/types/__init__.py ADDED
File without changes
@@ -0,0 +1,7 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Alignment(Enum):
5
+ GOOD = 0
6
+ NEUTRAL = 1
7
+ EVIL = 2
mima/types/blend.py ADDED
@@ -0,0 +1,8 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Blend(Enum):
5
+ DEFAULT = 0
6
+ ADD = 1
7
+ SUB = 2
8
+ MULT = 3
mima/types/damage.py ADDED
@@ -0,0 +1,42 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Damage(Enum):
5
+ NO_DAMAGE = 0
6
+ BODY = 1
7
+ SLICING = 2
8
+ PIERCING = 3
9
+ HEAVY = 4
10
+ EXPLOSION = 5
11
+ MAGIC = 6
12
+ FIRE = 7
13
+ WATER = 8
14
+ WIND = 9
15
+ EARTH = 10
16
+ HEAL = 11
17
+ DARK = 12
18
+ FRONT = 13
19
+ SIDE = 14
20
+ BACK = 15
21
+
22
+
23
+ PHYSICAL = [
24
+ Damage.BODY,
25
+ Damage.SLICING,
26
+ Damage.PIERCING,
27
+ Damage.HEAVY,
28
+ Damage.EXPLOSION,
29
+ Damage.FRONT,
30
+ Damage.SIDE,
31
+ Damage.BACK,
32
+ ]
33
+
34
+ MAGICAL = [
35
+ Damage.MAGIC,
36
+ Damage.FIRE,
37
+ Damage.WATER,
38
+ Damage.WIND,
39
+ Damage.EARTH,
40
+ Damage.HEAL,
41
+ Damage.DARK,
42
+ ]
@@ -0,0 +1,44 @@
1
+ from __future__ import annotations
2
+
3
+ from enum import Enum
4
+ from typing import Tuple
5
+
6
+
7
+ class Direction(Enum):
8
+ SOUTH = 0
9
+ WEST = 1
10
+ NORTH = 2
11
+ EAST = 3
12
+
13
+ def from_velocity(vx: float, vy: float):
14
+ direction = None
15
+ if abs(vx) >= abs(vy):
16
+ if vx > 0:
17
+ direction = Direction.EAST
18
+ elif vx < 0:
19
+ direction = Direction.WEST
20
+ else:
21
+ # TODO: Check for up and down
22
+ pass
23
+ elif abs(vx) < abs(vy):
24
+ if vy > 0:
25
+ direction = Direction.SOUTH
26
+ elif vy < 0:
27
+ direction = Direction.NORTH
28
+ else:
29
+ # TODO: Check for left and right
30
+ pass
31
+ return direction
32
+
33
+ def to_velocity(direction: Direction) -> Tuple[int, int]:
34
+ vx = vy = 0
35
+
36
+ if direction == Direction.SOUTH:
37
+ vy = 1
38
+ elif direction == Direction.EAST:
39
+ vx = 1
40
+ elif direction == Direction.NORTH:
41
+ vy = -1
42
+ elif direction == Direction.WEST:
43
+ vx = -1
44
+ return vx, vy
@@ -0,0 +1,7 @@
1
+ from enum import Enum
2
+
3
+
4
+ class GateColor(Enum):
5
+ RED = 0
6
+ GREEN = 1
7
+ BLUE = 2
@@ -0,0 +1,22 @@
1
+ from enum import Enum
2
+
3
+
4
+ class GraphicState(Enum):
5
+ STANDING = 0
6
+ WALKING = 1
7
+ ATTACKING = 2
8
+ DAMAGED = 3
9
+ CELEBRATING = 4
10
+ DEAD = 5
11
+ DEFEATED = 6
12
+ PUSHING = 7
13
+ OPEN = 8
14
+ CLOSED = 9
15
+ LOCKED = 10
16
+ OFF = 11
17
+ ON = 12
18
+
19
+
20
+ class Until(Enum):
21
+ UNLOCK = 0
22
+ NEXT_UPDATE = 1
mima/types/keys.py ADDED
@@ -0,0 +1,16 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Key(Enum):
5
+ UP = 0
6
+ DOWN = 1
7
+ LEFT = 2
8
+ RIGHT = 3
9
+ A = 4
10
+ B = 5
11
+ X = 6
12
+ Y = 7
13
+ R = 8
14
+ L = 9
15
+ START = 10
16
+ SELECT = 11
mima/types/mode.py ADDED
@@ -0,0 +1,15 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Mode(Enum):
5
+ LOADING = 0
6
+ TITLE = 1
7
+ SELECT_GAME = 2
8
+ LOCAL_MAP = 3
9
+ WORLD_MAP = 4
10
+ INVENTORY = 5
11
+ SHOP = 6
12
+ GAME_OVER = 7
13
+ TITLE_SETTINGS = 8
14
+ CONTROLS = 9
15
+ COMBAT = 10
mima/types/nature.py ADDED
@@ -0,0 +1,12 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Nature(Enum):
5
+ WALK = 0
6
+ TALK = 1
7
+ ATTACK = 2
8
+ KILLED = 3
9
+ SIGNAL = 4
10
+ NO_SIGNAL = 5
11
+ SAVE = 6
12
+ LOAD = 7
mima/types/object.py ADDED
@@ -0,0 +1,22 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ObjectType(Enum):
5
+ UNDEFINED = -1
6
+ PLAYER = 0
7
+ DYNAMIC = 1
8
+ PROJECTILE = 2
9
+ CREATURE = 3
10
+ SCRIPTED_CREATURE = 4
11
+ TELEPORT = 5
12
+ PICKUP = 6
13
+ MOVABLE = 7
14
+ GATE = 8
15
+ CONTAINER = 9
16
+ SWITCH = 10
17
+ FLOOR_SWITCH = 11
18
+ ONEWAY = 12
19
+ LOGIC_GATE = 13
20
+ LIGHT_SOURCE = 14
21
+ COLOR_SWITCH = 15
22
+ COLOR_GATE = 16
mima/types/start.py ADDED
@@ -0,0 +1,7 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Start:
5
+ NEW = 0
6
+ LOAD = 1
7
+ GAME_OVER = 2
mima/types/terrain.py ADDED
@@ -0,0 +1,9 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Terrain(Enum):
5
+ DEFAULT = 0
6
+ GRASS = 1
7
+ SHALLOW_WATER = 2
8
+ DEEP_WATER = 3
9
+ OCEAN = 4
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+
4
+ class WeaponSlot(Enum):
5
+ FIRST_HAND = 0
6
+ SECOND_HAND = 1
File without changes
mima/usables/item.py ADDED
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from ..util.constants import DEFAULT_SPRITE_HEIGHT, DEFAULT_SPRITE_WIDTH
6
+
7
+ if TYPE_CHECKING:
8
+ from ..engine import MimaEngine
9
+ from ..objects.creature import Creature
10
+ from ..objects.dynamic import Dynamic
11
+
12
+
13
+ class Item:
14
+ engine: MimaEngine
15
+
16
+ def __init__(self, name: str, sprite_name: str, description: str):
17
+ self.name: str = name
18
+ self.description: str = description
19
+ self.sprite_name: str = sprite_name
20
+ self.sprite_ox: int = 0
21
+ self.sprite_oy: int = 0
22
+ self.sprite_width: int = DEFAULT_SPRITE_WIDTH
23
+ self.sprite_height: int = DEFAULT_SPRITE_HEIGHT
24
+ self.key_item: bool = False
25
+ self.equipable: bool = False
26
+
27
+ def on_interaction(self, obj: Dynamic):
28
+ return False
29
+
30
+ def on_use(self, obj: Creature):
31
+ return False
mima/usables/weapon.py ADDED
@@ -0,0 +1,48 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Tuple
4
+
5
+ from ..types.damage import Damage
6
+ from ..types.direction import Direction
7
+ from .item import Item
8
+
9
+ if TYPE_CHECKING:
10
+ from ..objects.creature import Creature
11
+
12
+
13
+ class Weapon(Item):
14
+ def __init__(self, name: str, sprite: str, description: str):
15
+ super().__init__(name, sprite, description)
16
+
17
+ self.equipable = True
18
+
19
+ self.damage: int = 0
20
+ self.dtype: Damage = Damage.BODY
21
+ self.health_cost: int = 0
22
+ self.magic_cost: int = 0
23
+ self.stamina_cost: int = 0
24
+ self.arrow_cost: int = 0
25
+ self.bomb_cost: int = 0
26
+ self.swing_timer: int = 0.2
27
+ # self.projectiles: List[Projectile] = []
28
+
29
+ def _determine_attack_origin(self, obj: Creature) -> Tuple[float, float]:
30
+ vx = 0.0
31
+ vy = 0.0
32
+
33
+ if obj.facing_direction == Direction.SOUTH:
34
+ vy = 1.0
35
+ if obj.facing_direction == Direction.WEST:
36
+ vx = -1.0
37
+ if obj.facing_direction == Direction.NORTH:
38
+ vy = -1.0
39
+ if obj.facing_direction == Direction.EAST:
40
+ vx = 1.0
41
+
42
+ return vx, vy
43
+
44
+ def on_equip(self, obj: Creature):
45
+ pass
46
+
47
+ def on_unequip(self, obj: Creature):
48
+ pass
mima/util/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from .runtime_config import RuntimeConfig
mima/util/colors.py ADDED
@@ -0,0 +1,45 @@
1
+ from typing import Tuple
2
+
3
+
4
+ class Color:
5
+ def __init__(self, red: int, green: int, blue: int, alpha: int = 255):
6
+ self.red = red
7
+ self.green = green
8
+ self.blue = blue
9
+ self.alpha = alpha
10
+
11
+ def getRGBA(self) -> Tuple[int, int, int, int]:
12
+ return (self.red, self.green, self.blue, self.alpha)
13
+
14
+ def getRGB(self) -> Tuple[int, int, int]:
15
+ return (self.red, self.green, self.blue)
16
+
17
+ def __repr__(self):
18
+ return (
19
+ f"Color(red={self.red}, green={self.green}, "
20
+ f"blue={self.blue}, alpha={self.alpha})"
21
+ )
22
+
23
+ def short_name(self):
24
+ return f"{self.red}-{self.green}-{self.blue}-{self.alpha}"
25
+
26
+
27
+ BLACK = Color(0, 0, 0)
28
+ WHITE = Color(255, 255, 255)
29
+ ALPHA = Color(254, 253, 254)
30
+ LIGHTGREY = Color(100, 100, 100)
31
+ DARK_GREY = Color(64, 64, 64, 160)
32
+ VERY_LIGHT_GREY = Color(195, 195, 195)
33
+ RED = Color(255, 0, 0)
34
+ GREEN = Color(0, 255, 0)
35
+ BLUE = Color(0, 0, 255)
36
+ YELLOW = Color(255, 255, 0)
37
+ CYAN = Color(0, 255, 255)
38
+ PURPLE = Color(128, 0, 128)
39
+ DARK_RED = Color(64, 0, 0, 160)
40
+ DARK_GREEN = Color(0, 64, 0, 160)
41
+ DARK_BLUE = Color(0, 0, 64, 160)
42
+ DARK_YELLOW = Color(64, 64, 0, 160)
43
+ DARK_CYAN = Color(0, 64, 64, 160)
44
+ DARK_PURPLE = Color(64, 0, 64, 160)
45
+ TRANS_CYAN = Color(0, 64, 64, 128)