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
mima/util/constants.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Tile dimensions
|
|
2
|
+
WIDTH: int = int(256 * 1) # TODO: remove
|
|
3
|
+
HEIGHT: int = int(144 * 1) # TODO: remove
|
|
4
|
+
TILE_WIDTH: int = 16
|
|
5
|
+
TILE_HEIGHT: int = TILE_WIDTH
|
|
6
|
+
DEFAULT_SPRITE_WIDTH: int = TILE_WIDTH
|
|
7
|
+
DEFAULT_SPRITE_HEIGHT: int = TILE_HEIGHT
|
|
8
|
+
UI_HIGHT: int = 1 # TODO: remove
|
|
9
|
+
|
|
10
|
+
# Map transition
|
|
11
|
+
MOVE_MAP_DURATION: float = 1.0
|
|
12
|
+
MAP_TRANSITION_DURATION_FACTOR: float = 0.75
|
|
13
|
+
ONEWAY_ACTIVATION_DELAY: float = 0.175
|
|
14
|
+
ONEWAY_SPEED_BOOST: float = 2.0
|
|
15
|
+
|
|
16
|
+
# Gamepad
|
|
17
|
+
AXIS_DEADZONE: float = 0.25
|
|
18
|
+
AXIS_ACTIVATION: float = 0.5
|
|
19
|
+
|
|
20
|
+
# Touchscreen
|
|
21
|
+
TOUCH_ACTIVATION: float = 0.001
|
|
22
|
+
SINGLE_TAP_MIN: float = 0.2
|
|
23
|
+
SINGLE_TAP_MAX: float = 1.0
|
|
24
|
+
DOUBLE_TAP_SPEED: float = 0.2
|
|
25
|
+
|
|
26
|
+
# Font
|
|
27
|
+
BIG_FONT_NAME: str = "pixel-font"
|
|
28
|
+
BIG_FONT_WIDTH: int = 6
|
|
29
|
+
BIG_FONT_HEIGHT: int = 8
|
|
30
|
+
SMALL_FONT_NAME: str = "pixel-font-small"
|
|
31
|
+
SMALL_FONT_WIDTH: int = 4
|
|
32
|
+
SMALL_FONT_HEIGHT: int = 5
|
|
33
|
+
|
|
34
|
+
# Dynamics
|
|
35
|
+
DEFAULT_GRAPHIC_TIMER_STANDING: float = 0.5
|
|
36
|
+
DEFAULT_GRAPHIC_TIMER_WALKING: float = 0.15
|
|
37
|
+
DEFAULT_GRAPHIC_TIMER_DAMAGED: float = 0.075
|
|
38
|
+
DEFAULT_GRAPHIC_TIMER_DEAD: float = 0.25
|
|
39
|
+
DEFAULT_GRAPHIC_TIMER: float = 0.5
|
|
40
|
+
ATTRIBUTE_TIMER: float = 0.25
|
|
41
|
+
DEFAULT_KNOCK_SPEED: float = 5.0
|
|
42
|
+
|
|
43
|
+
# Gameplay
|
|
44
|
+
ABYSS_DAMAGE: int = 1
|
|
45
|
+
PLAYER_BASE_HEALTH: int = 30
|
|
46
|
+
PLAYER_BASE_SPEED: float = 4.5
|
|
47
|
+
PLAYER_BASE_RUN_SPEED: float = 6.0
|
mima/util/functions.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
def strtobool(val: str) -> bool:
|
|
2
|
+
"""Convert a string representation of truth to true (1) or false (0).
|
|
3
|
+
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
|
|
4
|
+
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
|
|
5
|
+
'val' is anything else.
|
|
6
|
+
"""
|
|
7
|
+
val = val.lower()
|
|
8
|
+
if val in ("y", "yes", "t", "true", "on", "1"):
|
|
9
|
+
return 1
|
|
10
|
+
elif val in ("n", "no", "f", "false", "off", "0", ""):
|
|
11
|
+
return 0
|
|
12
|
+
else:
|
|
13
|
+
raise ValueError("invalid truth value %r" % (val,))
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from ..types.keys import Key as K
|
|
2
|
+
|
|
3
|
+
BUTTONS = [
|
|
4
|
+
K.UP,
|
|
5
|
+
K.DOWN,
|
|
6
|
+
K.LEFT,
|
|
7
|
+
K.RIGHT,
|
|
8
|
+
K.START,
|
|
9
|
+
K.SELECT,
|
|
10
|
+
K.A,
|
|
11
|
+
K.B,
|
|
12
|
+
K.X,
|
|
13
|
+
K.Y,
|
|
14
|
+
K.L,
|
|
15
|
+
K.R,
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Keyboard
|
|
20
|
+
# The arrow keys need to be uppercase, other keys are lowercase
|
|
21
|
+
DEFAULT_KEYBOARD_MAP = {
|
|
22
|
+
K.UP: ["w", "UP"],
|
|
23
|
+
K.DOWN: ["s", "DOWN"],
|
|
24
|
+
K.LEFT: ["a", "LEFT"],
|
|
25
|
+
K.RIGHT: ["d", "RIGHT"],
|
|
26
|
+
K.START: ["i"],
|
|
27
|
+
K.SELECT: ["t"],
|
|
28
|
+
K.A: ["k"],
|
|
29
|
+
K.B: ["h"],
|
|
30
|
+
K.X: ["l"],
|
|
31
|
+
K.Y: ["j"],
|
|
32
|
+
K.L: ["o"],
|
|
33
|
+
K.R: ["c"],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
DEFAULT_JOYSTICK_MAP = {
|
|
37
|
+
K.UP: ["up"],
|
|
38
|
+
K.DOWN: ["down"],
|
|
39
|
+
K.LEFT: ["left"],
|
|
40
|
+
K.RIGHT: ["right"],
|
|
41
|
+
K.START: [7],
|
|
42
|
+
K.SELECT: [6],
|
|
43
|
+
K.A: [0],
|
|
44
|
+
K.B: [1],
|
|
45
|
+
K.X: [3],
|
|
46
|
+
K.Y: [2],
|
|
47
|
+
K.L: [4],
|
|
48
|
+
K.R: [5],
|
|
49
|
+
}
|
mima/util/logging.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import logging.config
|
|
3
|
+
|
|
4
|
+
_TRACE_INSTALLED = False
|
|
5
|
+
_DEFAULT_CONFIG = {
|
|
6
|
+
"version": 1,
|
|
7
|
+
"formatters": {
|
|
8
|
+
"brief": {
|
|
9
|
+
"format": ("%(asctime)s [%(name)s][%(levelname)s] %(message)s")
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
"handlers": {
|
|
13
|
+
"console": {
|
|
14
|
+
"class": "logging.StreamHandler",
|
|
15
|
+
"formatter": "brief",
|
|
16
|
+
"level": "INFO",
|
|
17
|
+
"stream": "ext://sys.stdout",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
"root": {
|
|
21
|
+
"level": "ERROR",
|
|
22
|
+
"handlers": ["console"],
|
|
23
|
+
},
|
|
24
|
+
"loggers": {
|
|
25
|
+
"mima": {"level": "TRACE"},
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def install_trace_logger():
|
|
31
|
+
global _TRACE_INSTALLED
|
|
32
|
+
if _TRACE_INSTALLED:
|
|
33
|
+
return
|
|
34
|
+
level = logging.TRACE = logging.DEBUG - 5
|
|
35
|
+
|
|
36
|
+
def log_logger(self, message, *args, **kwargs):
|
|
37
|
+
if self.isEnabledFor(level):
|
|
38
|
+
self._log(level, message, args, **kwargs)
|
|
39
|
+
|
|
40
|
+
logging.getLoggerClass().trace = log_logger
|
|
41
|
+
|
|
42
|
+
def log_root(msg, *args, **kwargs):
|
|
43
|
+
logging.log(level, msg, *args, **kwargs)
|
|
44
|
+
|
|
45
|
+
logging.addLevelName(level, "TRACE")
|
|
46
|
+
logging.trace = log_root
|
|
47
|
+
_TRACE_INSTALLED = True
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def configure_logging(config=_DEFAULT_CONFIG):
|
|
51
|
+
logging.config.dictConfig(config)
|
mima/util/property.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import configparser
|
|
2
|
+
import os
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from typing import Any, Dict
|
|
5
|
+
|
|
6
|
+
from ..types.keys import Key as K
|
|
7
|
+
from .colors import Color
|
|
8
|
+
from .functions import strtobool
|
|
9
|
+
|
|
10
|
+
DEFAULT_CONFIG = {
|
|
11
|
+
"keymap": {
|
|
12
|
+
"UP": "w",
|
|
13
|
+
"DOWN": "s",
|
|
14
|
+
"LEFT": "a",
|
|
15
|
+
"RIGHT": "d",
|
|
16
|
+
"A": "k",
|
|
17
|
+
"B": "h",
|
|
18
|
+
"X": "l",
|
|
19
|
+
"Y": "j",
|
|
20
|
+
"L": "o",
|
|
21
|
+
"R": "c",
|
|
22
|
+
"START": "i",
|
|
23
|
+
"SELECT": "t",
|
|
24
|
+
},
|
|
25
|
+
"colors": {
|
|
26
|
+
"gb_dark": "42,0,0",
|
|
27
|
+
"gb_medium_dark": "91,86,95",
|
|
28
|
+
"gb_medium_light": "186,191,181",
|
|
29
|
+
"gb_light": "255,255,241",
|
|
30
|
+
},
|
|
31
|
+
"flags": {"use_color": "false"},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class RuntimeConfig:
|
|
36
|
+
def __init__(self, config_path: str = ""):
|
|
37
|
+
self._loaded: Dict[str, Any] = deepcopy(DEFAULT_CONFIG)
|
|
38
|
+
self._converted: Dict[str, Any] = {}
|
|
39
|
+
|
|
40
|
+
if not config_path:
|
|
41
|
+
config_path = os.path.abspath(
|
|
42
|
+
os.path.join(os.getcwd(), "avenight.ini")
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
self._config_path = config_path
|
|
46
|
+
config = configparser.ConfigParser()
|
|
47
|
+
|
|
48
|
+
if os.path.exists(config_path):
|
|
49
|
+
config.read(config_path)
|
|
50
|
+
|
|
51
|
+
if config.sections():
|
|
52
|
+
self._read_config(config)
|
|
53
|
+
|
|
54
|
+
else:
|
|
55
|
+
self._write_config(config)
|
|
56
|
+
|
|
57
|
+
else:
|
|
58
|
+
self._write_config(config)
|
|
59
|
+
|
|
60
|
+
def _read_config(self, config: configparser.ConfigParser):
|
|
61
|
+
for key, mapping in config["keymap"].items():
|
|
62
|
+
vals = mapping.strip().split(",")
|
|
63
|
+
self._loaded["keymap"][key.upper()] = vals
|
|
64
|
+
|
|
65
|
+
self._loaded["colors"]["gb_dark"] = config["colors"]["gb_dark"]
|
|
66
|
+
self._loaded["colors"]["gb_medium_dark"] = config["colors"][
|
|
67
|
+
"gb_medium_dark"
|
|
68
|
+
]
|
|
69
|
+
self._loaded["colors"]["gb_medium_light"] = config["colors"][
|
|
70
|
+
"gb_medium_light"
|
|
71
|
+
]
|
|
72
|
+
self._loaded["colors"]["gb_light"] = config["colors"]["gb_light"]
|
|
73
|
+
|
|
74
|
+
self._loaded["flags"]["use_color"] = config["flags"]["use_color"]
|
|
75
|
+
|
|
76
|
+
def _write_config(self, config: configparser.ConfigParser):
|
|
77
|
+
config["keymap"] = {}
|
|
78
|
+
config["colors"] = {}
|
|
79
|
+
config["flags"] = {}
|
|
80
|
+
for key, mapping in self._loaded["keymap"].items():
|
|
81
|
+
config["keymap"][key.lower()] = mapping
|
|
82
|
+
|
|
83
|
+
config["colors"]["gb_dark"] = self._loaded["colors"]["gb_dark"]
|
|
84
|
+
config["colors"]["gb_medium_dark"] = self._loaded["colors"][
|
|
85
|
+
"gb_medium_dark"
|
|
86
|
+
]
|
|
87
|
+
config["colors"]["gb_medium_light"] = self._loaded["colors"][
|
|
88
|
+
"gb_medium_light"
|
|
89
|
+
]
|
|
90
|
+
config["colors"]["gb_light"] = self._loaded["colors"]["gb_light"]
|
|
91
|
+
|
|
92
|
+
config["flags"]["use_color"] = self._loaded["flags"]["use_color"]
|
|
93
|
+
|
|
94
|
+
with open(self._config_path, "w") as cfg_file:
|
|
95
|
+
config.write(cfg_file)
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def keymap(self):
|
|
99
|
+
if "keymap" in self._converted:
|
|
100
|
+
return self._converted["keymap"]
|
|
101
|
+
else:
|
|
102
|
+
self._converted["keymap"] = {}
|
|
103
|
+
for but in K:
|
|
104
|
+
self._converted["keymap"][but] = self._loaded["keymap"][
|
|
105
|
+
but.name
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
return self._converted["keymap"]
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def colors(self) -> Dict[str, Color]:
|
|
112
|
+
if "colors" in self._converted:
|
|
113
|
+
return self._converted["colors"]
|
|
114
|
+
else:
|
|
115
|
+
self._converted["colors"] = {}
|
|
116
|
+
for key, val in self._loaded["colors"].items():
|
|
117
|
+
self._converted["colors"][key] = Color(
|
|
118
|
+
*[int(p) for p in val.strip().split(",")]
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return self._converted["colors"]
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def flags(self) -> Dict[str, bool]:
|
|
125
|
+
if "flags" in self._converted:
|
|
126
|
+
return self._converted["flags"]
|
|
127
|
+
else:
|
|
128
|
+
self._converted["flags"] = {}
|
|
129
|
+
self._converted["flags"]["use_color"] = strtobool(
|
|
130
|
+
self._loaded["flags"]["use_color"]
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
return self._converted["flags"]
|
mima/view/__init__.py
ADDED
|
File without changes
|
mima/view/camera.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
|
+
|
|
5
|
+
from ..util.constants import TILE_HEIGHT, TILE_WIDTH
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from ..maps.tilemap import Tilemap
|
|
9
|
+
from ..objects.dynamic import Dynamic
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Camera:
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
visible_tiles_sx: int = 0,
|
|
16
|
+
visible_tiles_sy: int = 0,
|
|
17
|
+
visible_tiles_ex: Optional[int] = None,
|
|
18
|
+
visible_tiles_ey: Optional[int] = None,
|
|
19
|
+
):
|
|
20
|
+
self.visible_tiles_sx: int = visible_tiles_sx
|
|
21
|
+
self.visible_tiles_sy: int = visible_tiles_sy
|
|
22
|
+
self.visible_tiles_ex: int = visible_tiles_ex
|
|
23
|
+
self.visible_tiles_ey: int = visible_tiles_ey
|
|
24
|
+
|
|
25
|
+
if self.visible_tiles_ex is None:
|
|
26
|
+
self.visible_tiles_ex = (
|
|
27
|
+
self.engine.backend.render_width / TILE_WIDTH
|
|
28
|
+
- self.visible_tiles_sx
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
if self.visible_tiles_ey is None:
|
|
32
|
+
self.visible_tiles_ey = (
|
|
33
|
+
self.engine.backend.render_height / TILE_HEIGHT
|
|
34
|
+
- self.visible_tiles_sy
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def update(self, target: Dynamic, tilemap: Tilemap):
|
|
38
|
+
|
|
39
|
+
# Calculate x offset
|
|
40
|
+
self.ox = target.px - self.visible_tiles_ex / 2.0
|
|
41
|
+
self.ox = min(tilemap.width - self.visible_tiles_ex, max(0, self.ox))
|
|
42
|
+
if tilemap.width < self.visible_tiles_ex:
|
|
43
|
+
self.ox += (self.visible_tiles_ex - tilemap.width) / 2.0
|
|
44
|
+
self.ox -= self.visible_tiles_sx
|
|
45
|
+
|
|
46
|
+
# Calculate y offset
|
|
47
|
+
self.oy = target.py - self.visible_tiles_ey / 2.0
|
|
48
|
+
self.oy = min(tilemap.height - self.visible_tiles_ey, max(0, self.oy))
|
|
49
|
+
if tilemap.height < self.visible_tiles_ey:
|
|
50
|
+
self.oy += (self.visible_tiles_ey - tilemap.height) / 2.0
|
|
51
|
+
self.oy -= self.visible_tiles_sy
|