feat: adding bumper sfx (#315)

* feat: adding bumper sfx

* feat: adding missing bumpers

* Update packages/pinball_audio/lib/src/pinball_audio.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>
pull/328/head
Erick 2 years ago committed by GitHub
parent 5af198a9a0
commit ca9679ba1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -25,17 +25,17 @@ class AndroidAcres extends Component {
)..initialPosition = Vector2(-26, -28.25),
AndroidBumper.a(
children: [
ScoringBehavior(points: Points.twentyThousand),
BumperScoringBehavior(points: Points.twentyThousand),
],
)..initialPosition = Vector2(-25, 1.3),
AndroidBumper.b(
children: [
ScoringBehavior(points: Points.twentyThousand),
BumperScoringBehavior(points: Points.twentyThousand),
],
)..initialPosition = Vector2(-32.8, -9.2),
AndroidBumper.cow(
children: [
ScoringBehavior(points: Points.twentyThousand),
BumperScoringBehavior(points: Points.twentyThousand),
],
)..initialPosition = Vector2(-20.5, -13.8),
AndroidSpaceshipBonusBehavior(),

@ -18,22 +18,22 @@ class FlutterForest extends Component with ZIndex {
children: [
Signpost(
children: [
ScoringBehavior(points: Points.fiveThousand),
BumperScoringBehavior(points: Points.fiveThousand),
],
)..initialPosition = Vector2(8.35, -58.3),
DashNestBumper.main(
children: [
ScoringBehavior(points: Points.twoHundredThousand),
BumperScoringBehavior(points: Points.twoHundredThousand),
],
)..initialPosition = Vector2(18.55, -59.35),
DashNestBumper.a(
children: [
ScoringBehavior(points: Points.twentyThousand),
BumperScoringBehavior(points: Points.twentyThousand),
],
)..initialPosition = Vector2(8.95, -51.95),
DashNestBumper.b(
children: [
ScoringBehavior(points: Points.twentyThousand),
BumperScoringBehavior(points: Points.twentyThousand),
],
)..initialPosition = Vector2(22.3, -46.75),
DashAnimatronic()..position = Vector2(20, -66),

@ -23,7 +23,6 @@ class ScoringBehavior extends ContactBehavior with HasGameRef<PinballGame> {
if (other is! Ball) return;
gameRef.read<GameBloc>().add(Scored(points: _points.value));
gameRef.audio.score();
gameRef.firstChild<ZCanvasComponent>()!.add(
ScoreComponent(
points: _points,
@ -32,3 +31,23 @@ class ScoringBehavior extends ContactBehavior with HasGameRef<PinballGame> {
);
}
}
/// {@template bumper_scoring_behavior}
/// A specific [ScoringBehavior] used for Bumpers.
/// In addition to its parent logic, also plays the
/// SFX for bumpers
/// {@endtemplate}
class BumperScoringBehavior extends ScoringBehavior {
/// {@macro bumper_scoring_behavior}
BumperScoringBehavior({
required Points points,
}) : super(points: points);
@override
void beginContact(Object other, Contact contact) {
super.beginContact(other, contact);
if (other is! Ball) return;
gameRef.audio.bumper();
}
}

@ -16,17 +16,17 @@ class SparkyScorch extends Component {
children: [
SparkyBumper.a(
children: [
ScoringBehavior(points: Points.twentyThousand),
BumperScoringBehavior(points: Points.twentyThousand),
],
)..initialPosition = Vector2(-22.9, -41.65),
SparkyBumper.b(
children: [
ScoringBehavior(points: Points.twentyThousand),
BumperScoringBehavior(points: Points.twentyThousand),
],
)..initialPosition = Vector2(-21.25, -57.9),
SparkyBumper.c(
children: [
ScoringBehavior(points: Points.twentyThousand),
BumperScoringBehavior(points: Points.twentyThousand),
],
)..initialPosition = Vector2(-3.3, -52.55),
SparkyComputerSensor()..initialPosition = Vector2(-13, -49.9),

@ -14,9 +14,10 @@ class $AssetsMusicGen {
class $AssetsSfxGen {
const $AssetsSfxGen();
String get bumperA => 'assets/sfx/bumper_a.mp3';
String get bumperB => 'assets/sfx/bumper_b.mp3';
String get google => 'assets/sfx/google.mp3';
String get ioPinballVoiceOver => 'assets/sfx/io_pinball_voice_over.mp3';
String get plim => 'assets/sfx/plim.mp3';
}
class Assets {

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:audioplayers/audioplayers.dart';
import 'package:flame_audio/audio_pool.dart';
import 'package:flame_audio/flame_audio.dart';
@ -40,6 +42,7 @@ class PinballAudio {
LoopSingleAudio? loopSingleAudio,
PreCacheSingleAudio? preCacheSingleAudio,
ConfigureAudioCache? configureAudioCache,
Random? seed,
}) : _createAudioPool = createAudioPool ?? AudioPool.create,
_playSingleAudio = playSingleAudio ?? FlameAudio.audioCache.play,
_loopSingleAudio = loopSingleAudio ?? FlameAudio.audioCache.loop,
@ -48,7 +51,8 @@ class PinballAudio {
_configureAudioCache = configureAudioCache ??
((AudioCache a) {
a.prefix = '';
});
}),
_seed = seed ?? Random();
final CreateAudioPool _createAudioPool;
@ -60,14 +64,24 @@ class PinballAudio {
final ConfigureAudioCache _configureAudioCache;
late AudioPool _scorePool;
final Random _seed;
late AudioPool _bumperAPool;
late AudioPool _bumperBPool;
/// Loads the sounds effects into the memory
Future<void> load() async {
_configureAudioCache(FlameAudio.audioCache);
_scorePool = await _createAudioPool(
_prefixFile(Assets.sfx.plim),
_bumperAPool = await _createAudioPool(
_prefixFile(Assets.sfx.bumperA),
maxPlayers: 4,
prefix: '',
);
_bumperBPool = await _createAudioPool(
_prefixFile(Assets.sfx.bumperB),
maxPlayers: 4,
prefix: '',
);
@ -79,9 +93,9 @@ class PinballAudio {
]);
}
/// Plays the basic score sound
void score() {
_scorePool.start();
/// Plays a random bumper sfx.
void bumper() {
(_seed.nextBool() ? _bumperAPool : _bumperBPool).start(volume: 0.6);
}
/// Plays the google word bonus

@ -1,4 +1,6 @@
// ignore_for_file: prefer_const_constructors, one_member_abstracts
import 'dart:math';
import 'package:audioplayers/audioplayers.dart';
import 'package:flame_audio/audio_pool.dart';
import 'package:flame_audio/flame_audio.dart';
@ -39,6 +41,8 @@ abstract class _PreCacheSingleAudio {
class _MockPreCacheSingleAudio extends Mock implements _PreCacheSingleAudio {}
class _MockRandom extends Mock implements Random {}
void main() {
group('PinballAudio', () {
late _MockCreateAudioPool createAudioPool;
@ -46,6 +50,7 @@ void main() {
late _MockPlaySingleAudio playSingleAudio;
late _MockLoopSingleAudio loopSingleAudio;
late _PreCacheSingleAudio preCacheSingleAudio;
late Random seed;
late PinballAudio audio;
setUpAll(() {
@ -74,12 +79,15 @@ void main() {
preCacheSingleAudio = _MockPreCacheSingleAudio();
when(() => preCacheSingleAudio.onCall(any())).thenAnswer((_) async {});
seed = _MockRandom();
audio = PinballAudio(
configureAudioCache: configureAudioCache.onCall,
createAudioPool: createAudioPool.onCall,
playSingleAudio: playSingleAudio.onCall,
loopSingleAudio: loopSingleAudio.onCall,
preCacheSingleAudio: preCacheSingleAudio.onCall,
seed: seed,
);
});
@ -88,12 +96,20 @@ void main() {
});
group('load', () {
test('creates the score pool', () async {
test('creates the bumpers pools', () async {
await audio.load();
verify(
() => createAudioPool.onCall(
'packages/pinball_audio/${Assets.sfx.plim}',
'packages/pinball_audio/${Assets.sfx.bumperA}',
maxPlayers: 4,
prefix: '',
),
).called(1);
verify(
() => createAudioPool.onCall(
'packages/pinball_audio/${Assets.sfx.bumperB}',
maxPlayers: 4,
prefix: '',
),
@ -137,22 +153,52 @@ void main() {
});
});
group('score', () {
test('plays the score sound pool', () async {
final audioPool = _MockAudioPool();
when(audioPool.start).thenAnswer((_) async => () {});
group('bumper', () {
late AudioPool bumperAPool;
late AudioPool bumperBPool;
setUp(() {
bumperAPool = _MockAudioPool();
when(() => bumperAPool.start(volume: any(named: 'volume')))
.thenAnswer((_) async => () {});
when(
() => createAudioPool.onCall(
any(),
'packages/pinball_audio/${Assets.sfx.bumperA}',
maxPlayers: any(named: 'maxPlayers'),
prefix: any(named: 'prefix'),
),
).thenAnswer((_) async => audioPool);
).thenAnswer((_) async => bumperAPool);
await audio.load();
audio.score();
bumperBPool = _MockAudioPool();
when(() => bumperBPool.start(volume: any(named: 'volume')))
.thenAnswer((_) async => () {});
when(
() => createAudioPool.onCall(
'packages/pinball_audio/${Assets.sfx.bumperB}',
maxPlayers: any(named: 'maxPlayers'),
prefix: any(named: 'prefix'),
),
).thenAnswer((_) async => bumperBPool);
});
group('when seed is true', () {
test('plays the bumper A sound pool', () async {
when(seed.nextBool).thenReturn(true);
await audio.load();
audio.bumper();
verify(() => bumperAPool.start(volume: 0.6)).called(1);
});
});
group('when seed is false', () {
test('plays the bumper B sound pool', () async {
when(seed.nextBool).thenReturn(false);
await audio.load();
audio.bumper();
verify(audioPool.start).called(1);
verify(() => bumperBPool.start(volume: 0.6)).called(1);
});
});
});

@ -90,20 +90,6 @@ void main() {
},
);
flameBlocTester.testGameWidget(
'plays score sound',
setUp: (game, tester) async {
final scoringBehavior = ScoringBehavior(points: Points.oneMillion);
await parent.add(scoringBehavior);
final canvas = ZCanvasComponent(children: [parent]);
await game.ensureAdd(canvas);
scoringBehavior.beginContact(ball, _MockContact());
verify(audio.score).called(1);
},
);
flameBlocTester.testGameWidget(
"adds a ScoreComponent at Ball's position with points",
setUp: (game, tester) async {
@ -130,4 +116,57 @@ void main() {
);
});
});
group('BumperScoringBehavior', () {
group('beginContact', () {
late GameBloc bloc;
late PinballAudio audio;
late Ball ball;
late BodyComponent parent;
setUp(() {
audio = _MockPinballAudio();
ball = _MockBall();
final ballBody = _MockBody();
when(() => ball.body).thenReturn(ballBody);
when(() => ballBody.position).thenReturn(Vector2.all(4));
parent = _TestBodyComponent();
});
final flameBlocTester = FlameBlocTester<EmptyPinballTestGame, GameBloc>(
gameBuilder: () => EmptyPinballTestGame(
audio: audio,
),
blocBuilder: () {
bloc = _MockGameBloc();
const state = GameState(
score: 0,
multiplier: 1,
rounds: 3,
bonusHistory: [],
);
whenListen(bloc, Stream.value(state), initialState: state);
return bloc;
},
assets: assets,
);
flameBlocTester.testGameWidget(
'plays bumper sound',
setUp: (game, tester) async {
final scoringBehavior = BumperScoringBehavior(
points: Points.oneMillion,
);
await parent.add(scoringBehavior);
final canvas = ZCanvasComponent(children: [parent]);
await game.ensureAdd(canvas);
scoringBehavior.beginContact(ball, _MockContact());
verify(audio.bumper).called(1);
},
);
});
});
}

Loading…
Cancel
Save