zombie-escape 1.14.4__py3-none-any.whl → 1.15.2__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.
- zombie_escape/__about__.py +1 -1
- zombie_escape/config.py +1 -0
- zombie_escape/entities.py +126 -199
- zombie_escape/entities_constants.py +11 -1
- zombie_escape/export_images.py +4 -4
- zombie_escape/font_utils.py +47 -0
- zombie_escape/gameplay/__init__.py +2 -1
- zombie_escape/gameplay/constants.py +4 -0
- zombie_escape/gameplay/interactions.py +83 -16
- zombie_escape/gameplay/layout.py +9 -15
- zombie_escape/gameplay/movement.py +45 -29
- zombie_escape/gameplay/spawn.py +15 -29
- zombie_escape/gameplay/state.py +62 -7
- zombie_escape/gameplay/survivors.py +61 -10
- zombie_escape/gameplay/utils.py +33 -0
- zombie_escape/level_blueprints.py +35 -31
- zombie_escape/level_constants.py +2 -2
- zombie_escape/locales/ui.en.json +19 -8
- zombie_escape/locales/ui.ja.json +19 -8
- zombie_escape/localization.py +7 -1
- zombie_escape/models.py +21 -6
- zombie_escape/render/__init__.py +2 -2
- zombie_escape/render/core.py +113 -81
- zombie_escape/render/hud.py +112 -40
- zombie_escape/render/overview.py +93 -2
- zombie_escape/render/shadows.py +2 -2
- zombie_escape/render_constants.py +12 -0
- zombie_escape/screens/__init__.py +6 -189
- zombie_escape/screens/game_over.py +8 -21
- zombie_escape/screens/gameplay.py +71 -26
- zombie_escape/screens/settings.py +114 -43
- zombie_escape/screens/title.py +128 -47
- zombie_escape/stage_constants.py +37 -8
- zombie_escape/windowing.py +508 -0
- zombie_escape/world_grid.py +7 -5
- zombie_escape/zombie_escape.py +26 -13
- {zombie_escape-1.14.4.dist-info → zombie_escape-1.15.2.dist-info}/METADATA +24 -24
- zombie_escape-1.15.2.dist-info/RECORD +54 -0
- zombie_escape-1.14.4.dist-info/RECORD +0 -53
- {zombie_escape-1.14.4.dist-info → zombie_escape-1.15.2.dist-info}/WHEEL +0 -0
- {zombie_escape-1.14.4.dist-info → zombie_escape-1.15.2.dist-info}/entry_points.txt +0 -0
- {zombie_escape-1.14.4.dist-info → zombie_escape-1.15.2.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -19,14 +19,8 @@ from ..input_utils import (
|
|
|
19
19
|
from ..localization import translate as tr
|
|
20
20
|
from ..models import GameData, Stage
|
|
21
21
|
from ..render import RenderAssets, _draw_status_bar, compute_floor_cells, draw_level_overview, show_message
|
|
22
|
-
from ..screens import
|
|
23
|
-
|
|
24
|
-
ScreenTransition,
|
|
25
|
-
nudge_window_scale,
|
|
26
|
-
present,
|
|
27
|
-
sync_window_size,
|
|
28
|
-
toggle_fullscreen,
|
|
29
|
-
)
|
|
22
|
+
from ..screens import ScreenID, ScreenTransition
|
|
23
|
+
from ..windowing import nudge_window_scale, present, sync_window_size, toggle_fullscreen
|
|
30
24
|
|
|
31
25
|
|
|
32
26
|
def game_over_screen(
|
|
@@ -87,6 +81,7 @@ def game_over_screen(
|
|
|
87
81
|
if survivor.alive() and survivor.is_buddy and not survivor.rescued
|
|
88
82
|
],
|
|
89
83
|
survivors=list(game_data.groups.survivor_group),
|
|
84
|
+
fall_spawn_cells=game_data.layout.fall_spawn_cells,
|
|
90
85
|
palette_key=state.ambient_palette_key,
|
|
91
86
|
)
|
|
92
87
|
|
|
@@ -113,7 +108,7 @@ def game_over_screen(
|
|
|
113
108
|
show_message(
|
|
114
109
|
screen,
|
|
115
110
|
tr("game_over.win"),
|
|
116
|
-
|
|
111
|
+
11,
|
|
117
112
|
GREEN,
|
|
118
113
|
(screen_width // 2, screen_height // 2 - 26),
|
|
119
114
|
)
|
|
@@ -121,18 +116,10 @@ def game_over_screen(
|
|
|
121
116
|
show_message(
|
|
122
117
|
screen,
|
|
123
118
|
tr("game_over.lose"),
|
|
124
|
-
|
|
119
|
+
11,
|
|
125
120
|
RED,
|
|
126
121
|
(screen_width // 2, screen_height // 2 - 26),
|
|
127
122
|
)
|
|
128
|
-
if state.game_over_message:
|
|
129
|
-
show_message(
|
|
130
|
-
screen,
|
|
131
|
-
state.game_over_message,
|
|
132
|
-
18,
|
|
133
|
-
LIGHT_GRAY,
|
|
134
|
-
(screen_width // 2, screen_height // 2 + 6),
|
|
135
|
-
)
|
|
136
123
|
summary_y = screen_height // 2 + 70
|
|
137
124
|
if stage and (stage.rescue_stage or stage.buddy_required_count > 0):
|
|
138
125
|
total_rescued = state.survivors_rescued + state.buddy_rescued
|
|
@@ -140,7 +127,7 @@ def game_over_screen(
|
|
|
140
127
|
show_message(
|
|
141
128
|
screen,
|
|
142
129
|
msg,
|
|
143
|
-
|
|
130
|
+
11,
|
|
144
131
|
LIGHT_GRAY,
|
|
145
132
|
(screen_width // 2, summary_y),
|
|
146
133
|
)
|
|
@@ -157,7 +144,7 @@ def game_over_screen(
|
|
|
157
144
|
show_message(
|
|
158
145
|
screen,
|
|
159
146
|
msg,
|
|
160
|
-
|
|
147
|
+
11,
|
|
161
148
|
LIGHT_GRAY,
|
|
162
149
|
(screen_width // 2, summary_y),
|
|
163
150
|
)
|
|
@@ -165,7 +152,7 @@ def game_over_screen(
|
|
|
165
152
|
show_message(
|
|
166
153
|
screen,
|
|
167
154
|
tr("game_over.prompt"),
|
|
168
|
-
|
|
155
|
+
11,
|
|
169
156
|
WHITE,
|
|
170
157
|
(screen_width // 2, screen_height // 2 + 24),
|
|
171
158
|
)
|
|
@@ -5,7 +5,8 @@ from typing import TYPE_CHECKING, Any
|
|
|
5
5
|
import pygame
|
|
6
6
|
from pygame import surface, time
|
|
7
7
|
|
|
8
|
-
from ..colors import RED, YELLOW
|
|
8
|
+
from ..colors import LIGHT_GRAY, RED, WHITE, YELLOW
|
|
9
|
+
from ..font_utils import load_font
|
|
9
10
|
from ..gameplay_constants import (
|
|
10
11
|
CAR_HINT_DELAY_MS_DEFAULT,
|
|
11
12
|
SURVIVAL_TIME_ACCEL_SUBSTEPS,
|
|
@@ -20,6 +21,7 @@ from ..gameplay import (
|
|
|
20
21
|
initialize_game_state,
|
|
21
22
|
maintain_waiting_car_supply,
|
|
22
23
|
nearest_waiting_car,
|
|
24
|
+
schedule_timed_message,
|
|
23
25
|
place_flashlights,
|
|
24
26
|
place_fuel_can,
|
|
25
27
|
place_shoes,
|
|
@@ -32,6 +34,8 @@ from ..gameplay import (
|
|
|
32
34
|
update_footprints,
|
|
33
35
|
update_endurance_timer,
|
|
34
36
|
)
|
|
37
|
+
from ..gameplay.state import frames_to_ms, ms_to_frames
|
|
38
|
+
from ..gameplay.constants import INTRO_MESSAGE_DISPLAY_FRAMES
|
|
35
39
|
from ..input_utils import (
|
|
36
40
|
CONTROLLER_BUTTON_DOWN,
|
|
37
41
|
CONTROLLER_DEVICE_ADDED,
|
|
@@ -45,19 +49,14 @@ from ..input_utils import (
|
|
|
45
49
|
)
|
|
46
50
|
from ..gameplay.spawn import _alive_waiting_cars
|
|
47
51
|
from ..world_grid import build_wall_index
|
|
48
|
-
from ..localization import translate as tr
|
|
52
|
+
from ..localization import get_font_settings, translate as tr
|
|
49
53
|
from ..models import Stage
|
|
50
|
-
from ..render import draw, draw_debug_overview, draw_pause_overlay, prewarm_fog_overlays,
|
|
54
|
+
from ..render import draw, draw_debug_overview, draw_pause_overlay, prewarm_fog_overlays, show_message_wrapped
|
|
55
|
+
from ..render_constants import GAMEPLAY_FONT_SIZE, TIMED_MESSAGE_LEFT_X, TIMED_MESSAGE_TOP_Y
|
|
51
56
|
from ..rng import generate_seed, seed_rng
|
|
52
57
|
from ..progress import record_stage_clear
|
|
53
|
-
from ..screens import
|
|
54
|
-
|
|
55
|
-
ScreenTransition,
|
|
56
|
-
nudge_window_scale,
|
|
57
|
-
present,
|
|
58
|
-
sync_window_size,
|
|
59
|
-
toggle_fullscreen,
|
|
60
|
-
)
|
|
58
|
+
from ..screens import ScreenID, ScreenTransition
|
|
59
|
+
from ..windowing import nudge_window_scale, present, sync_window_size, toggle_fullscreen
|
|
61
60
|
|
|
62
61
|
if TYPE_CHECKING:
|
|
63
62
|
from ..render import RenderAssets
|
|
@@ -93,9 +92,32 @@ def gameplay_screen(
|
|
|
93
92
|
_set_mouse_hidden(False)
|
|
94
93
|
return transition
|
|
95
94
|
|
|
95
|
+
def _show_loading_still() -> None:
|
|
96
|
+
screen.fill((0, 0, 0))
|
|
97
|
+
if stage.intro_key:
|
|
98
|
+
intro_text = tr(stage.intro_key)
|
|
99
|
+
font_settings = get_font_settings()
|
|
100
|
+
font_size = font_settings.scaled_size(GAMEPLAY_FONT_SIZE * 2)
|
|
101
|
+
font = load_font(font_settings.resource, font_size)
|
|
102
|
+
line_height = int(round(font.get_linesize() * font_settings.line_height_scale))
|
|
103
|
+
x = TIMED_MESSAGE_LEFT_X
|
|
104
|
+
y = TIMED_MESSAGE_TOP_Y
|
|
105
|
+
for line in intro_text.splitlines():
|
|
106
|
+
if not line:
|
|
107
|
+
y += line_height
|
|
108
|
+
continue
|
|
109
|
+
surface = font.render(line, False, WHITE)
|
|
110
|
+
screen.blit(surface, (x, y))
|
|
111
|
+
y += line_height
|
|
112
|
+
present(screen)
|
|
113
|
+
pygame.event.pump()
|
|
114
|
+
|
|
96
115
|
seed_value = seed if seed is not None else generate_seed()
|
|
97
116
|
applied_seed = seed_rng(seed_value)
|
|
98
117
|
|
|
118
|
+
loading_started_ms = pygame.time.get_ticks()
|
|
119
|
+
_show_loading_still()
|
|
120
|
+
|
|
99
121
|
game_data = initialize_game_state(config, stage)
|
|
100
122
|
game_data.state.seed = applied_seed
|
|
101
123
|
game_data.state.debug_mode = debug_mode
|
|
@@ -113,6 +135,18 @@ def gameplay_screen(
|
|
|
113
135
|
render_assets,
|
|
114
136
|
stage=stage,
|
|
115
137
|
)
|
|
138
|
+
if stage.intro_key and game_data.state.timed_message:
|
|
139
|
+
loading_elapsed_ms = max(0, pygame.time.get_ticks() - loading_started_ms)
|
|
140
|
+
remaining_ms = max(0, frames_to_ms(INTRO_MESSAGE_DISPLAY_FRAMES) - loading_elapsed_ms)
|
|
141
|
+
schedule_timed_message(
|
|
142
|
+
game_data.state,
|
|
143
|
+
tr(stage.intro_key),
|
|
144
|
+
duration_frames=max(0, ms_to_frames(remaining_ms)),
|
|
145
|
+
clear_on_input=True,
|
|
146
|
+
color=LIGHT_GRAY,
|
|
147
|
+
align="left",
|
|
148
|
+
now_ms=game_data.state.elapsed_play_ms,
|
|
149
|
+
)
|
|
116
150
|
paused_manual = False
|
|
117
151
|
paused_focus = False
|
|
118
152
|
ignore_focus_loss_until = 0
|
|
@@ -154,6 +188,8 @@ def gameplay_screen(
|
|
|
154
188
|
cell_size = game_data.cell_size
|
|
155
189
|
if stage.requires_fuel:
|
|
156
190
|
fuel_spawn_count = stage.fuel_spawn_count
|
|
191
|
+
if stage.endurance_stage:
|
|
192
|
+
fuel_spawn_count = 0
|
|
157
193
|
fuel_can = place_fuel_can(
|
|
158
194
|
layout_data["fuel_cells"] or layout_data["walkable_cells"],
|
|
159
195
|
cell_size,
|
|
@@ -214,14 +250,6 @@ def gameplay_screen(
|
|
|
214
250
|
hint_color=None,
|
|
215
251
|
fps=current_fps,
|
|
216
252
|
)
|
|
217
|
-
if game_data.state.game_over_message:
|
|
218
|
-
show_message(
|
|
219
|
-
screen,
|
|
220
|
-
game_data.state.game_over_message,
|
|
221
|
-
18,
|
|
222
|
-
RED,
|
|
223
|
-
(screen_width // 2, screen_height // 2 - 24),
|
|
224
|
-
)
|
|
225
253
|
present(screen)
|
|
226
254
|
continue
|
|
227
255
|
return _finalize(
|
|
@@ -315,13 +343,24 @@ def gameplay_screen(
|
|
|
315
343
|
|
|
316
344
|
paused = paused_manual or paused_focus
|
|
317
345
|
if paused:
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
346
|
+
if debug_overview:
|
|
347
|
+
draw_debug_overview(
|
|
348
|
+
render_assets,
|
|
349
|
+
screen,
|
|
350
|
+
overview_surface,
|
|
351
|
+
game_data,
|
|
352
|
+
config,
|
|
353
|
+
screen_width=screen_width,
|
|
354
|
+
screen_height=screen_height,
|
|
355
|
+
)
|
|
356
|
+
else:
|
|
357
|
+
draw(
|
|
358
|
+
render_assets,
|
|
359
|
+
screen,
|
|
360
|
+
game_data,
|
|
361
|
+
config=config,
|
|
362
|
+
fps=current_fps,
|
|
363
|
+
)
|
|
325
364
|
if show_pause_overlay:
|
|
326
365
|
draw_pause_overlay(screen)
|
|
327
366
|
present(screen)
|
|
@@ -347,6 +386,12 @@ def gameplay_screen(
|
|
|
347
386
|
shoes_count=game_data.state.shoes_count,
|
|
348
387
|
pad_input=pad_vector,
|
|
349
388
|
)
|
|
389
|
+
if (
|
|
390
|
+
game_data.state.timed_message
|
|
391
|
+
and game_data.state.timed_message.clear_on_input
|
|
392
|
+
and (player_dx or player_dy or car_dx or car_dy)
|
|
393
|
+
):
|
|
394
|
+
game_data.state.timed_message = None
|
|
350
395
|
update_entities(
|
|
351
396
|
game_data,
|
|
352
397
|
player_dx,
|
|
@@ -9,7 +9,7 @@ from pygame import surface, time
|
|
|
9
9
|
|
|
10
10
|
from ..colors import BLACK, GREEN, LIGHT_GRAY, WHITE
|
|
11
11
|
from ..config import DEFAULT_CONFIG, save_config
|
|
12
|
-
from ..font_utils import load_font
|
|
12
|
+
from ..font_utils import blit_text_scaled, load_font, render_text_scaled
|
|
13
13
|
from ..input_utils import (
|
|
14
14
|
CONTROLLER_BUTTON_DOWN,
|
|
15
15
|
CONTROLLER_BUTTON_DPAD_DOWN,
|
|
@@ -36,13 +36,18 @@ from ..localization import (
|
|
|
36
36
|
from ..render import show_message, wrap_text
|
|
37
37
|
from ..progress import user_progress_path
|
|
38
38
|
from ..screens import (
|
|
39
|
-
|
|
39
|
+
TITLE_FONT_SCALE,
|
|
40
|
+
TITLE_HEADER_Y,
|
|
41
|
+
TITLE_SECTION_TOP,
|
|
42
|
+
)
|
|
43
|
+
from ..windowing import (
|
|
44
|
+
adjust_menu_logical_size,
|
|
45
|
+
nudge_menu_window_scale,
|
|
40
46
|
present,
|
|
41
47
|
sync_window_size,
|
|
42
48
|
toggle_fullscreen,
|
|
43
49
|
)
|
|
44
50
|
|
|
45
|
-
|
|
46
51
|
def settings_screen(
|
|
47
52
|
screen: surface.Surface,
|
|
48
53
|
clock: time.Clock,
|
|
@@ -54,7 +59,10 @@ def settings_screen(
|
|
|
54
59
|
) -> dict[str, Any]:
|
|
55
60
|
"""Settings menu shown from the title screen."""
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
settings_font_scale = TITLE_FONT_SCALE
|
|
63
|
+
screen_width, screen_height = screen.get_size()
|
|
64
|
+
if screen_width <= 0 or screen_height <= 0:
|
|
65
|
+
screen_width, screen_height = screen_size
|
|
58
66
|
working = copy.deepcopy(config)
|
|
59
67
|
set_language(working.get("language"))
|
|
60
68
|
selected = 0
|
|
@@ -170,6 +178,18 @@ def settings_screen(
|
|
|
170
178
|
},
|
|
171
179
|
],
|
|
172
180
|
},
|
|
181
|
+
{
|
|
182
|
+
"label": tr("settings.sections.visual"),
|
|
183
|
+
"rows": [
|
|
184
|
+
{
|
|
185
|
+
"label": tr("settings.rows.shadows"),
|
|
186
|
+
"path": ("visual", "shadows", "enabled"),
|
|
187
|
+
"easy_value": True,
|
|
188
|
+
"left_label": tr("common.on"),
|
|
189
|
+
"right_label": tr("common.off"),
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
},
|
|
173
193
|
]
|
|
174
194
|
|
|
175
195
|
def rebuild_rows() -> tuple[list[dict], list[dict], list[str]]:
|
|
@@ -196,6 +216,7 @@ def settings_screen(
|
|
|
196
216
|
return config
|
|
197
217
|
if event.type in (pygame.WINDOWSIZECHANGED, pygame.VIDEORESIZE):
|
|
198
218
|
sync_window_size(event)
|
|
219
|
+
adjust_menu_logical_size()
|
|
199
220
|
continue
|
|
200
221
|
if event.type == pygame.JOYDEVICEADDED or (
|
|
201
222
|
CONTROLLER_DEVICE_ADDED is not None and event.type == CONTROLLER_DEVICE_ADDED
|
|
@@ -215,13 +236,14 @@ def settings_screen(
|
|
|
215
236
|
return _exit_settings()
|
|
216
237
|
if event.type == pygame.KEYDOWN:
|
|
217
238
|
if event.key == pygame.K_LEFTBRACKET:
|
|
218
|
-
|
|
239
|
+
nudge_menu_window_scale(0.5)
|
|
219
240
|
continue
|
|
220
241
|
if event.key == pygame.K_RIGHTBRACKET:
|
|
221
|
-
|
|
242
|
+
nudge_menu_window_scale(2.0)
|
|
222
243
|
continue
|
|
223
244
|
if event.key == pygame.K_f:
|
|
224
245
|
toggle_fullscreen()
|
|
246
|
+
adjust_menu_logical_size()
|
|
225
247
|
continue
|
|
226
248
|
if event.key in (pygame.K_ESCAPE, pygame.K_BACKSPACE):
|
|
227
249
|
return _exit_settings()
|
|
@@ -316,23 +338,25 @@ def settings_screen(
|
|
|
316
338
|
show_message(
|
|
317
339
|
screen,
|
|
318
340
|
tr("settings.title"),
|
|
319
|
-
26,
|
|
341
|
+
26 * settings_font_scale,
|
|
320
342
|
LIGHT_GRAY,
|
|
321
|
-
(screen_width // 2,
|
|
343
|
+
(screen_width // 2, TITLE_HEADER_Y),
|
|
344
|
+
scale_factor=settings_font_scale,
|
|
322
345
|
)
|
|
323
346
|
|
|
324
347
|
try:
|
|
325
348
|
font_settings = get_font_settings()
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
349
|
+
label_size = font_settings.scaled_size(11 * settings_font_scale)
|
|
350
|
+
value_size = font_settings.scaled_size(11 * settings_font_scale)
|
|
351
|
+
section_size = font_settings.scaled_size(12 * settings_font_scale)
|
|
352
|
+
label_font = load_font(font_settings.resource, label_size)
|
|
329
353
|
highlight_color = (70, 70, 70)
|
|
330
354
|
|
|
331
|
-
row_height =
|
|
332
|
-
start_y =
|
|
355
|
+
row_height = 16
|
|
356
|
+
start_y = TITLE_SECTION_TOP
|
|
333
357
|
|
|
334
|
-
segment_width = 30
|
|
335
|
-
segment_height = 18
|
|
358
|
+
segment_width = int(round(30 * 1.5 * 0.8))
|
|
359
|
+
segment_height = int(round(18 * 0.8))
|
|
336
360
|
segment_gap = 10
|
|
337
361
|
segment_total_width = segment_width * 2 + segment_gap
|
|
338
362
|
|
|
@@ -345,7 +369,13 @@ def settings_screen(
|
|
|
345
369
|
section_states: dict[str, dict] = {}
|
|
346
370
|
y_cursor = start_y
|
|
347
371
|
for section in sections:
|
|
348
|
-
header_surface =
|
|
372
|
+
header_surface = render_text_scaled(
|
|
373
|
+
font_settings.resource,
|
|
374
|
+
section_size,
|
|
375
|
+
section["label"],
|
|
376
|
+
LIGHT_GRAY,
|
|
377
|
+
scale_factor=settings_font_scale,
|
|
378
|
+
)
|
|
349
379
|
section_states[section["label"]] = {
|
|
350
380
|
"next_y": y_cursor + header_surface.get_height() + 4,
|
|
351
381
|
"header_surface": header_surface,
|
|
@@ -376,25 +406,34 @@ def settings_screen(
|
|
|
376
406
|
if idx == selected:
|
|
377
407
|
pygame.draw.rect(screen, highlight_color, highlight_rect)
|
|
378
408
|
|
|
379
|
-
|
|
380
|
-
|
|
409
|
+
label_height = label_font.get_linesize()
|
|
410
|
+
blit_text_scaled(
|
|
411
|
+
screen,
|
|
412
|
+
font_settings.resource,
|
|
413
|
+
label_size,
|
|
414
|
+
row["label"],
|
|
415
|
+
WHITE,
|
|
416
|
+
scale_factor=settings_font_scale,
|
|
381
417
|
topleft=(
|
|
382
418
|
col_x,
|
|
383
|
-
row_y_current + (row_height -
|
|
384
|
-
)
|
|
419
|
+
row_y_current + (row_height - label_height) // 2,
|
|
420
|
+
),
|
|
385
421
|
)
|
|
386
|
-
screen.blit(label_surface, label_rect)
|
|
387
422
|
if row_type == "choice":
|
|
388
423
|
display_fn = row.get("get_display")
|
|
389
424
|
display_text = display_fn(value) if display_fn and value is not None else str(value)
|
|
390
|
-
|
|
391
|
-
|
|
425
|
+
blit_text_scaled(
|
|
426
|
+
screen,
|
|
427
|
+
font_settings.resource,
|
|
428
|
+
value_size,
|
|
429
|
+
display_text,
|
|
430
|
+
WHITE,
|
|
431
|
+
scale_factor=settings_font_scale,
|
|
392
432
|
midright=(
|
|
393
433
|
col_x + row_width,
|
|
394
434
|
row_y_current + row_height // 2,
|
|
395
|
-
)
|
|
435
|
+
),
|
|
396
436
|
)
|
|
397
|
-
screen.blit(value_surface, value_rect)
|
|
398
437
|
elif row_type == "toggle":
|
|
399
438
|
slider_y = row_y_current + (row_height - segment_height) // 2 - 2
|
|
400
439
|
slider_x = col_x + row_width - segment_total_width
|
|
@@ -415,16 +454,23 @@ def settings_screen(
|
|
|
415
454
|
outline_color = GREEN if active else LIGHT_GRAY
|
|
416
455
|
pygame.draw.rect(screen, active_color, rect)
|
|
417
456
|
pygame.draw.rect(screen, outline_color, rect, width=2)
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
457
|
+
blit_text_scaled(
|
|
458
|
+
screen,
|
|
459
|
+
font_settings.resource,
|
|
460
|
+
value_size,
|
|
461
|
+
text,
|
|
462
|
+
WHITE,
|
|
463
|
+
scale_factor=settings_font_scale,
|
|
464
|
+
center=rect.center,
|
|
465
|
+
)
|
|
421
466
|
|
|
422
467
|
draw_segment(left_rect, row["left_label"], left_active)
|
|
423
468
|
draw_segment(right_rect, row["right_label"], right_active)
|
|
424
469
|
|
|
425
470
|
hint_start_y = start_y
|
|
426
471
|
hint_start_x = screen_width // 2 + 16
|
|
427
|
-
|
|
472
|
+
hint_size = font_settings.scaled_size(11 * settings_font_scale)
|
|
473
|
+
hint_font = load_font(font_settings.resource, hint_size)
|
|
428
474
|
hint_lines = [
|
|
429
475
|
tr("settings.hints.navigate"),
|
|
430
476
|
tr("settings.hints.adjust"),
|
|
@@ -432,33 +478,58 @@ def settings_screen(
|
|
|
432
478
|
tr("settings.hints.reset"),
|
|
433
479
|
tr("settings.hints.exit"),
|
|
434
480
|
]
|
|
435
|
-
hint_line_height = hint_font.get_linesize()
|
|
481
|
+
hint_line_height = int(round(hint_font.get_linesize() * font_settings.line_height_scale))
|
|
436
482
|
hint_max_width = screen_width - hint_start_x - 16
|
|
437
483
|
y_cursor = hint_start_y
|
|
438
484
|
for line in hint_lines:
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
485
|
+
blit_text_scaled(
|
|
486
|
+
screen,
|
|
487
|
+
font_settings.resource,
|
|
488
|
+
hint_size,
|
|
489
|
+
line,
|
|
490
|
+
WHITE,
|
|
491
|
+
scale_factor=settings_font_scale,
|
|
492
|
+
topleft=(hint_start_x, y_cursor),
|
|
493
|
+
)
|
|
442
494
|
y_cursor += hint_line_height
|
|
443
495
|
|
|
444
496
|
y_cursor += 26
|
|
445
497
|
window_hint = tr("menu.window_hint")
|
|
446
498
|
for line in wrap_text(window_hint, hint_font, hint_max_width):
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
499
|
+
blit_text_scaled(
|
|
500
|
+
screen,
|
|
501
|
+
font_settings.resource,
|
|
502
|
+
hint_size,
|
|
503
|
+
line,
|
|
504
|
+
WHITE,
|
|
505
|
+
scale_factor=settings_font_scale,
|
|
506
|
+
topleft=(hint_start_x, y_cursor),
|
|
507
|
+
)
|
|
450
508
|
y_cursor += hint_line_height
|
|
451
509
|
|
|
452
|
-
|
|
510
|
+
path_size = font_settings.scaled_size(11 * settings_font_scale)
|
|
511
|
+
path_font = load_font(font_settings.resource, path_size)
|
|
453
512
|
config_text = tr("settings.config_path", path=str(config_path))
|
|
454
513
|
progress_text = tr("settings.progress_path", path=str(user_progress_path()))
|
|
455
514
|
line_height = path_font.get_linesize()
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
515
|
+
blit_text_scaled(
|
|
516
|
+
screen,
|
|
517
|
+
font_settings.resource,
|
|
518
|
+
path_size,
|
|
519
|
+
config_text,
|
|
520
|
+
LIGHT_GRAY,
|
|
521
|
+
scale_factor=settings_font_scale,
|
|
522
|
+
midtop=(screen_width // 2, screen_height - 32 - line_height),
|
|
523
|
+
)
|
|
524
|
+
blit_text_scaled(
|
|
525
|
+
screen,
|
|
526
|
+
font_settings.resource,
|
|
527
|
+
path_size,
|
|
528
|
+
progress_text,
|
|
529
|
+
LIGHT_GRAY,
|
|
530
|
+
scale_factor=settings_font_scale,
|
|
531
|
+
midtop=(screen_width // 2, screen_height - 32),
|
|
532
|
+
)
|
|
462
533
|
except pygame.error as e:
|
|
463
534
|
print(f"Error rendering settings: {e}")
|
|
464
535
|
|