Skip to content

v1.7.2 — Pause Menu, Title Screen, Accessibility, GPU Fix, Settings UX

Choose a tag to compare

@avcode-exe avcode-exe released this 30 Jul 10:28
· 4 commits to main since this release

v1.7.2 — Pause Menu, Title Screen, Accessibility, GPU Fix, Settings UX

🎉 New Features

Pause Menu — DOM-based modal overlay

Replaced the canvas-dim pause overlay with a full DOM modal with improved UX:

  • Three buttons: Resume, Restart (with confirmation dialog), and Save Game
  • Focus trap: Tab/Shift+Tab cycles within pause menu buttons only (prevents tabging to background elements like the quick access bar)
  • Backdrop click does NOT resume: Player must click Resume or press Space/ESC
  • Canvas aria-hidden: When the pause menu is open, the game canvas receives aria-hidden="true" so screen readers focus on the modal dialog; removed when closed
  • Prefers-reduced-motion: Respects OS-level reduced motion setting; disables all fade-in/fade-out animations when enabled

Title Screen — Canvas background with click-anywhere start

A polished first-impression title screen:

  • Animated gradient background with twinkling particles
  • "Tower Defense" title text with GPU-accelerated gradient caching (cached across frames)
  • Click anywhere on the canvas or press SPACE to start — no more hunting for a specific button
  • DOM overlay with New Game, Load Game, Settings, and About buttons
  • Load Game is automatically disabled when no save slots exist
  • Particle quality auto-throttles on the title screen (same _checkFrameBudget() mechanism as in-game)
  • Canvas onMouseDown() now handles TITLE state: any click starts the game

Quick Access Bar — Hidden during title screen

  • The bottom bar (Monsters, Controls, DEV, Settings, Notifications, About) is hidden during the title screen via a .bar-hidden CSS class (display: none !important)
  • Shown when the player starts the game (click anywhere, press SPACE, or load a save)
  • Hidden again when returning to the title screen

Settings Popup Improvements

  • Save/Cancel buttons fixed at bottom-right: Moved outside the tab content container so they remain in the same position regardless of which tab is active. The sidebar and tab content are now in a flex row, with actions below.
  • Simplified Audio Settings: Reduced to a single Master volume slider with live percentage display. Removed SFX, Ambient, and UI sliders and all mute checkboxes for a cleaner, less cluttered settings panel.
  • Dynamic popup width: Popups use width: max-content to resize to fit content rather than using fixed min-width/max-width constraints. Min-widths adjusted to smaller values (180–300px range).
  • Single-line content: Added white-space: nowrap to .game-panel so all popup content renders on single lines. Added overflow-x: auto to .bar-popup for horizontal scrolling when content exceeds viewport width.

🐛 Bug Fixes

  • Space key in TITLE state: Previously called togglePause() which silently did nothing (state was TITLE, not WAVE_ACTIVE). Now correctly calls startNewGame().
  • onMouseDown in TITLE state: Previously returned early for both DEFEAT and TITLE states, ignoring all clicks. Now starts the game on any click.
  • GPU StagingBuffer error: On Linux without a GPU device (/dev/dri) or display server (DISPLAY), GPU rasterization is now proactively disabled via app.commandLine.appendSwitch() before app.whenReady(), preventing cc/raster/one_copy_raster_buffer_provider.cc:282: Creation of StagingBuffer's SharedImage failed errors in headless/VM/container environments. Added switches: --disable-gpu, --disable-gpu-sandbox, --disable-software-rasterizer, --disable-gpu-rasterization, --disable-accelerated-video-decode.
  • Game loop stability: Reset _lastSaveWave in restart() so auto-save debounce doesn't skip waves after game reset. Clear _pendingAttack on ATTACKING→MOVING transitions to prevent stale attack queue entries. Guard against undefined m.leak in _stepMonsters. Restore _onProjectileImpact callback in restore(). Replace sparse Array(N) with Array(N).fill(null) for _monsterTileIndex.
  • Version utilities: isPrerelease regex updated to match all common pre-release formats (-beta, -alpha, -rc, -pre). parseVersion handles 4-segment versions.
  • Healer scan throttling: Healer _tryHealAllies now throttles O(n) target scans to every 0.2s (CONFIG.HEAL_SCAN_INTERVAL) instead of every frame.

