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.
- mima/__init__.py +1 -0
- mima/backend/__init__.py +1 -0
- mima/backend/pygame_assets.py +345 -0
- mima/backend/pygame_audio.py +75 -0
- mima/backend/pygame_backend.py +399 -0
- mima/backend/pygame_events.py +430 -0
- mima/collision.py +237 -0
- mima/engine.py +197 -0
- mima/maps/__init__.py +0 -0
- mima/maps/template.py +41 -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 +45 -0
- mima/maps/tilemap.py +159 -0
- mima/maps/tileset.py +32 -0
- mima/maps/tileset_info.py +9 -0
- mima/maps/transition_map.py +148 -0
- mima/objects/__init__.py +0 -0
- mima/objects/animated_sprite.py +198 -0
- mima/objects/attribute_effect.py +26 -0
- mima/objects/attributes.py +123 -0
- mima/objects/creature.py +332 -0
- mima/objects/dynamic.py +182 -0
- mima/objects/effects/__init__.py +0 -0
- mima/objects/effects/colorize_screen.py +36 -0
- mima/objects/effects/light.py +107 -0
- mima/objects/effects/walking_on_grass.py +38 -0
- mima/objects/effects/walking_on_water.py +41 -0
- mima/objects/loader.py +103 -0
- mima/objects/projectile.py +86 -0
- mima/objects/sprite.py +110 -0
- mima/objects/world/__init__.py +0 -0
- mima/objects/world/color_gate.py +68 -0
- mima/objects/world/color_switch.py +105 -0
- mima/objects/world/container.py +171 -0
- mima/objects/world/floor_switch.py +111 -0
- mima/objects/world/gate.py +174 -0
- mima/objects/world/light_source.py +124 -0
- mima/objects/world/logic_gate.py +163 -0
- mima/objects/world/movable.py +338 -0
- mima/objects/world/oneway.py +168 -0
- mima/objects/world/pickup.py +88 -0
- mima/objects/world/switch.py +165 -0
- mima/objects/world/teleport.py +288 -0
- mima/scene_engine.py +79 -0
- mima/scripts/__init__.py +2 -0
- mima/scripts/command.py +24 -0
- mima/scripts/commands/__init__.py +0 -0
- mima/scripts/commands/add_quest.py +19 -0
- mima/scripts/commands/change_map.py +15 -0
- mima/scripts/commands/close_dialog.py +8 -0
- mima/scripts/commands/give_item.py +24 -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 +57 -0
- mima/scripts/commands/parallel.py +53 -0
- mima/scripts/commands/play_sound.py +13 -0
- mima/scripts/commands/present_item.py +51 -0
- mima/scripts/commands/progress_quest.py +12 -0
- mima/scripts/commands/quit_game.py +8 -0
- mima/scripts/commands/save_game.py +13 -0
- mima/scripts/commands/screen_fade.py +65 -0
- mima/scripts/commands/serial.py +46 -0
- mima/scripts/commands/set_facing_direction.py +21 -0
- mima/scripts/commands/set_spawn_map.py +14 -0
- mima/scripts/commands/show_choices.py +43 -0
- mima/scripts/commands/show_dialog.py +11 -0
- mima/scripts/commands/take_coins.py +23 -0
- mima/scripts/script_processor.py +40 -0
- mima/states/__init__.py +0 -0
- mima/states/game_state.py +162 -0
- mima/states/quest.py +72 -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 +22 -0
- mima/types/keys.py +16 -0
- mima/types/mode.py +15 -0
- mima/types/nature.py +12 -0
- mima/types/object.py +22 -0
- mima/types/start.py +7 -0
- mima/types/terrain.py +9 -0
- mima/types/weapon_slot.py +6 -0
- mima/usables/__init__.py +0 -0
- mima/usables/item.py +31 -0
- mima/usables/weapon.py +48 -0
- mima/util/__init__.py +1 -0
- mima/util/colors.py +45 -0
- mima/util/constants.py +47 -0
- mima/util/functions.py +13 -0
- mima/util/input_defaults.py +49 -0
- mima/util/logging.py +51 -0
- mima/util/property.py +8 -0
- mima/util/runtime_config.py +133 -0
- mima/view/__init__.py +0 -0
- mima/view/camera.py +51 -0
- mima/view/scene.py +350 -0
- mima_engine-0.1.0.dist-info/METADATA +14 -0
- mima_engine-0.1.0.dist-info/RECORD +114 -0
- mima_engine-0.1.0.dist-info/WHEEL +5 -0
- 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
|
mima/states/__init__.py
ADDED
|
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
|
mima/types/alignment.py
ADDED
mima/types/blend.py
ADDED
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
|
+
]
|
mima/types/direction.py
ADDED
|
@@ -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
|
mima/types/gate_color.py
ADDED
|
@@ -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
mima/types/mode.py
ADDED
mima/types/nature.py
ADDED
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
mima/types/terrain.py
ADDED
mima/usables/__init__.py
ADDED
|
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)
|