feat: add kicker audio group (#418)

* feat: add kicker audio group

* refactor: add RandomABAudio
pull/421/head
Allison Ryan 2 years ago committed by GitHub
parent 18d40aa85d
commit d601af7307
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,4 +5,5 @@ export 'bumper_noise_behavior.dart';
export 'camera_focusing_behavior.dart'; export 'camera_focusing_behavior.dart';
export 'character_selection_behavior.dart'; export 'character_selection_behavior.dart';
export 'cow_bumper_noise_behavior.dart'; export 'cow_bumper_noise_behavior.dart';
export 'kicker_noise_behavior.dart';
export 'scoring_behavior.dart'; export 'scoring_behavior.dart';

@ -0,0 +1,11 @@
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_flame/pinball_flame.dart';
class KickerNoiseBehavior extends ContactBehavior {
@override
void beginContact(Object other, Contact contact) {
super.beginContact(other, contact);
readProvider<PinballAudioPlayer>().play(PinballAudio.kicker);
}
}

@ -52,6 +52,7 @@ class _BottomGroupSide extends Component {
children: [ children: [
ScoringContactBehavior(points: Points.fiveThousand) ScoringContactBehavior(points: Points.fiveThousand)
..applyTo(['bouncy_edge']), ..applyTo(['bouncy_edge']),
KickerNoiseBehavior()..applyTo(['bouncy_edge']),
], ],
)..initialPosition = Vector2( )..initialPosition = Vector2(
(22.44 * direction) + centerXAdjustment, (22.44 * direction) + centerXAdjustment,

@ -23,6 +23,8 @@ class $AssetsSfxGen {
String get gameOverVoiceOver => 'assets/sfx/game_over_voice_over.mp3'; String get gameOverVoiceOver => 'assets/sfx/game_over_voice_over.mp3';
String get google => 'assets/sfx/google.mp3'; String get google => 'assets/sfx/google.mp3';
String get ioPinballVoiceOver => 'assets/sfx/io_pinball_voice_over.mp3'; String get ioPinballVoiceOver => 'assets/sfx/io_pinball_voice_over.mp3';
String get kickerA => 'assets/sfx/kicker_a.mp3';
String get kickerB => 'assets/sfx/kicker_b.mp3';
String get launcher => 'assets/sfx/launcher.mp3'; String get launcher => 'assets/sfx/launcher.mp3';
String get sparky => 'assets/sfx/sparky.mp3'; String get sparky => 'assets/sfx/sparky.mp3';
} }

@ -30,6 +30,9 @@ enum PinballAudio {
/// Launcher. /// Launcher.
launcher, launcher,
/// Kicker.
kicker,
/// Sparky. /// Sparky.
sparky, sparky,
@ -113,39 +116,45 @@ class _LoopAudio extends _Audio {
} }
} }
class _BumperAudio extends _Audio { class _RandomABAudio extends _Audio {
_BumperAudio({ _RandomABAudio({
required this.createAudioPool, required this.createAudioPool,
required this.seed, required this.seed,
required this.audioAssetA,
required this.audioAssetB,
this.volume,
}); });
final CreateAudioPool createAudioPool; final CreateAudioPool createAudioPool;
final Random seed; final Random seed;
final String audioAssetA;
final String audioAssetB;
final double? volume;
late AudioPool bumperA; late AudioPool audioA;
late AudioPool bumperB; late AudioPool audioB;
@override @override
Future<void> load() async { Future<void> load() async {
await Future.wait( await Future.wait(
[ [
createAudioPool( createAudioPool(
prefixFile(Assets.sfx.bumperA), prefixFile(audioAssetA),
maxPlayers: 4, maxPlayers: 4,
prefix: '', prefix: '',
).then((pool) => bumperA = pool), ).then((pool) => audioA = pool),
createAudioPool( createAudioPool(
prefixFile(Assets.sfx.bumperB), prefixFile(audioAssetB),
maxPlayers: 4, maxPlayers: 4,
prefix: '', prefix: '',
).then((pool) => bumperB = pool), ).then((pool) => audioB = pool),
], ],
); );
} }
@override @override
void play() { void play() {
(seed.nextBool() ? bumperA : bumperB).start(volume: 0.6); (seed.nextBool() ? audioA : audioB).start(volume: volume ?? 1);
} }
} }
@ -241,9 +250,19 @@ class PinballAudioPlayer {
playSingleAudio: _playSingleAudio, playSingleAudio: _playSingleAudio,
path: Assets.sfx.gameOverVoiceOver, path: Assets.sfx.gameOverVoiceOver,
), ),
PinballAudio.bumper: _BumperAudio( PinballAudio.bumper: _RandomABAudio(
createAudioPool: _createAudioPool,
seed: _seed,
audioAssetA: Assets.sfx.bumperA,
audioAssetB: Assets.sfx.bumperB,
volume: 0.6,
),
PinballAudio.kicker: _RandomABAudio(
createAudioPool: _createAudioPool, createAudioPool: _createAudioPool,
seed: _seed, seed: _seed,
audioAssetA: Assets.sfx.kickerA,
audioAssetB: Assets.sfx.kickerB,
volume: 0.6,
), ),
PinballAudio.cowMoo: _ThrottledAudio( PinballAudio.cowMoo: _ThrottledAudio(
preCacheSingleAudio: _preCacheSingleAudio, preCacheSingleAudio: _preCacheSingleAudio,

@ -119,6 +119,26 @@ void main() {
).called(1); ).called(1);
}); });
test('creates the kicker pools', () async {
await Future.wait(audioPlayer.load());
verify(
() => createAudioPool.onCall(
'packages/pinball_audio/${Assets.sfx.kickerA}',
maxPlayers: 4,
prefix: '',
),
).called(1);
verify(
() => createAudioPool.onCall(
'packages/pinball_audio/${Assets.sfx.kickerB}',
maxPlayers: 4,
prefix: '',
),
).called(1);
});
test('configures the audio cache instance', () async { test('configures the audio cache instance', () async {
await Future.wait(audioPlayer.load()); await Future.wait(audioPlayer.load());
@ -234,6 +254,55 @@ void main() {
}); });
}); });
group('kicker', () {
late AudioPool kickerAPool;
late AudioPool kickerBPool;
setUp(() {
kickerAPool = _MockAudioPool();
when(() => kickerAPool.start(volume: any(named: 'volume')))
.thenAnswer((_) async => () {});
when(
() => createAudioPool.onCall(
'packages/pinball_audio/${Assets.sfx.kickerA}',
maxPlayers: any(named: 'maxPlayers'),
prefix: any(named: 'prefix'),
),
).thenAnswer((_) async => kickerAPool);
kickerBPool = _MockAudioPool();
when(() => kickerBPool.start(volume: any(named: 'volume')))
.thenAnswer((_) async => () {});
when(
() => createAudioPool.onCall(
'packages/pinball_audio/${Assets.sfx.kickerB}',
maxPlayers: any(named: 'maxPlayers'),
prefix: any(named: 'prefix'),
),
).thenAnswer((_) async => kickerBPool);
});
group('when seed is true', () {
test('plays the kicker A sound pool', () async {
when(seed.nextBool).thenReturn(true);
await Future.wait(audioPlayer.load());
audioPlayer.play(PinballAudio.kicker);
verify(() => kickerAPool.start(volume: 0.6)).called(1);
});
});
group('when seed is false', () {
test('plays the kicker B sound pool', () async {
when(seed.nextBool).thenReturn(false);
await Future.wait(audioPlayer.load());
audioPlayer.play(PinballAudio.kicker);
verify(() => kickerBPool.start(volume: 0.6)).called(1);
});
});
});
group('cow moo', () { group('cow moo', () {
test('plays the correct file', () async { test('plays the correct file', () async {
await Future.wait(audioPlayer.load()); await Future.wait(audioPlayer.load());

@ -0,0 +1,59 @@
// ignore_for_file: cascade_invocations
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/behaviors/behaviors.dart';
import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_flame/pinball_flame.dart';
class _TestGame extends Forge2DGame {
Future<void> pump(
_TestBodyComponent child, {
required PinballAudioPlayer audioPlayer,
}) {
return ensureAdd(
FlameProvider<PinballAudioPlayer>.value(
audioPlayer,
children: [child],
),
);
}
}
class _TestBodyComponent extends BodyComponent {
@override
Body createBody() => world.createBody(BodyDef());
}
class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {}
class _MockContact extends Mock implements Contact {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('KickerNoiseBehavior', () {
late PinballAudioPlayer audioPlayer;
final flameTester = FlameTester(_TestGame.new);
setUp(() {
audioPlayer = _MockPinballAudioPlayer();
});
flameTester.testGameWidget(
'plays kicker sound',
setUp: (game, _) async {
final behavior = KickerNoiseBehavior();
final parent = _TestBodyComponent();
await game.pump(parent, audioPlayer: audioPlayer);
await parent.ensureAdd(behavior);
behavior.beginContact(Object(), _MockContact());
},
verify: (_, __) async {
verify(() => audioPlayer.play(PinballAudio.kicker)).called(1);
},
);
});
}
Loading…
Cancel
Save