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
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,8 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class Property:
6
+ name: str
7
+ dtype: str
8
+ value: str
@@ -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