mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-10-31 08:56:01 +08:00 
			
		
		
		
	Move flame_audio & update to work with current rc11 (#807)
This commit is contained in:
		| @ -15,4 +15,5 @@ Bridge packages are packages which: | ||||
|  | ||||
| ## Index | ||||
|  - [Flame](./flame) | ||||
|  - [Flame Audio](./flame_audio) | ||||
|  - [Fire Atlas](./flame_fire_atlas) | ||||
|  | ||||
							
								
								
									
										75
									
								
								packages/flame_audio/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								packages/flame_audio/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| # Miscellaneous | ||||
| *.class | ||||
| *.log | ||||
| *.pyc | ||||
| *.swp | ||||
| .DS_Store | ||||
| .atom/ | ||||
| .buildlog/ | ||||
| .history | ||||
| .svn/ | ||||
|  | ||||
| # IntelliJ related | ||||
| *.iml | ||||
| *.ipr | ||||
| *.iws | ||||
| .idea/ | ||||
|  | ||||
| # The .vscode folder contains launch configuration and tasks you configure in | ||||
| # VS Code which you may wish to be included in version control, so this line | ||||
| # is commented out by default. | ||||
| #.vscode/ | ||||
|  | ||||
| # Flutter/Dart/Pub related | ||||
| **/doc/api/ | ||||
| .dart_tool/ | ||||
| .flutter-plugins | ||||
| .flutter-plugins-dependencies | ||||
| .packages | ||||
| .pub-cache/ | ||||
| .pub/ | ||||
| build/ | ||||
|  | ||||
| # Android related | ||||
| **/android/**/gradle-wrapper.jar | ||||
| **/android/.gradle | ||||
| **/android/captures/ | ||||
| **/android/gradlew | ||||
| **/android/gradlew.bat | ||||
| **/android/local.properties | ||||
| **/android/**/GeneratedPluginRegistrant.java | ||||
|  | ||||
| # iOS/XCode related | ||||
| **/ios/**/*.mode1v3 | ||||
| **/ios/**/*.mode2v3 | ||||
| **/ios/**/*.moved-aside | ||||
| **/ios/**/*.pbxuser | ||||
| **/ios/**/*.perspectivev3 | ||||
| **/ios/**/*sync/ | ||||
| **/ios/**/.sconsign.dblite | ||||
| **/ios/**/.tags* | ||||
| **/ios/**/.vagrant/ | ||||
| **/ios/**/DerivedData/ | ||||
| **/ios/**/Icon? | ||||
| **/ios/**/Pods/ | ||||
| **/ios/**/.symlinks/ | ||||
| **/ios/**/profile | ||||
| **/ios/**/xcuserdata | ||||
| **/ios/.generated/ | ||||
| **/ios/Flutter/App.framework | ||||
| **/ios/Flutter/Flutter.framework | ||||
| **/ios/Flutter/Flutter.podspec | ||||
| **/ios/Flutter/Generated.xcconfig | ||||
| **/ios/Flutter/app.flx | ||||
| **/ios/Flutter/app.zip | ||||
| **/ios/Flutter/flutter_assets/ | ||||
| **/ios/Flutter/flutter_export_environment.sh | ||||
| **/ios/ServiceDefinitions.json | ||||
| **/ios/Runner/GeneratedPluginRegistrant.* | ||||
|  | ||||
| # Exceptions to above rules. | ||||
| !**/ios/**/default.mode1v3 | ||||
| !**/ios/**/default.mode2v3 | ||||
| !**/ios/**/default.pbxuser | ||||
| !**/ios/**/default.perspectivev3 | ||||
| !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages | ||||
							
								
								
									
										24
									
								
								packages/flame_audio/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								packages/flame_audio/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| ## [next] | ||||
| * Moved project to the mono-repo | ||||
| * Updated flame, audioplayers | ||||
|  | ||||
| ## [0.1.0-rc5] | ||||
| * Updated `audioplayers` version | ||||
| * Updated Flame version | ||||
| * Add support to null safety | ||||
|  | ||||
| ## [0.1.0-rc4] | ||||
| * Update audioplayers version | ||||
|  | ||||
| ## [0.1.0-rc3] | ||||
| * Bump flame version to rc5, upgrade code to match, update other dependencies | ||||
| * Add linter and fix code to comply | ||||
|  | ||||
| ## [0.1.0-rc2] | ||||
| * Bump flame version to rc2 and audioplayers version to 0.17 | ||||
|  | ||||
| ## [0.1.0-rc1] | ||||
| * First real version, including all necessary files for 1.0.0 | ||||
|  | ||||
| ## [0.0.1] | ||||
| * Empty release; in the future all flame audio related code will live here. | ||||
							
								
								
									
										1
									
								
								packages/flame_audio/LICENSE
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								packages/flame_audio/LICENSE
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | ||||
| ../../LICENSE | ||||
							
								
								
									
										28
									
								
								packages/flame_audio/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								packages/flame_audio/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| # flame_audio | ||||
|  | ||||
| <p align="center"> | ||||
|   <a href="https://flame-engine.org"> | ||||
|     <img alt="flame" width="200px" src="https://user-images.githubusercontent.com/6718144/101553774-3bc7b000-39ad-11eb-8a6a-de2daa31bd64.png"> | ||||
|   </a> | ||||
| </p> | ||||
|  | ||||
| <p align="center"> | ||||
| Adds audio support for <a href="https://github.com/flame-engine/flame">Flame</a> using the <a href="https://github.com/luanpotter/audioplayers">audioplayers</a> package. | ||||
| </p> | ||||
|  | ||||
| <p align="center"> | ||||
|   <a title="Pub" href="https://pub.dartlang.org/packages/flame_audio" ><img src="https://img.shields.io/pub/v/flame_audio.svg?style=popout&include_prereleases" /></a> | ||||
|   <img src="https://github.com/flame-engine/flame_audio/workflows/Lint/badge.svg?branch=master&event=push" alt="Test" /> | ||||
|   <a title="Discord" href="https://discord.gg/pxrBmy4" ><img src="https://img.shields.io/discord/509714518008528896.svg" /></a> | ||||
| </p> | ||||
|  | ||||
| --- | ||||
|  | ||||
| This package makes it easy to add audio capabilities to your games, integrating [Audioplayers](https://github.com/luanpotter/audioplayers) features seamless into your Flame game code. | ||||
|  | ||||
| Add this as a dependency alongside Flame v1 to your game if you want to play background music, ambient sounds, sound effects, etc. | ||||
|  | ||||
| # Credits | ||||
|  | ||||
|  * The [Flame Engine team](https://github.com/orgs/flame-engine/people), who is continuously working on maintaining and improving Flame. | ||||
|  * [luanpotter's audioplayers](https://github.com/luanpotter/audioplayer) lib, which was originally a fork from [rxlabz's audioplayer](https://github.com/rxlabz/audioplayer). | ||||
							
								
								
									
										149
									
								
								packages/flame_audio/analysis_options.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								packages/flame_audio/analysis_options.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,149 @@ | ||||
| # Source of linter options: | ||||
| # http://dart-lang.github.io/linter/lints/options/options.html | ||||
|  | ||||
| analyzer: | ||||
|   strong-mode: | ||||
|     implicit-casts: false | ||||
|     implicit-dynamic: false | ||||
|  | ||||
|   plugins: | ||||
|     - dart_code_metrics | ||||
|  | ||||
| linter: | ||||
|   rules: | ||||
|     - always_declare_return_types | ||||
|     - always_put_control_body_on_new_line | ||||
|     - always_require_non_null_named_parameters | ||||
|     - annotate_overrides | ||||
|     - avoid_double_and_int_checks | ||||
|     - avoid_dynamic_calls | ||||
|     - avoid_empty_else | ||||
|     - avoid_equals_and_hash_code_on_mutable_classes | ||||
|     - avoid_escaping_inner_quotes | ||||
|     - avoid_field_initializers_in_const_classes | ||||
|     - avoid_init_to_null | ||||
|     - avoid_js_rounded_ints | ||||
|     - avoid_null_checks_in_equality_operators | ||||
|     - avoid_private_typedef_functions | ||||
|     - avoid_redundant_argument_values | ||||
|     - avoid_relative_lib_imports | ||||
|     - avoid_return_types_on_setters | ||||
|     - avoid_shadowing_type_parameters | ||||
|     - avoid_slow_async_io | ||||
|     - avoid_type_to_string | ||||
|     - avoid_types_as_parameter_names | ||||
|     - avoid_unused_constructor_parameters | ||||
|     - await_only_futures | ||||
|     - camel_case_extensions | ||||
|     - camel_case_types | ||||
|     - cancel_subscriptions | ||||
|     - cast_nullable_to_non_nullable | ||||
|     - close_sinks | ||||
|     - comment_references | ||||
|     - constant_identifier_names | ||||
|     - control_flow_in_finally | ||||
|     - curly_braces_in_flow_control_structures | ||||
|     - directives_ordering | ||||
|     - do_not_use_environment | ||||
|     - empty_catches | ||||
|     - empty_constructor_bodies | ||||
|     - empty_statements | ||||
|     - exhaustive_cases | ||||
|     - file_names | ||||
|     - hash_and_equals | ||||
|     - implementation_imports | ||||
|     - invariant_booleans | ||||
|     - iterable_contains_unrelated_type | ||||
|     - join_return_with_assignment | ||||
|     - library_names | ||||
|     - library_prefixes | ||||
|     - list_remove_unrelated_type | ||||
|     - literal_only_boolean_expressions | ||||
|     - missing_whitespace_between_adjacent_strings | ||||
|     - no_adjacent_strings_in_list | ||||
|     - no_duplicate_case_values | ||||
|     - no_runtimeType_toString | ||||
|     - omit_local_variable_types | ||||
|     - package_api_docs | ||||
|     - package_names | ||||
|     - package_prefixed_library_names | ||||
|     - parameter_assignments | ||||
|     - prefer_adjacent_string_concatenation | ||||
|     - prefer_asserts_in_initializer_lists | ||||
|     - prefer_collection_literals | ||||
|     - prefer_conditional_assignment | ||||
|     - prefer_const_constructors | ||||
|     - prefer_const_constructors_in_immutables | ||||
|     - prefer_const_declarations | ||||
|     - prefer_const_literals_to_create_immutables | ||||
|     - prefer_contains | ||||
|     - prefer_equal_for_default_values | ||||
|     - prefer_final_fields | ||||
|     - prefer_final_in_for_each | ||||
|     - prefer_final_locals | ||||
|     - prefer_for_elements_to_map_fromIterable | ||||
|     - prefer_foreach | ||||
|     - prefer_function_declarations_over_variables | ||||
|     - prefer_generic_function_type_aliases | ||||
|     - prefer_if_elements_to_conditional_expressions | ||||
|     - prefer_if_null_operators | ||||
|     - prefer_initializing_formals | ||||
|     - prefer_inlined_adds | ||||
|     - prefer_interpolation_to_compose_strings | ||||
|     - prefer_is_empty | ||||
|     - prefer_is_not_empty | ||||
|     - prefer_is_not_operator | ||||
|     - prefer_iterable_whereType | ||||
|     - prefer_mixin | ||||
|     - prefer_null_aware_operators | ||||
|     - prefer_single_quotes | ||||
|     - prefer_spread_collections | ||||
|     - prefer_relative_imports | ||||
|     - prefer_typing_uninitialized_variables | ||||
|     - prefer_void_to_null | ||||
|     - provide_deprecation_message | ||||
|     - recursive_getters | ||||
|     - slash_for_doc_comments | ||||
|     - sort_unnamed_constructors_first | ||||
|     - test_types_in_equals | ||||
|     - throw_in_finally | ||||
|     - type_annotate_public_apis | ||||
|     - type_init_formals | ||||
|     - unnecessary_await_in_return | ||||
|     - unnecessary_brace_in_string_interps | ||||
|     - unnecessary_const | ||||
|     - unnecessary_getters_setters | ||||
|     - unnecessary_lambdas | ||||
|     - unnecessary_new | ||||
|     - unnecessary_null_aware_assignments | ||||
|     - unnecessary_null_in_if_null_operators | ||||
|     - unnecessary_overrides | ||||
|     - unnecessary_parenthesis | ||||
|     - unnecessary_raw_strings | ||||
|     - unnecessary_statements | ||||
|     - unnecessary_string_escapes | ||||
|     - unnecessary_string_interpolations | ||||
|     - unnecessary_this | ||||
|     - use_full_hex_values_for_flutter_colors | ||||
|     - use_function_type_syntax_for_parameters | ||||
|     - use_is_even_rather_than_modulo | ||||
|     - use_rethrow_when_possible | ||||
|     - unrelated_type_equality_checks | ||||
|     - unsafe_html | ||||
|     - void_checks | ||||
|  | ||||
| dart_code_metrics: | ||||
|   rules: | ||||
|     - prefer-trailing-comma | ||||
|     - prefer-trailing-comma-for-collection | ||||
|     - no-equal-then-else | ||||
|     - no-object-declaration | ||||
|     - potential-null-dereference | ||||
|   metrics-exclude: | ||||
|     - test/** | ||||
|   metrics: | ||||
|     number-of-parameters: 8 | ||||
|     number-of-methods: 32 | ||||
|     source-lines-of-code: 200 | ||||
|     cyclomatic-complexity: 36 | ||||
|     maximum-nesting-level: 8 | ||||
							
								
								
									
										51
									
								
								packages/flame_audio/example/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								packages/flame_audio/example/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| # Miscellaneous | ||||
| *.class | ||||
| *.log | ||||
| *.pyc | ||||
| *.swp | ||||
| .DS_Store | ||||
| .atom/ | ||||
| .buildlog/ | ||||
| .history | ||||
| .svn/ | ||||
|  | ||||
| # IntelliJ related | ||||
| *.iml | ||||
| *.ipr | ||||
| *.iws | ||||
| .idea/ | ||||
|  | ||||
| # The .vscode folder contains launch configuration and tasks you configure in | ||||
| # VS Code which you may wish to be included in version control, so this line | ||||
| # is commented out by default. | ||||
| #.vscode/ | ||||
|  | ||||
| # Flutter/Dart/Pub related | ||||
| **/doc/api/ | ||||
| **/ios/Flutter/.last_build_id | ||||
| .dart_tool/ | ||||
| .flutter-plugins | ||||
| .flutter-plugins-dependencies | ||||
| .packages | ||||
| .pub-cache/ | ||||
| .pub/ | ||||
| /build/ | ||||
|  | ||||
| # Web related | ||||
| lib/generated_plugin_registrant.dart | ||||
|  | ||||
| # Symbolication related | ||||
| app.*.symbols | ||||
|  | ||||
| # Obfuscation related | ||||
| app.*.map.json | ||||
|  | ||||
| # Exceptions to above rules. | ||||
| !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages | ||||
|  | ||||
| android | ||||
| ios | ||||
| web | ||||
| integration_test | ||||
| macos | ||||
| test | ||||
							
								
								
									
										10
									
								
								packages/flame_audio/example/.metadata
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								packages/flame_audio/example/.metadata
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| # This file tracks properties of this Flutter project. | ||||
| # Used by Flutter tool to assess capabilities and perform upgrades etc. | ||||
| # | ||||
| # This file should be version controlled and should not be manually edited. | ||||
|  | ||||
| version: | ||||
|   revision: a2bde82fbd52e09057a4146f46889f4e10342d32 | ||||
|   channel: beta | ||||
|  | ||||
| project_type: app | ||||
							
								
								
									
										6
									
								
								packages/flame_audio/example/CREDITS.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								packages/flame_audio/example/CREDITS.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| # Credits | ||||
|  | ||||
| CC-0 audio files for this examples obtained here: | ||||
|  | ||||
|  * sfx: https://opengameart.org/content/63-digital-sound-effects-lasers-phasers-space-etc | ||||
|  * bg music: https://opengameart.org/content/another-space-background-track | ||||
							
								
								
									
										3
									
								
								packages/flame_audio/example/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/flame_audio/example/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| # flame audio example | ||||
|  | ||||
| Simple project to showcase the usage of flame_audio | ||||
							
								
								
									
										
											BIN
										
									
								
								packages/flame_audio/example/assets/audio/music/bg_music.ogg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/flame_audio/example/assets/audio/music/bg_music.ogg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								packages/flame_audio/example/assets/audio/sfx/fire_1.mp3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/flame_audio/example/assets/audio/sfx/fire_1.mp3
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								packages/flame_audio/example/assets/audio/sfx/fire_2.mp3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/flame_audio/example/assets/audio/sfx/fire_2.mp3
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										81
									
								
								packages/flame_audio/example/lib/main.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								packages/flame_audio/example/lib/main.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | ||||
| import 'package:flame/components.dart'; | ||||
| import 'package:flame/extensions.dart'; | ||||
| import 'package:flame/game.dart'; | ||||
| import 'package:flame/gestures.dart'; | ||||
| import 'package:flame/palette.dart'; | ||||
| import 'package:flame_audio/audio_pool.dart'; | ||||
| import 'package:flame_audio/flame_audio.dart'; | ||||
| import 'package:flutter/widgets.dart' hide Animation; | ||||
|  | ||||
| void main() async { | ||||
|   runApp(GameWidget(game: AudioGame())); | ||||
| } | ||||
|  | ||||
| /// This example game showcases three possible use cases: | ||||
| /// | ||||
| /// 1. Use the static FlameAudio class to easily fire a sfx using the default | ||||
| /// configs for the button tap. | ||||
| /// 2. Uses a custom AudioPool for extremely efficient audio loading and pooling | ||||
| /// for tapping elsewhere. | ||||
| /// 3. Uses the Bgm utility for background music. | ||||
| class AudioGame extends BaseGame with TapDetector { | ||||
|   static Paint black = BasicPalette.black.paint(); | ||||
|   static Paint gray = const PaletteEntry(Color(0xFFCCCCCC)).paint(); | ||||
|   static TextPaint text = TextPaint( | ||||
|     config: TextPaintConfig(color: BasicPalette.white.color), | ||||
|   ); | ||||
|  | ||||
|   late AudioPool pool; | ||||
|  | ||||
|   @override | ||||
|   Future<void> onLoad() async { | ||||
|     pool = await AudioPool.create('fire_2.mp3', minPlayers: 3, maxPlayers: 4); | ||||
|     startBgmMusic(); | ||||
|   } | ||||
|  | ||||
|   Rect get button => Rect.fromLTWH(20, size.y - 300, size.x - 40, 200); | ||||
|  | ||||
|   void startBgmMusic() { | ||||
|     FlameAudio.bgm.initialize(); | ||||
|     FlameAudio.bgm.play('music/bg_music.ogg'); | ||||
|   } | ||||
|  | ||||
|   void fireOne() { | ||||
|     FlameAudio.audioCache.play('sfx/fire_1.mp3'); | ||||
|   } | ||||
|  | ||||
|   void fireTwo() { | ||||
|     pool.start(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   void render(Canvas canvas) { | ||||
|     super.render(canvas); | ||||
|     canvas.drawRect(size.toRect(), black); | ||||
|  | ||||
|     text.render( | ||||
|       canvas, | ||||
|       '(click anywhere for 1)', | ||||
|       Vector2(size.x / 2, 200), | ||||
|       anchor: Anchor.topCenter, | ||||
|     ); | ||||
|  | ||||
|     canvas.drawRect(button, gray); | ||||
|  | ||||
|     text.render( | ||||
|       canvas, | ||||
|       'click here for 2', | ||||
|       Vector2(size.x / 2, size.y - 200), | ||||
|       anchor: Anchor.bottomCenter, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   void onTapDown(TapDownInfo details) { | ||||
|     if (button.containsPoint(details.eventPosition.game)) { | ||||
|       fireTwo(); | ||||
|     } else { | ||||
|       fireOne(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										26
									
								
								packages/flame_audio/example/pubspec.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								packages/flame_audio/example/pubspec.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| name: example | ||||
| description: Simple project to showcase the usage of flame_audio | ||||
|  | ||||
| publish_to: 'none' | ||||
|  | ||||
| version: 1.0.0+1 | ||||
|  | ||||
| environment: | ||||
|   sdk: ">=2.12.0 <3.0.0" | ||||
|  | ||||
| dependencies: | ||||
|   flame: 1.0.0-releasecandidate.11 | ||||
|   flame_audio: | ||||
|     path: ../ | ||||
|   flutter: | ||||
|     sdk: flutter | ||||
|  | ||||
| dev_dependencies: | ||||
|   dart_code_metrics: ^3.2.2 | ||||
|  | ||||
| flutter: | ||||
|   uses-material-design: false | ||||
|   assets: | ||||
|     - assets/audio/music/bg_music.ogg | ||||
|     - assets/audio/sfx/fire_1.mp3 | ||||
|     - assets/audio/sfx/fire_2.mp3 | ||||
							
								
								
									
										101
									
								
								packages/flame_audio/lib/audio_pool.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								packages/flame_audio/lib/audio_pool.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | ||||
| import 'dart:async'; | ||||
|  | ||||
| import 'package:audioplayers/audioplayers.dart'; | ||||
| import 'package:synchronized/synchronized.dart'; | ||||
|  | ||||
| typedef Stoppable = void Function(); | ||||
|  | ||||
| /// An AudioPool is a provider of AudioPlayers that leaves them pre-loaded to minimize delays. | ||||
| /// | ||||
| /// All AudioPlayers loaded are for the same [sound]. If you want multiple sounds use multiple [AudioPool]. | ||||
| /// Use this class if you'd like have extremely quick firing, repetitive and simultaneous sounds, like shooting a laser in a fast-paced spaceship game. | ||||
| class AudioPool { | ||||
|   final AudioCache _cache; | ||||
|   final Map<String, AudioPlayer> _currentPlayers = {}; | ||||
|   final List<AudioPlayer> _availablePlayers = []; | ||||
|  | ||||
|   final String sound; | ||||
|   final bool repeating; | ||||
|   final int minPlayers, maxPlayers; | ||||
|  | ||||
|   final Lock _lock = Lock(); | ||||
|  | ||||
|   AudioPool._( | ||||
|     this.sound, { | ||||
|     bool? repeating, | ||||
|     int? maxPlayers, | ||||
|     int? minPlayers = 1, | ||||
|     String? prefix, | ||||
|   })  : _cache = AudioCache(prefix: prefix ?? 'assets/audio/sfx/'), | ||||
|         repeating = repeating ?? false, | ||||
|         maxPlayers = maxPlayers ?? 1, | ||||
|         minPlayers = minPlayers ?? 1; | ||||
|  | ||||
|   static Future<AudioPool> create( | ||||
|     String sound, { | ||||
|     bool? repeating, | ||||
|     int? maxPlayers, | ||||
|     int? minPlayers = 1, | ||||
|     String? prefix, | ||||
|   }) async { | ||||
|     final instance = AudioPool._( | ||||
|       sound, | ||||
|       repeating: repeating, | ||||
|       maxPlayers: maxPlayers, | ||||
|       minPlayers: minPlayers, | ||||
|       prefix: prefix, | ||||
|     ); | ||||
|     for (var i = 0; i < instance.minPlayers; i++) { | ||||
|       instance._availablePlayers.add(await instance._createNewAudioPlayer()); | ||||
|     } | ||||
|  | ||||
|     return instance; | ||||
|   } | ||||
|  | ||||
|   Future<Stoppable> start({double volume = 1.0}) async { | ||||
|     return _lock.synchronized(() async { | ||||
|       if (_availablePlayers.isEmpty) { | ||||
|         _availablePlayers.add(await _createNewAudioPlayer()); | ||||
|       } | ||||
|       final player = _availablePlayers.removeAt(0); | ||||
|       _currentPlayers[player.playerId] = player; | ||||
|       await player.setVolume(volume); | ||||
|       await player.resume(); | ||||
|  | ||||
|       late StreamSubscription<void> subscription; | ||||
|  | ||||
|       void stop() { | ||||
|         _lock.synchronized(() async { | ||||
|           final p = _currentPlayers.remove(player.playerId); | ||||
|           if (p != null) { | ||||
|             subscription.cancel(); | ||||
|             await p.stop(); | ||||
|             if (_availablePlayers.length >= maxPlayers) { | ||||
|               await p.release(); | ||||
|             } else { | ||||
|               _availablePlayers.add(p); | ||||
|             } | ||||
|           } | ||||
|         }); | ||||
|       } | ||||
|  | ||||
|       subscription = player.onPlayerCompletion.listen((_) { | ||||
|         if (repeating) { | ||||
|           player.resume(); | ||||
|         } else { | ||||
|           stop(); | ||||
|         } | ||||
|       }); | ||||
|  | ||||
|       return stop; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   Future<AudioPlayer> _createNewAudioPlayer() async { | ||||
|     final player = AudioPlayer(); | ||||
|     final url = (await _cache.load(sound)).path; | ||||
|     await player.setUrl(url); | ||||
|     await player.setReleaseMode(ReleaseMode.STOP); | ||||
|     return player; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										123
									
								
								packages/flame_audio/lib/bgm.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								packages/flame_audio/lib/bgm.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,123 @@ | ||||
| import 'dart:io'; | ||||
|  | ||||
| import 'package:audioplayers/audioplayers.dart'; | ||||
| import 'package:flutter/widgets.dart'; | ||||
|  | ||||
| /// The looping background music class. | ||||
| /// | ||||
| /// This class helps with looping background music management that reacts to | ||||
| /// application lifecycle state changes. On construction, the instance is added | ||||
| /// as an observer to the [WidgetsBinding] instance. A [dispose] function is | ||||
| /// provided in case this functionality needs to be unloaded but the app needs | ||||
| /// to keep running. | ||||
| class Bgm extends WidgetsBindingObserver { | ||||
|   bool _isRegistered = false; | ||||
|   late AudioCache audioCache; | ||||
|   AudioPlayer? audioPlayer; | ||||
|   bool isPlaying = false; | ||||
|  | ||||
|   Bgm({AudioCache? audioCache}) : audioCache = audioCache ?? AudioCache(); | ||||
|  | ||||
|   /// Registers a [WidgetsBinding] observer. | ||||
|   /// | ||||
|   /// This must be called for auto-pause and resume to work properly. | ||||
|   void initialize() { | ||||
|     if (_isRegistered) { | ||||
|       return; | ||||
|     } | ||||
|     _isRegistered = true; | ||||
|     WidgetsBinding.instance?.addObserver(this); | ||||
|   } | ||||
|  | ||||
|   /// Dispose the [WidgetsBinding] observer. | ||||
|   void dispose() { | ||||
|     if (!_isRegistered) { | ||||
|       return; | ||||
|     } | ||||
|     WidgetsBinding.instance?.removeObserver(this); | ||||
|     _isRegistered = false; | ||||
|   } | ||||
|  | ||||
|   /// Plays and loops a background music file specified by [filename]. | ||||
|   /// | ||||
|   /// The volume can be specified in the optional named parameter [volume] | ||||
|   /// where `0` means off and `1` means max. | ||||
|   /// | ||||
|   /// It is safe to call this function even when a current BGM track is | ||||
|   /// playing. | ||||
|   Future<void> play(String filename, {double volume = 1}) async { | ||||
|     final currentPlayer = audioPlayer; | ||||
|     if (currentPlayer != null && currentPlayer.state != PlayerState.STOPPED) { | ||||
|       currentPlayer.stop(); | ||||
|     } | ||||
|  | ||||
|     isPlaying = true; | ||||
|     audioPlayer = await audioCache.loop(filename, volume: volume); | ||||
|   } | ||||
|  | ||||
|   /// Stops the currently playing background music track (if any). | ||||
|   Future<void> stop() async { | ||||
|     isPlaying = false; | ||||
|     if (audioPlayer != null) { | ||||
|       await audioPlayer!.stop(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Resumes the currently played (but resumed) background music. | ||||
|   Future<void> resume() async { | ||||
|     if (audioPlayer != null) { | ||||
|       isPlaying = true; | ||||
|       await audioPlayer!.resume(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Pauses the background music without unloading or resetting the audio | ||||
|   /// player. | ||||
|   Future<void> pause() async { | ||||
|     if (audioPlayer != null) { | ||||
|       isPlaying = false; | ||||
|       await audioPlayer!.pause(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Pre-fetch an audio and store it in the cache. | ||||
|   /// | ||||
|   /// Alias of `audioCache.load();`. | ||||
|   Future<Uri> load(String file) => audioCache.load(file); | ||||
|  | ||||
|   /// Pre-fetch an audio and store it in the cache. | ||||
|   /// | ||||
|   /// Alias of `audioCache.loadAsFile();`. | ||||
|   Future<File> loadAsFile(String file) => audioCache.loadAsFile(file); | ||||
|  | ||||
|   /// Pre-fetch a list of audios and store them in the cache. | ||||
|   /// | ||||
|   /// Alias of `audioCache.loadAll();`. | ||||
|   Future<List<Uri>> loadAll(List<String> files) => audioCache.loadAll(files); | ||||
|  | ||||
|   /// Clears the file in the cache. | ||||
|   /// | ||||
|   /// Alias of `audioCache.clear();`. | ||||
|   void clear(Uri file) => audioCache.clear(file); | ||||
|  | ||||
|   /// Clears all the audios in the cache. | ||||
|   /// | ||||
|   /// Alias of `audioCache.clearAll();`. | ||||
|   void clearAll() => audioCache.clearAll(); | ||||
|  | ||||
|   /// Handler for AppLifecycleState changes. | ||||
|   /// | ||||
|   /// This function handles the automatic pause and resume when the app | ||||
|   /// lifecycle state changes. There is NO NEED to call this function directly | ||||
|   /// directly. | ||||
|   @override | ||||
|   void didChangeAppLifecycleState(AppLifecycleState state) { | ||||
|     if (state == AppLifecycleState.resumed) { | ||||
|       if (isPlaying && audioPlayer?.state == PlayerState.PAUSED) { | ||||
|         audioPlayer?.resume(); | ||||
|       } | ||||
|     } else { | ||||
|       audioPlayer?.pause(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										43
									
								
								packages/flame_audio/lib/flame_audio.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								packages/flame_audio/lib/flame_audio.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| import 'package:audioplayers/audioplayers.dart'; | ||||
|  | ||||
| import 'bgm.dart'; | ||||
|  | ||||
| /// This utility class holds static references to some global audio objects. | ||||
| /// | ||||
| /// You can use as a helper to very simply play a sound or a background music. | ||||
| /// Alternatively you can create your own instances and control them yourself. | ||||
| class FlameAudio { | ||||
|   /// Access a shared instance of the [AudioCache] class. | ||||
|   static AudioCache audioCache = AudioCache(prefix: 'assets/audio/'); | ||||
|  | ||||
|   /// Plays a single run of the given [file], with a given [volume]. | ||||
|   static Future<AudioPlayer> play(String file, {double volume = 1.0}) { | ||||
|     return audioCache.play(file, volume: volume, mode: PlayerMode.LOW_LATENCY); | ||||
|   } | ||||
|  | ||||
|   /// Plays, and keep looping the given [file] | ||||
|   static Future<AudioPlayer> loop(String file, {double volume = 1.0}) { | ||||
|     return audioCache.loop(file, volume: volume, mode: PlayerMode.LOW_LATENCY); | ||||
|   } | ||||
|  | ||||
|   /// Plays a single run of the given file [file] | ||||
|   /// This method supports long audio files | ||||
|   static Future<AudioPlayer> playLongAudio(String file, {double volume = 1.0}) { | ||||
|     return audioCache.play(file, volume: volume); | ||||
|   } | ||||
|  | ||||
|   /// Plays, and keep looping the given [file] | ||||
|   /// This method supports long audio files | ||||
|   /// | ||||
|   /// NOTE: Length audio files on Android have an audio gap between loop | ||||
|   /// iterations, this happens due to limitations on Android's native media | ||||
|   /// player features, if you need a gapless loop, prefer the loop method | ||||
|   static Future<AudioPlayer> loopLongAudio(String file, {double volume = 1.0}) { | ||||
|     return audioCache.loop(file, volume: volume); | ||||
|   } | ||||
|  | ||||
|   /// Access a shared instance of the [Bgm] class. | ||||
|   /// | ||||
|   /// This will use the same global audio cache from [FlameAudio]. | ||||
|   static late final Bgm bgm = Bgm(audioCache: audioCache); | ||||
| } | ||||
							
								
								
									
										22
									
								
								packages/flame_audio/pubspec.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								packages/flame_audio/pubspec.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| name: flame_audio | ||||
| description: Audio support for the Flame game engine. This containst all audio related code will live in the future, using the audioplayers package. | ||||
| version: 0.1.0-rc5 | ||||
| homepage: https://github.com/flame-engine/flame_audio | ||||
|  | ||||
| environment: | ||||
|   sdk: ">=2.12.0 <3.0.0" | ||||
|   flutter: ">=1.17.0" | ||||
|  | ||||
| dependencies: | ||||
|   flame: '>=1.0.0-releasecandidate.11' | ||||
|   audioplayers: ^0.19.0 | ||||
|   synchronized: ^3.0.0 | ||||
|   flutter: | ||||
|     sdk: flutter | ||||
|  | ||||
| dev_dependencies: | ||||
|   dart_code_metrics: ^3.2.2 | ||||
|   dartdoc: ^0.42.0 | ||||
|   flutter_test: | ||||
|     sdk: flutter | ||||
|   test: ^1.9.4 | ||||
		Reference in New Issue
	
	Block a user
	 Luan Nico
					Luan Nico