mima-engine 0.1.4__py3-none-any.whl → 0.2.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 -1
- mima/backend/pygame_assets.py +15 -9
- mima/backend/pygame_audio.py +5 -2
- mima/backend/pygame_backend.py +255 -57
- mima/backend/pygame_camera.py +63 -0
- mima/backend/pygame_events.py +331 -85
- mima/collision.py +182 -111
- mima/engine.py +155 -15
- mima/maps/tiled/tiled_map.py +3 -3
- mima/maps/tiled/tiled_tileset.py +1 -0
- mima/maps/tilemap.py +78 -15
- mima/maps/tileset.py +8 -2
- mima/maps/transition_map.py +6 -8
- mima/mode_engine.py +80 -0
- mima/objects/animated_sprite.py +23 -15
- mima/objects/attributes.py +3 -0
- mima/objects/creature.py +64 -25
- mima/objects/dynamic.py +30 -8
- mima/objects/effects/colorize_screen.py +22 -6
- mima/objects/effects/debug_box.py +124 -0
- mima/objects/effects/light.py +21 -30
- mima/objects/effects/show_sprite.py +39 -0
- mima/objects/effects/walking_on_grass.py +25 -7
- mima/objects/effects/walking_on_water.py +17 -6
- mima/objects/loader.py +24 -13
- mima/objects/projectile.py +21 -6
- mima/objects/sprite.py +7 -8
- mima/objects/world/color_gate.py +5 -2
- mima/objects/world/color_switch.py +12 -6
- mima/objects/world/container.py +17 -8
- mima/objects/world/floor_switch.py +8 -4
- mima/objects/world/gate.py +8 -5
- mima/objects/world/light_source.py +11 -9
- mima/objects/world/logic_gate.py +8 -7
- mima/objects/world/movable.py +72 -28
- mima/objects/world/oneway.py +14 -9
- mima/objects/world/pickup.py +10 -5
- mima/objects/world/switch.py +28 -25
- mima/objects/world/teleport.py +76 -55
- mima/scene_engine.py +19 -20
- mima/scripts/command.py +16 -2
- mima/scripts/commands/change_map.py +23 -4
- mima/scripts/commands/equip_weapon.py +23 -0
- mima/scripts/commands/give_item.py +5 -3
- mima/scripts/commands/move_map.py +9 -9
- mima/scripts/commands/parallel.py +16 -3
- mima/scripts/commands/present_item.py +7 -5
- mima/scripts/commands/screen_fade.py +30 -12
- mima/scripts/commands/serial.py +30 -7
- mima/scripts/commands/set_spawn_map.py +6 -3
- mima/scripts/commands/show_choices.py +16 -7
- mima/scripts/commands/show_dialog.py +110 -3
- mima/scripts/script_processor.py +41 -20
- mima/states/game_state.py +2 -0
- mima/states/memory.py +28 -0
- mima/states/quest.py +2 -3
- mima/types/keys.py +48 -0
- mima/types/mode.py +4 -10
- mima/types/player.py +9 -0
- mima/types/position.py +13 -0
- mima/types/tile_collision.py +11 -0
- mima/types/window.py +44 -0
- mima/usables/item.py +1 -0
- mima/util/colors.py +5 -0
- mima/util/constants.py +6 -0
- mima/util/functions.py +27 -0
- mima/util/input_defaults.py +109 -0
- mima/util/runtime_config.py +234 -30
- mima/util/trading_item.py +20 -0
- mima/view/camera.py +160 -19
- mima/view/mima_mode.py +612 -0
- mima/view/mima_scene.py +225 -0
- mima/view/mima_view.py +12 -0
- mima/view/mima_window.py +153 -0
- {mima_engine-0.1.4.dist-info → mima_engine-0.2.0.dist-info}/METADATA +4 -2
- mima_engine-0.2.0.dist-info/RECORD +128 -0
- {mima_engine-0.1.4.dist-info → mima_engine-0.2.0.dist-info}/WHEEL +1 -1
- mima/view/scene.py +0 -322
- mima_engine-0.1.4.dist-info/RECORD +0 -114
- {mima_engine-0.1.4.dist-info → mima_engine-0.2.0.dist-info}/top_level.txt +0 -0
mima/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.2.0"
|
mima/backend/pygame_assets.py
CHANGED
|
@@ -12,6 +12,7 @@ from ..maps.tiled.tiled_template import TiledTemplate
|
|
|
12
12
|
from ..maps.tiled.tiled_tileset import TiledTileset
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
|
+
from ..maps.tilemap import Tilemap
|
|
15
16
|
from ..util import RuntimeConfig
|
|
16
17
|
|
|
17
18
|
LOG = logging.getLogger(__name__)
|
|
@@ -111,9 +112,9 @@ class PygameAssets:
|
|
|
111
112
|
name = os.path.split(snd)[1].split(".")[0]
|
|
112
113
|
self._load_sound(name, snd)
|
|
113
114
|
|
|
114
|
-
for
|
|
115
|
-
name = os.path.split(
|
|
116
|
-
self._load_csv(name,
|
|
115
|
+
for csvf in self._assets_to_load.get("csv", []):
|
|
116
|
+
name = os.path.split(csvf)[1].split(".")[0]
|
|
117
|
+
self._load_csv(name, csvf)
|
|
117
118
|
|
|
118
119
|
def _load_csv(self, name, filename):
|
|
119
120
|
if not os.path.isfile(filename):
|
|
@@ -220,9 +221,9 @@ class PygameAssets:
|
|
|
220
221
|
return name
|
|
221
222
|
try:
|
|
222
223
|
self._maps[name] = TiledMap(name, filename)
|
|
223
|
-
except KeyError
|
|
224
|
-
|
|
225
|
-
raise
|
|
224
|
+
except KeyError:
|
|
225
|
+
LOG.exception(f"Failed to load map={name}")
|
|
226
|
+
raise
|
|
226
227
|
|
|
227
228
|
return name
|
|
228
229
|
|
|
@@ -282,19 +283,24 @@ class PygameAssets:
|
|
|
282
283
|
if name is None:
|
|
283
284
|
return None
|
|
284
285
|
else:
|
|
285
|
-
if self.rtc.flags
|
|
286
|
+
if self.rtc.flags.get("use_color", False):
|
|
286
287
|
name_color = f"{name}_color"
|
|
287
288
|
else:
|
|
288
289
|
name_color = name
|
|
289
290
|
return self._sprites.get(name_color, self._sprites[name])
|
|
290
291
|
|
|
292
|
+
def new_map(self, name, tilemap: Tilemap):
|
|
293
|
+
self._maps[name] = tilemap
|
|
294
|
+
|
|
291
295
|
def new_sprite(self, name, surface: pygame.Surface):
|
|
292
296
|
self._sprites[name] = surface
|
|
293
297
|
|
|
294
298
|
def get_tileset(self, name):
|
|
295
299
|
if name not in self._tilesets:
|
|
296
|
-
|
|
297
|
-
|
|
300
|
+
msg = f"Could not find tileset '{name}'."
|
|
301
|
+
raise ValueError(msg)
|
|
302
|
+
# LOG.warning("Could not find tileset %s.", name)
|
|
303
|
+
# return self._tilesets["simple_sheet"]
|
|
298
304
|
return self._tilesets[name]
|
|
299
305
|
|
|
300
306
|
def get_template(self, name):
|
mima/backend/pygame_audio.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
from typing import TYPE_CHECKING, List, Tuple
|
|
4
5
|
|
|
5
6
|
import pygame
|
|
@@ -7,6 +8,8 @@ import pygame
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from .pygame_assets import PygameAssets
|
|
9
10
|
|
|
11
|
+
LOG = logging.getLogger(__name__)
|
|
12
|
+
|
|
10
13
|
|
|
11
14
|
class PygameAudio:
|
|
12
15
|
def __init__(self, assets: PygameAssets):
|
|
@@ -45,8 +48,8 @@ class PygameAudio:
|
|
|
45
48
|
self._play_music(name)
|
|
46
49
|
self.current_track = name
|
|
47
50
|
self.is_playing = True
|
|
48
|
-
except Exception
|
|
49
|
-
|
|
51
|
+
except Exception:
|
|
52
|
+
LOG.exception(f"Could not load {name}.")
|
|
50
53
|
|
|
51
54
|
def _play_music(self, name: str, repeat: int = -1):
|
|
52
55
|
pygame.mixer.music.load(self.assets.get_music(name))
|
mima/backend/pygame_backend.py
CHANGED
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING, Dict, List, Optional
|
|
5
5
|
|
|
6
6
|
import pygame
|
|
7
7
|
|
|
8
8
|
from ..types.blend import Blend
|
|
9
9
|
from ..util.colors import BLACK, WHITE, Color
|
|
10
10
|
from ..util.constants import (
|
|
11
|
-
BIG_FONT_HEIGHT,
|
|
12
11
|
BIG_FONT_NAME,
|
|
13
|
-
BIG_FONT_WIDTH,
|
|
14
12
|
SMALL_FONT_HEIGHT,
|
|
15
13
|
SMALL_FONT_NAME,
|
|
16
14
|
SMALL_FONT_WIDTH,
|
|
17
15
|
)
|
|
18
16
|
from .pygame_assets import PygameAssets
|
|
19
17
|
from .pygame_audio import PygameAudio
|
|
18
|
+
from .pygame_camera import PygameCamera
|
|
20
19
|
from .pygame_events import SDL2_BACKGROUND_EVENTS, PygameUserInput
|
|
21
20
|
|
|
22
21
|
if TYPE_CHECKING:
|
|
23
22
|
from ..engine import MimaEngine
|
|
23
|
+
from ..types.keys import Key as K
|
|
24
|
+
from ..types.player import Player
|
|
24
25
|
from ..util import RuntimeConfig
|
|
25
26
|
|
|
26
27
|
LOG = logging.getLogger(__name__)
|
|
27
28
|
|
|
29
|
+
C_DISPLAY = "display"
|
|
30
|
+
|
|
28
31
|
|
|
29
32
|
class PygameBackend:
|
|
30
33
|
engine: MimaEngine
|
|
@@ -57,14 +60,22 @@ class PygameBackend:
|
|
|
57
60
|
self._filter_blend: Blend = Blend.DEFAULT
|
|
58
61
|
self._last_sprite_name: str = ""
|
|
59
62
|
self._last_sprite: pygame.Surface
|
|
63
|
+
self._cameras: Dict[str, PygameCamera] = {}
|
|
60
64
|
|
|
61
|
-
def init(
|
|
65
|
+
def init(
|
|
66
|
+
self,
|
|
67
|
+
keyboard_map: Optional[Dict[K, List[str]]] = None,
|
|
68
|
+
joystick_map: Optional[Dict[K, List[str]]] = None,
|
|
69
|
+
joy_to_player: Optional[Dict[int, Player]] = None,
|
|
70
|
+
):
|
|
62
71
|
LOG.info("Initializing pygame backend.")
|
|
63
72
|
pygame.mixer.pre_init(44100, -16, 2, 2048)
|
|
64
73
|
pygame.init()
|
|
65
74
|
|
|
66
75
|
self.clock = pygame.time.Clock()
|
|
67
|
-
self.user_input = PygameUserInput(
|
|
76
|
+
self.user_input = PygameUserInput(
|
|
77
|
+
keyboard_map, joystick_map, joy_to_player, self.platform
|
|
78
|
+
)
|
|
68
79
|
self.assets = PygameAssets(self.rtc, self.init_file)
|
|
69
80
|
self.audio = PygameAudio(self.assets)
|
|
70
81
|
|
|
@@ -100,11 +111,14 @@ class PygameBackend:
|
|
|
100
111
|
|
|
101
112
|
if pixel_size > 1:
|
|
102
113
|
self.manual_scale = True
|
|
103
|
-
self.
|
|
104
|
-
|
|
105
|
-
)
|
|
114
|
+
self.new_camera(C_DISPLAY, self.render_width, self.render_height)
|
|
115
|
+
# self.display = pygame.Surface(
|
|
116
|
+
# (self.render_width, self.render_height)
|
|
117
|
+
# )
|
|
106
118
|
else:
|
|
107
|
-
self.
|
|
119
|
+
self.new_camera(C_DISPLAY, self.display_width, self.display_height)
|
|
120
|
+
self._cameras[C_DISPLAY].view = self._screen
|
|
121
|
+
# self.display = self._screen
|
|
108
122
|
|
|
109
123
|
if self.platform == "PC":
|
|
110
124
|
if self.icon_path:
|
|
@@ -121,26 +135,44 @@ class PygameBackend:
|
|
|
121
135
|
self.user_input.width = self.render_width
|
|
122
136
|
self.user_input.height = self.render_height
|
|
123
137
|
self.assets.load()
|
|
124
|
-
# self.assets.load_items()
|
|
125
138
|
|
|
126
139
|
def clear(self, color: Color = Color(0, 0, 0)):
|
|
127
|
-
self.
|
|
128
|
-
|
|
129
|
-
|
|
140
|
+
for camera in self._cameras.values():
|
|
141
|
+
camera.clear(color)
|
|
142
|
+
|
|
143
|
+
if self.manual_scale:
|
|
144
|
+
self._screen.fill(color.getRGBA())
|
|
145
|
+
|
|
146
|
+
def add_camera(self, name, camera):
|
|
147
|
+
self._cameras[name] = camera
|
|
148
|
+
|
|
149
|
+
def remove_camera(self, name):
|
|
150
|
+
return self._cameras.pop(name)
|
|
151
|
+
|
|
152
|
+
def new_camera(self, name, width, height):
|
|
153
|
+
self._cameras[name] = PygameCamera(int(width), int(height))
|
|
154
|
+
|
|
155
|
+
def get_camera(self, name):
|
|
156
|
+
return self._cameras[name]
|
|
130
157
|
|
|
131
158
|
def configure_filter(
|
|
132
|
-
self,
|
|
159
|
+
self,
|
|
160
|
+
color: Color = BLACK,
|
|
161
|
+
blend_mode: Blend = Blend.DEFAULT,
|
|
162
|
+
camera: str = C_DISPLAY,
|
|
133
163
|
):
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
164
|
+
if camera == "all":
|
|
165
|
+
for cam in self._cameras.values():
|
|
166
|
+
cam.configure_filter(color, blend_mode)
|
|
167
|
+
else:
|
|
168
|
+
self._cameras[camera].configure_filter(color, blend_mode)
|
|
169
|
+
|
|
170
|
+
def apply_filter(self, camera: str = C_DISPLAY):
|
|
171
|
+
if camera == "all":
|
|
172
|
+
for cam in self._cameras.values():
|
|
173
|
+
cam.apply_filter()
|
|
174
|
+
else:
|
|
175
|
+
self._cameras[camera].apply_filter()
|
|
144
176
|
|
|
145
177
|
def draw_partial_sprite(
|
|
146
178
|
self,
|
|
@@ -151,14 +183,18 @@ class PygameBackend:
|
|
|
151
183
|
sy: float,
|
|
152
184
|
width: float,
|
|
153
185
|
height: float,
|
|
186
|
+
camera_name: str = C_DISPLAY,
|
|
154
187
|
blend_mode: Blend = Blend.DEFAULT,
|
|
155
188
|
draw_to_filter: bool = False,
|
|
189
|
+
draw_to_ui: bool = False,
|
|
156
190
|
):
|
|
157
191
|
if sprite_name:
|
|
158
192
|
if draw_to_filter:
|
|
159
|
-
display = self.
|
|
193
|
+
display = self._cameras[camera_name].filter
|
|
194
|
+
elif draw_to_ui:
|
|
195
|
+
display = self._cameras[camera_name].ui
|
|
160
196
|
else:
|
|
161
|
-
display = self.
|
|
197
|
+
display = self._cameras[camera_name].view
|
|
162
198
|
|
|
163
199
|
if sprite_name != self._last_sprite_name:
|
|
164
200
|
self._last_sprite_name = sprite_name
|
|
@@ -171,22 +207,52 @@ class PygameBackend:
|
|
|
171
207
|
sprite,
|
|
172
208
|
pygame.Vector2(px, py),
|
|
173
209
|
pygame.Rect(sx, sy, width, height),
|
|
174
|
-
special_flags=
|
|
175
|
-
|
|
176
|
-
|
|
210
|
+
special_flags=(
|
|
211
|
+
0
|
|
212
|
+
if blend_mode == Blend.DEFAULT
|
|
213
|
+
else blend_to_pygame_flag(blend_mode)
|
|
214
|
+
),
|
|
177
215
|
)
|
|
178
|
-
except Exception
|
|
179
|
-
|
|
180
|
-
f"Exception drawing sprite {sprite_name}: {px},
|
|
216
|
+
except Exception:
|
|
217
|
+
LOG.exception(
|
|
218
|
+
f"Exception drawing sprite {sprite_name}: {px}, "
|
|
219
|
+
f"{py}, {sx}, {sy}, {width}, {height}"
|
|
181
220
|
)
|
|
182
|
-
raise
|
|
183
|
-
# else:
|
|
184
|
-
# print(f"Draw sprite {sprite_name} at {(px, py)}.")
|
|
221
|
+
raise
|
|
185
222
|
|
|
186
223
|
def draw_line(
|
|
187
|
-
self,
|
|
224
|
+
self,
|
|
225
|
+
sx: float,
|
|
226
|
+
sy: float,
|
|
227
|
+
ex: float,
|
|
228
|
+
ey: float,
|
|
229
|
+
color: Color,
|
|
230
|
+
camera_name: str = C_DISPLAY,
|
|
231
|
+
blend_mode: Blend = Blend.DEFAULT,
|
|
232
|
+
draw_to_filter: bool = False,
|
|
233
|
+
draw_to_ui: bool = False,
|
|
234
|
+
width: int = 1,
|
|
188
235
|
):
|
|
189
|
-
|
|
236
|
+
if draw_to_filter:
|
|
237
|
+
display = self._cameras[camera_name].filter
|
|
238
|
+
elif draw_to_ui:
|
|
239
|
+
display = self._cameras[camera_name].ui
|
|
240
|
+
else:
|
|
241
|
+
display = self._cameras[camera_name].view
|
|
242
|
+
if blend_mode == Blend.DEFAULT:
|
|
243
|
+
pygame.draw.line(
|
|
244
|
+
display, color.getRGBA(), (sx, sy), (ex, ey), width
|
|
245
|
+
)
|
|
246
|
+
else:
|
|
247
|
+
surf = pygame.Surface(
|
|
248
|
+
(ex, ey)
|
|
249
|
+
) # FIXME: lines into negative directions
|
|
250
|
+
surf.fill(BLACK)
|
|
251
|
+
pygame.draw.line(surf, color.getRGBA(), (0, 0), (ex, ey), width)
|
|
252
|
+
rect = surf.get_rect(topleft=(0, 0))
|
|
253
|
+
display.blit(
|
|
254
|
+
surf, rect, special_flags=blend_to_pygame_flag(blend_mode)
|
|
255
|
+
)
|
|
190
256
|
|
|
191
257
|
def fill_circle(
|
|
192
258
|
self,
|
|
@@ -194,13 +260,17 @@ class PygameBackend:
|
|
|
194
260
|
py: float,
|
|
195
261
|
radius: float,
|
|
196
262
|
color: Color,
|
|
263
|
+
camera_name: str = C_DISPLAY,
|
|
197
264
|
blend_mode: Blend = Blend.DEFAULT,
|
|
198
265
|
draw_to_filter: bool = False,
|
|
266
|
+
draw_to_ui: bool = False,
|
|
199
267
|
):
|
|
200
268
|
if draw_to_filter:
|
|
201
|
-
display = self.
|
|
269
|
+
display = self._cameras[camera_name].filter
|
|
270
|
+
elif draw_to_ui:
|
|
271
|
+
display = self._cameras[camera_name].ui
|
|
202
272
|
else:
|
|
203
|
-
display = self.
|
|
273
|
+
display = self._cameras[camera_name].view
|
|
204
274
|
|
|
205
275
|
if blend_mode == Blend.DEFAULT:
|
|
206
276
|
pygame.draw.circle(display, color.getRGBA(), (px, py), radius)
|
|
@@ -215,10 +285,32 @@ class PygameBackend:
|
|
|
215
285
|
special_flags=blend_to_pygame_flag(blend_mode),
|
|
216
286
|
)
|
|
217
287
|
|
|
218
|
-
def draw_circle(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
288
|
+
def draw_circle(
|
|
289
|
+
self,
|
|
290
|
+
px: float,
|
|
291
|
+
py: float,
|
|
292
|
+
radius: float,
|
|
293
|
+
color: Color,
|
|
294
|
+
camera_name: str = C_DISPLAY,
|
|
295
|
+
blend_mode: Blend = Blend.DEFAULT,
|
|
296
|
+
draw_to_filter: bool = False,
|
|
297
|
+
draw_to_ui: bool = False,
|
|
298
|
+
):
|
|
299
|
+
if draw_to_filter:
|
|
300
|
+
display = self._cameras[camera_name].filter
|
|
301
|
+
elif draw_to_ui:
|
|
302
|
+
display = self._cameras[camera_name].ui
|
|
303
|
+
else:
|
|
304
|
+
display = self._cameras[camera_name].view
|
|
305
|
+
|
|
306
|
+
if blend_mode == Blend.DEFAULT:
|
|
307
|
+
pygame.draw.circle(
|
|
308
|
+
display, color.getRGBA(), (px, py), radius, width=1
|
|
309
|
+
)
|
|
310
|
+
else:
|
|
311
|
+
raise NotImplementedError(
|
|
312
|
+
"Draw circle is not implemented with blendmode"
|
|
313
|
+
)
|
|
222
314
|
|
|
223
315
|
def fill_rect(
|
|
224
316
|
self,
|
|
@@ -227,13 +319,18 @@ class PygameBackend:
|
|
|
227
319
|
width: float,
|
|
228
320
|
height: float,
|
|
229
321
|
color: Color,
|
|
322
|
+
camera_name: str = C_DISPLAY,
|
|
323
|
+
blend_mode: Blend = Blend.DEFAULT,
|
|
230
324
|
draw_to_filter: bool = False,
|
|
325
|
+
draw_to_ui: bool = False,
|
|
231
326
|
):
|
|
232
327
|
r, g, b, a = color.getRGBA()
|
|
233
328
|
if draw_to_filter:
|
|
234
|
-
display = self.
|
|
329
|
+
display = self._cameras[camera_name].filter
|
|
330
|
+
elif draw_to_ui:
|
|
331
|
+
display = self._cameras[camera_name].ui
|
|
235
332
|
else:
|
|
236
|
-
display = self.
|
|
333
|
+
display = self._cameras[camera_name].view
|
|
237
334
|
|
|
238
335
|
if a < 255:
|
|
239
336
|
surf = pygame.Surface((width, height))
|
|
@@ -254,40 +351,75 @@ class PygameBackend:
|
|
|
254
351
|
width: float,
|
|
255
352
|
height: float,
|
|
256
353
|
color: Color,
|
|
354
|
+
camera_name: str = C_DISPLAY,
|
|
257
355
|
line_width: int = 1,
|
|
356
|
+
blend_mode: Blend = Blend.DEFAULT,
|
|
357
|
+
draw_to_filter: bool = False,
|
|
358
|
+
draw_to_ui: bool = False,
|
|
258
359
|
):
|
|
360
|
+
|
|
361
|
+
if draw_to_filter:
|
|
362
|
+
display = self._cameras[camera_name].filter
|
|
363
|
+
elif draw_to_ui:
|
|
364
|
+
display = self._cameras[camera_name].ui
|
|
365
|
+
else:
|
|
366
|
+
display = self._cameras[camera_name].view
|
|
259
367
|
line_width = max(1, line_width)
|
|
260
368
|
pygame.draw.rect(
|
|
261
|
-
|
|
369
|
+
display,
|
|
262
370
|
color.getRGB(),
|
|
263
371
|
pygame.Rect(px, py, width, height),
|
|
264
372
|
width=line_width,
|
|
265
373
|
)
|
|
266
374
|
|
|
267
375
|
def draw_big_text(
|
|
268
|
-
self,
|
|
376
|
+
self,
|
|
377
|
+
text: str,
|
|
378
|
+
px: float,
|
|
379
|
+
py: float,
|
|
380
|
+
color: Color = WHITE,
|
|
381
|
+
camera_name: str = C_DISPLAY,
|
|
382
|
+
blend_mode: Blend = Blend.DEFAULT,
|
|
383
|
+
draw_to_filter: bool = False,
|
|
384
|
+
draw_to_ui: bool = False,
|
|
269
385
|
):
|
|
270
386
|
self.draw_text(
|
|
271
387
|
text,
|
|
272
388
|
px,
|
|
273
389
|
py,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
390
|
+
self.rtc.big_font_name,
|
|
391
|
+
self.rtc.big_font_width,
|
|
392
|
+
self.rtc.big_font_height,
|
|
277
393
|
color,
|
|
394
|
+
camera_name,
|
|
395
|
+
blend_mode,
|
|
396
|
+
draw_to_filter,
|
|
397
|
+
draw_to_ui,
|
|
278
398
|
)
|
|
279
399
|
|
|
280
400
|
def draw_small_text(
|
|
281
|
-
self,
|
|
401
|
+
self,
|
|
402
|
+
text: str,
|
|
403
|
+
px: float,
|
|
404
|
+
py: float,
|
|
405
|
+
color: Color = WHITE,
|
|
406
|
+
camera_name: str = C_DISPLAY,
|
|
407
|
+
blend_mode: Blend = Blend.DEFAULT,
|
|
408
|
+
draw_to_filter: bool = False,
|
|
409
|
+
draw_to_ui: bool = False,
|
|
282
410
|
):
|
|
283
411
|
self.draw_text(
|
|
284
412
|
text,
|
|
285
413
|
px,
|
|
286
414
|
py,
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
415
|
+
self.rtc.small_font_name,
|
|
416
|
+
self.rtc.small_font_width,
|
|
417
|
+
self.rtc.small_font_height,
|
|
290
418
|
color,
|
|
419
|
+
camera_name,
|
|
420
|
+
blend_mode,
|
|
421
|
+
draw_to_filter,
|
|
422
|
+
draw_to_ui,
|
|
291
423
|
)
|
|
292
424
|
|
|
293
425
|
def draw_text(
|
|
@@ -299,6 +431,10 @@ class PygameBackend:
|
|
|
299
431
|
font_width: int,
|
|
300
432
|
font_height: int,
|
|
301
433
|
color: Color = WHITE,
|
|
434
|
+
camera_name: str = C_DISPLAY,
|
|
435
|
+
blend_mode: Blend = Blend.DEFAULT,
|
|
436
|
+
draw_to_filter: bool = False,
|
|
437
|
+
draw_to_ui: bool = False,
|
|
302
438
|
):
|
|
303
439
|
if color != WHITE:
|
|
304
440
|
old_sprite = self.assets.get_sprite(font_name)
|
|
@@ -321,12 +457,21 @@ class PygameBackend:
|
|
|
321
457
|
sy,
|
|
322
458
|
font_width,
|
|
323
459
|
font_height,
|
|
460
|
+
camera_name,
|
|
461
|
+
blend_mode,
|
|
462
|
+
draw_to_filter,
|
|
463
|
+
draw_to_ui,
|
|
324
464
|
)
|
|
325
465
|
idx += 1
|
|
326
466
|
|
|
327
467
|
def draw_pixel(self, px: float, py: float, color: Color):
|
|
328
468
|
self.display.set_at((int(px), int(py)), color.getRGB())
|
|
329
469
|
|
|
470
|
+
def draw_camera(self, name, px, py, scale):
|
|
471
|
+
self.display.blit(
|
|
472
|
+
pygame.transform.scale_by(self._cameras[name], scale), (px, py)
|
|
473
|
+
)
|
|
474
|
+
|
|
330
475
|
def set_caption(self, text: str):
|
|
331
476
|
pygame.display.set_caption(text)
|
|
332
477
|
|
|
@@ -350,13 +495,66 @@ class PygameBackend:
|
|
|
350
495
|
|
|
351
496
|
self.user_input.process(event)
|
|
352
497
|
|
|
353
|
-
def update_display(self):
|
|
354
|
-
|
|
498
|
+
def update_display(self, *cameras):
|
|
499
|
+
scale = self.display_width / self.render_width
|
|
500
|
+
for cam_name in cameras:
|
|
501
|
+
cam = self._cameras[cam_name]
|
|
502
|
+
# target_width = int(
|
|
503
|
+
# self._screen.get_width()
|
|
504
|
+
# + cam.render_width / self._screen.get_width()
|
|
505
|
+
# )
|
|
506
|
+
# target_height = int(
|
|
507
|
+
# self._screen.get_height()
|
|
508
|
+
# + cam.render_height / self._screen.get_height()
|
|
509
|
+
# )
|
|
510
|
+
# self._screen.blit(
|
|
511
|
+
# pygame.transform.scale_by(cam.view, scale),
|
|
512
|
+
# (cam.px * scale, cam.py * scale),
|
|
513
|
+
# )
|
|
514
|
+
self._screen.blit(
|
|
515
|
+
pygame.transform.scale(
|
|
516
|
+
cam.view,
|
|
517
|
+
(cam.render_width * scale, cam.render_height * scale),
|
|
518
|
+
),
|
|
519
|
+
(cam.px * scale, cam.py * scale),
|
|
520
|
+
)
|
|
521
|
+
for cam_name in cameras:
|
|
522
|
+
cam = self._cameras[cam_name]
|
|
523
|
+
self._screen.blit(
|
|
524
|
+
pygame.transform.scale(
|
|
525
|
+
cam.ui,
|
|
526
|
+
(cam.render_width * scale, cam.render_height * scale),
|
|
527
|
+
),
|
|
528
|
+
(cam.px * scale, cam.py * scale),
|
|
529
|
+
special_flags=(pygame.BLEND_ALPHA_SDL2),
|
|
530
|
+
)
|
|
531
|
+
# print(
|
|
532
|
+
# cam_name,
|
|
533
|
+
# (cam.px, cam.py),
|
|
534
|
+
# cam.view.get_size(),
|
|
535
|
+
# scale,
|
|
536
|
+
# # (target_width, target_height),
|
|
537
|
+
# # cam.camera_scale,
|
|
538
|
+
# # (
|
|
539
|
+
# # cam.view.get_width() * cam.camera_scale,
|
|
540
|
+
# # cam.view.get_height() * cam.camera_scale,
|
|
541
|
+
# # ),
|
|
542
|
+
# )
|
|
543
|
+
if not cameras and self.manual_scale:
|
|
544
|
+
self._screen.blit(
|
|
545
|
+
pygame.transform.scale(
|
|
546
|
+
self._cameras[C_DISPLAY].view,
|
|
547
|
+
(self.display_width, self.display_height),
|
|
548
|
+
),
|
|
549
|
+
(0, 0),
|
|
550
|
+
)
|
|
355
551
|
self._screen.blit(
|
|
356
552
|
pygame.transform.scale(
|
|
357
|
-
self.
|
|
553
|
+
self._cameras[C_DISPLAY].ui,
|
|
554
|
+
(self.display_width, self.display_height),
|
|
358
555
|
),
|
|
359
556
|
(0, 0),
|
|
557
|
+
special_flags=(pygame.BLEND_ALPHA_SDL2),
|
|
360
558
|
)
|
|
361
559
|
|
|
362
560
|
pygame.display.flip()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import pygame
|
|
4
|
+
|
|
5
|
+
from ..types.blend import Blend
|
|
6
|
+
from ..util.colors import BLACK, WHITE, Color, ALPHA
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PygameCamera:
|
|
10
|
+
def __init__(self, width: int, height: int):
|
|
11
|
+
self.px: int = 0
|
|
12
|
+
self.py: int = 0
|
|
13
|
+
self.render_width = width
|
|
14
|
+
self.render_height = height
|
|
15
|
+
self.view: pygame.Surface = pygame.Surface((width, height))
|
|
16
|
+
self.filter: pygame.Surface = pygame.Surface((width, height))
|
|
17
|
+
self.ui: pygame.Surface = pygame.Surface((width, height))
|
|
18
|
+
self._filter_color: Color = BLACK
|
|
19
|
+
self._filter_blend: Blend = Blend.DEFAULT
|
|
20
|
+
self._ui_color: Color = ALPHA
|
|
21
|
+
self.camera_scale: float = 1.0
|
|
22
|
+
|
|
23
|
+
def clear(self, color: Color = BLACK):
|
|
24
|
+
self.view.fill(color.getRGBA())
|
|
25
|
+
self.filter.fill(self._filter_color.getRGBA())
|
|
26
|
+
self.ui.fill(self._ui_color.getRGBA())
|
|
27
|
+
self.ui.set_colorkey(self._ui_color.getRGBA())
|
|
28
|
+
|
|
29
|
+
def configure_filter(
|
|
30
|
+
self, color: Color = BLACK, blend_mode: Blend = Blend.DEFAULT
|
|
31
|
+
):
|
|
32
|
+
self._filter_color = color
|
|
33
|
+
self._filter_blend = blend_mode
|
|
34
|
+
|
|
35
|
+
def apply_filter(self):
|
|
36
|
+
if self._filter_blend != Blend.DEFAULT:
|
|
37
|
+
self.view.blit(
|
|
38
|
+
self.filter,
|
|
39
|
+
pygame.Vector2(0, 0),
|
|
40
|
+
special_flags=blend_to_pygame_flag(self._filter_blend),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def change_zoom(self, width, height):
|
|
44
|
+
self.view = pygame.Surface((width, height))
|
|
45
|
+
self.filter = pygame.Surface((width, height))
|
|
46
|
+
|
|
47
|
+
def change_ui_zoom(self, width, height):
|
|
48
|
+
self.ui = pygame.Surface((width, height), flags=pygame.SRCALPHA)
|
|
49
|
+
self.ui.convert_alpha()
|
|
50
|
+
self.ui.set_colorkey(ALPHA.getRGBA())
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def blend_to_pygame_flag(blend_mode: Blend):
|
|
54
|
+
if blend_mode == Blend.DEFAULT:
|
|
55
|
+
return 0
|
|
56
|
+
elif blend_mode == Blend.ADD:
|
|
57
|
+
return pygame.BLEND_RGBA_ADD
|
|
58
|
+
elif blend_mode == Blend.SUB:
|
|
59
|
+
return pygame.BLEND_RGBA_SUB
|
|
60
|
+
elif blend_mode == Blend.MULT:
|
|
61
|
+
return pygame.BLEND_RGBA_MULT
|
|
62
|
+
else:
|
|
63
|
+
return 0
|