Title screen, pause menu, settings dialog and savegames

- title screen (continue/new/load/settings/help) and Esc pause menu
- settings: language & sound, camera, graphics, game, rebindable keys;
  stored in localStorage and in every savegame (always applied on load)
- savegames as JSON (.dcsave): download, load via file picker or drag & drop
- autosave to localStorage every 2 minutes and when the tab is hidden/closed
- configurable wall detail, light count, interface size, game speed, hints
- audio behind a cargo feature so native tests run (cargo test --no-default-features)
- savegame round-trip test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-02 23:08:33 +01:00
1 parent fbf6f223fc
commit fb7dab3683
17 files changed
+1742 -345

No files matched your search

+18 -4
View File
@@ -3,7 +3,25 @@
// Events without a registered sound stay silent.
use crate::game::{Sfx, SfxEvent, SFX_ALL};
#[cfg(feature = "audio")]
use macroquad::audio::{load_sound_from_bytes, play_sound, PlaySoundParams, Sound};
#[cfg(not(feature = "audio"))]
use stub::*;
// Silent stand-in when the "audio" feature is off (native tests)
#[cfg(not(feature = "audio"))]
mod stub {
#[derive(Clone)]
pub struct Sound;
pub struct PlaySoundParams {
pub looped: bool,
pub volume: f32,
}
pub async fn load_sound_from_bytes(_: &[u8]) -> Result<Sound, ()> {
Err(())
}
pub fn play_sound(_: &Sound, _: PlaySoundParams) {}
}
use macroquad::prelude::*;
pub struct SoundBank {
@@ -33,10 +51,6 @@ impl SoundBank {
// procedurally generated sounds will be registered here
pub async fn generate_all(&mut self) {}
pub fn change_volume(&mut self, d: f32) {
self.volume = (self.volume + d).clamp(0.0, 1.0);
}
// minimum gap between two identical sounds (avoids a wall of noise)
fn min_gap(sfx: Sfx) -> f64 {
match sfx {