🔒 Security

  • 0 vulnerabilities (down from 15 at v1.7.1; was 15 high/critical)
  • electron-updater updated to ^6.8.9 — fixes builder-util-runtime credential leak (GHSA-p2f4-r6v6-j797)
  • brace-expansion override to ^5.0.8 — fixes DoS via unbounded expansion (GHSA-mh99-v99m-4gvg)
  • Declared transitive dependencies (semver, builder-util-runtime, js-yaml) explicitly in package.json
  • Added engines.node >= 20 requirement

🧪 Testing

  • 1,938 tests across 50 files (up from 1,885 at v1.7.1; +53 new tests)
  • New file: tests/pauseMenu.test.js (13 tests) — pause menu buttons, title screen, settings sub-modal, quit-to-title
  • New tests in tests/main.test.js: 10 tests covering showPauseMenu aria-hidden, hidePauseMenu aria-hidden removal, pause menu button focusability, backdrop click non-resume, focus trap Tab/Shift+Tab cycling, title screen button aria-labels, title screen button clickability, title screen role=dialog and aria-modal, pause menu role=dialog and aria-modal
  • New tests in tests/game.test.js: _checkFrameBudget called in TITLE state, title screen gradient caching, particle pre-computation
  • Pause menu integration: _showPauseMenu/_hidePauseMenu window calls, ESC-when-PAUSED, gameRuntime pause/resume/defeat integration
  • Electron main tests: Added commandLine.appendSwitch mock, disableHardwareAcceleration mock
  • IPC channel parity test: All 16 preload.cjs channels handled in electron-main.js and vice versa
  • Known limitations consolidated to exactly 5 remaining (L1–L5)
  • Coverage: 50 test files, all passing, lint clean, format clean

📝 Documentation

  • CHANGELOG.md: Comprehensive entry with full history from v1.4.1 through v1.7.2 (252 lines)
  • README.md: Updated features list, controls table (click-anywhere added), UI panels section, settings panel description, audio settings subsection, test counts (1,938)
  • PLAN.md: Version updated to 1.7.2 (stable), definition of done items checked off
  • Inline code documentation added to:
    • src/main.js — pause menu architecture, focus trap, title screen, canvas aria-hidden
    • src/game.js — title screen rendering, particle throttling, click-anywhere, bar show/hide
    • src/particles.js — quality tiers, auto-throttle, hardware-aware pool sizing
    • src/gameRuntime.js — pause/resume/defeat state transitions

📦 Technical

  • Electron 42 with context isolation, --disable-gpu fallback for headless Linux
  • ES modules throughout src/ with clean module boundaries
  • Fixed-timestep simulation decoupled from frame rate via accumulator
  • Entity pooling for projectiles, popups, and tile-index arrays
  • Offscreen canvas caching for static grid/path layers
  • Dynamic particle system with 4 quality tiers (Low/Medium/High/Ultra) and auto-throttle
  • Background heartbeat keeps sim running when window is backgrounded
  • CI: GitHub Actions on ubuntu-latest, Node 20/22/24

📂 Files Changed

17 files modified (+340/-261 lines):

  • CHANGELOG.md — comprehensive v1.7.2 entry
  • README.md — updated features, controls, test counts, documentation
  • css/style.css — bar-hidden class, settings sidebar-row, settings-actions bottom-right, single-line, dynamic popup width
  • electron-main.js — GPU fallback with /dev/dri check, additional GPU switches, improved crash handler
  • index.html — bar-hidden default, settings-actions moved outside tab content, simplified audio settings, title screen prompt text
  • package.json — version 1.7.2
  • package-lock.json — version 1.7.2
  • src/game.js — title screen optimization, click-anywhere, bar show/hide, version string, inline docs
  • src/gamePersistence.js — CURRENT_VERSION → 1.7.2
  • src/gameRuntime.js — inline documentation for pause/resume/defeat
  • src/main.js — settings-actions placement, title screen, bar hide/show, inline docs
  • src/particles.js — inline documentation for quality tiers
  • tests/electronMain.test.js — commandLine mock
  • tests/helpers.js — version update
  • tests/main.test.js — version update
  • tests/persistence.test.js — version update
  • tests/preload.test.js — version update