diff --git a/game_template/lib/main.dart b/game_template/lib/main.dart index cce450def..a5bbdee38 100644 --- a/game_template/lib/main.dart +++ b/game_template/lib/main.dart @@ -256,6 +256,7 @@ class MyApp extends StatelessWidget { ), ), ), + routeInformationProvider: _router.routeInformationProvider, routeInformationParser: _router.routeInformationParser, routerDelegate: _router.routerDelegate, scaffoldMessengerKey: scaffoldMessengerKey, diff --git a/game_template/lib/src/audio/audio_controller.dart b/game_template/lib/src/audio/audio_controller.dart index 8cfd6cf3a..df8e52d17 100644 --- a/game_template/lib/src/audio/audio_controller.dart +++ b/game_template/lib/src/audio/audio_controller.dart @@ -5,7 +5,7 @@ import 'dart:collection'; import 'dart:math'; -import 'package:audioplayers/audioplayers.dart' hide Logger; +import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/widgets.dart'; import 'package:logging/logging.dart'; @@ -17,18 +17,10 @@ import 'sounds.dart'; class AudioController { static final _log = Logger('AudioController'); - late AudioCache _musicCache; - - late AudioCache _sfxCache; - final AudioPlayer _musicPlayer; /// This is a list of [AudioPlayer] instances which are rotated to play /// sound effects. - /// - /// Normally, we would just call [AudioCache.play] and let it procure its - /// own [AudioPlayer] every time. But this seems to lead to errors and - /// bad performance on iOS devices. final List _sfxPlayers; int _currentSfxPlayer = 0; @@ -49,26 +41,15 @@ class AudioController { /// of [_sfxPlayers] to learn why this is the case. /// /// Background music does not count into the [polyphony] limit. Music will - /// never be overridden by sound effects. + /// never be overridden by sound effects because that would be silly. AudioController({int polyphony = 2}) : assert(polyphony >= 1), _musicPlayer = AudioPlayer(playerId: 'musicPlayer'), _sfxPlayers = Iterable.generate( - polyphony, - (i) => AudioPlayer( - playerId: 'sfxPlayer#$i', - mode: PlayerMode.LOW_LATENCY)).toList(growable: false), + polyphony, (i) => AudioPlayer(playerId: 'sfxPlayer#$i')) + .toList(growable: false), _playlist = Queue.of(List.of(songs)..shuffle()) { - _musicCache = AudioCache( - fixedPlayer: _musicPlayer, - prefix: 'assets/music/', - ); - _sfxCache = AudioCache( - fixedPlayer: _sfxPlayers.first, - prefix: 'assets/sfx/', - ); - - _musicPlayer.onPlayerCompletion.listen(_changeSong); + _musicPlayer.onPlayerComplete.listen(_changeSong); } /// Enables the [AudioController] to listen to [AppLifecycleState] events, @@ -127,8 +108,10 @@ class AudioController { // This assumes there is only a limited number of sound effects in the game. // If there are hundreds of long sound effect files, it's better // to be more selective when preloading. - await _sfxCache - .loadAll(SfxType.values.expand(soundTypeToFilename).toList()); + await AudioCache.instance.loadAll(SfxType.values + .expand(soundTypeToFilename) + .map((path) => 'sfx/$path') + .toList()); } /// Plays a single sound effect, defined by [type]. @@ -153,9 +136,11 @@ class AudioController { final options = soundTypeToFilename(type); final filename = options[_random.nextInt(options.length)]; _log.info(() => '- Chosen filename: $filename'); - _sfxCache.play(filename, volume: soundTypeToVolume(type)); + + final currentPlayer = _sfxPlayers[_currentSfxPlayer]; + currentPlayer.play(AssetSource('sfx/$filename'), + volume: soundTypeToVolume(type)); _currentSfxPlayer = (_currentSfxPlayer + 1) % _sfxPlayers.length; - _sfxCache.fixedPlayer = _sfxPlayers[_currentSfxPlayer]; } void _changeSong(void _) { @@ -163,8 +148,7 @@ class AudioController { // Put the song that just finished playing to the end of the playlist. _playlist.addLast(_playlist.removeFirst()); // Play the next song. - _log.info(() => 'Playing ${_playlist.first} now.'); - _musicCache.play(_playlist.first.filename); + _playFirstSongInPlaylist(); } void _handleAppLifecycle() { @@ -208,41 +192,46 @@ class AudioController { } } + Future _playFirstSongInPlaylist() async { + _log.info(() => 'Playing ${_playlist.first} now.'); + await _musicPlayer.play(AssetSource('music/${_playlist.first.filename}')); + } + Future _resumeMusic() async { _log.info('Resuming music'); switch (_musicPlayer.state) { - case PlayerState.PAUSED: + case PlayerState.paused: _log.info('Calling _musicPlayer.resume()'); try { await _musicPlayer.resume(); } catch (e) { // Sometimes, resuming fails with an "Unexpected" error. _log.severe(e); - await _musicCache.play(_playlist.first.filename); + await _playFirstSongInPlaylist(); } break; - case PlayerState.STOPPED: + case PlayerState.stopped: _log.info("resumeMusic() called when music is stopped. " "This probably means we haven't yet started the music. " "For example, the game was started with sound off."); - await _musicCache.play(_playlist.first.filename); + await _playFirstSongInPlaylist(); break; - case PlayerState.PLAYING: + case PlayerState.playing: _log.warning('resumeMusic() called when music is playing. ' 'Nothing to do.'); break; - case PlayerState.COMPLETED: + case PlayerState.completed: _log.warning('resumeMusic() called when music is completed. ' "Music should never be 'completed' as it's either not playing " "or looping forever."); - await _musicCache.play(_playlist.first.filename); + await _playFirstSongInPlaylist(); break; } } void _soundsOnHandler() { for (final player in _sfxPlayers) { - if (player.state == PlayerState.PLAYING) { + if (player.state == PlayerState.playing) { player.stop(); } } @@ -250,11 +239,11 @@ class AudioController { void _startMusic() { _log.info('starting music'); - _musicCache.play(_playlist.first.filename); + _playFirstSongInPlaylist(); } void _stopAllSound() { - if (_musicPlayer.state == PlayerState.PLAYING) { + if (_musicPlayer.state == PlayerState.playing) { _musicPlayer.pause(); } for (final player in _sfxPlayers) { @@ -264,7 +253,7 @@ class AudioController { void _stopMusic() { _log.info('Stopping music'); - if (_musicPlayer.state == PlayerState.PLAYING) { + if (_musicPlayer.state == PlayerState.playing) { _musicPlayer.pause(); } } diff --git a/game_template/macos/Flutter/GeneratedPluginRegistrant.swift b/game_template/macos/Flutter/GeneratedPluginRegistrant.swift index 5032c602a..273d30bc9 100644 --- a/game_template/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/game_template/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,7 +5,7 @@ import FlutterMacOS import Foundation -import audioplayers +import audioplayers_darwin import firebase_core import firebase_crashlytics import games_services @@ -13,7 +13,7 @@ import path_provider_macos import shared_preferences_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - AudioplayersPlugin.register(with: registry.registrar(forPlugin: "AudioplayersPlugin")) + AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin")) GamesServicesPlugin.register(with: registry.registrar(forPlugin: "GamesServicesPlugin")) diff --git a/game_template/pubspec.yaml b/game_template/pubspec.yaml index bffee3008..096a96a1b 100644 --- a/game_template/pubspec.yaml +++ b/game_template/pubspec.yaml @@ -13,9 +13,9 @@ dependencies: flutter: sdk: flutter - audioplayers: ^0.20.1 + audioplayers: ^1.0.1 cupertino_icons: ^1.0.2 - go_router: ^3.0.1 + go_router: ^4.4.1 logging: ^1.0.2 provider: ^6.0.2 shared_preferences: ^2.0.13 @@ -26,14 +26,14 @@ dependencies: firebase_core: ^1.15.0 # Needed for Crashlytics below firebase_crashlytics: ^2.8.1 # Error reporting games_services: ^3.0.0 # Achievements and leaderboards - google_mobile_ads: ^1.1.0 # Ads + google_mobile_ads: ^2.0.1 # Ads in_app_purchase: ^3.0.1 # In-app purchases dev_dependencies: flutter_test: sdk: flutter - flutter_launcher_icons: ^0.9.2 + flutter_launcher_icons: ^0.10.0 flutter_lints: ^2.0.1 test: ^1.19.0 diff --git a/game_template/windows/flutter/generated_plugin_registrant.cc b/game_template/windows/flutter/generated_plugin_registrant.cc index 8b6d4680a..09e8e2c34 100644 --- a/game_template/windows/flutter/generated_plugin_registrant.cc +++ b/game_template/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,9 @@ #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + AudioplayersWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); } diff --git a/game_template/windows/flutter/generated_plugins.cmake b/game_template/windows/flutter/generated_plugins.cmake index b93c4c30c..375535c98 100644 --- a/game_template/windows/flutter/generated_plugins.cmake +++ b/game_template/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + audioplayers_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST