import 'package:flutter/material.dart'; import 'package:flutter_soloud/flutter_soloud.dart'; import 'package:wolf_3d_data_types/wolf_3d_data_types.dart'; import 'package:wolf_3d_synth/wolf_3d_synth.dart'; import 'package:wolf_dart/features/difficulty/difficulty.dart'; import 'package:wolf_dart/features/renderer/renderer.dart'; class DifficultyScreen extends StatefulWidget { const DifficultyScreen( this.data, { super.key, }); final WolfensteinData data; @override State createState() => _DifficultyScreenState(); } class _DifficultyScreenState extends State { AudioSource? _menuMusicSource; SoundHandle? _menuMusicHandle; bool get isShareware => widget.data.version == GameVersion.shareware; @override void initState() { super.initState(); _playMenuMusic(); } Future _playMenuMusic() async { final soloud = SoLoud.instance; if (!soloud.isInitialized) { return; } // 2. We only want to play music if the IMF data actually exists if (widget.data.music.isNotEmpty) { // Get the first track (usually the menu theme "Wondering About My Loved Ones") final music = widget.data.music.first; // Render the hardware instructions into PCM and wrap in a WAV header final pcmSamples = ImfRenderer.render(music); final wavBytes = ImfRenderer.createWavFile(pcmSamples); // 3. Load the bytes into SoLoud's memory // The 'menu_theme.wav' string is just a dummy name to tell SoLoud it's dealing with a WAV format _menuMusicSource = await soloud.loadMem('menu_theme.wav', wavBytes); // 4. Play the source and tell it to loop continuously! _menuMusicHandle = await soloud.play( _menuMusicSource!, looping: true, ); } } @override void dispose() { _cleanupAudio(); super.dispose(); } void _cleanupAudio() { final soloud = SoLoud.instance; // Stop the playback if (_menuMusicHandle != null) { soloud.stop(_menuMusicHandle!); } // Free the raw WAV data from C++ memory if (_menuMusicSource != null) { soloud.disposeSource(_menuMusicSource!); } } void _startGame(Difficulty difficulty, {bool showGallery = false}) { // Stop the music and clear memory right before we push the new route _cleanupAudio(); Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (_) => WolfRenderer( widget.data, difficulty: difficulty, isShareware: isShareware, showSpriteGallery: showGallery, ), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, floatingActionButton: FloatingActionButton( backgroundColor: Colors.red[900], onPressed: () => _startGame(Difficulty.bringEmOn, showGallery: true), child: const Icon(Icons.bug_report, color: Colors.white), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'HOW TOUGH ARE YOU?', style: TextStyle( color: Colors.red, fontSize: 32, fontWeight: FontWeight.bold, fontFamily: 'Courier', ), ), const SizedBox(height: 40), // --- Difficulty Buttons --- ListView.builder( shrinkWrap: true, itemCount: Difficulty.values.length, itemBuilder: (context, index) { final Difficulty difficulty = Difficulty.values[index]; return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.blueGrey[900], foregroundColor: Colors.white, minimumSize: const Size(300, 50), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4), ), ), onPressed: () => _startGame(difficulty), child: Text( difficulty.title, style: const TextStyle(fontSize: 18), ), ), ); }, ), ], ), ), ); } }