@ -1,4 +1,4 @@
|
||||
export 'ball_spawning_behavior.dart';
|
||||
export 'bumper_noisy_behavior.dart';
|
||||
export 'bumper_noise_behavior.dart';
|
||||
export 'camera_focusing_behavior.dart';
|
||||
export 'scoring_behavior.dart';
|
||||
|
@ -1,15 +1,13 @@
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:pinball/game/pinball_game.dart';
|
||||
import 'package:pinball_audio/pinball_audio.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
class BumperNoisyBehavior extends ContactBehavior with HasGameRef<PinballGame> {
|
||||
class BumperNoiseBehavior extends ContactBehavior {
|
||||
@override
|
||||
void beginContact(Object other, Contact contact) {
|
||||
super.beginContact(other, contact);
|
||||
gameRef.player.play(PinballAudio.bumper);
|
||||
readProvider<PinballPlayer>().play(PinballAudio.bumper);
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 569 KiB After Width: | Height: | Size: 374 KiB |
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 218 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 252 KiB After Width: | Height: | Size: 254 KiB |
@ -0,0 +1,65 @@
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
|
||||
class FlameProvider<T> extends Component {
|
||||
FlameProvider.value(
|
||||
this.provider, {
|
||||
Iterable<Component>? children,
|
||||
}) : super(
|
||||
children: children,
|
||||
);
|
||||
|
||||
final T provider;
|
||||
}
|
||||
|
||||
class MultiFlameProvider extends Component {
|
||||
MultiFlameProvider({
|
||||
required List<FlameProvider<dynamic>> providers,
|
||||
Iterable<Component>? children,
|
||||
}) : _providers = providers,
|
||||
_initialChildren = children,
|
||||
assert(providers.isNotEmpty, 'At least one provider must be given') {
|
||||
_addProviders();
|
||||
}
|
||||
|
||||
final List<FlameProvider<dynamic>> _providers;
|
||||
final Iterable<Component>? _initialChildren;
|
||||
FlameProvider<dynamic>? _lastProvider;
|
||||
|
||||
Future<void> _addProviders() async {
|
||||
final _list = [..._providers];
|
||||
|
||||
var current = _list.removeAt(0);
|
||||
while (_list.isNotEmpty) {
|
||||
final provider = _list.removeAt(0);
|
||||
await current.add(provider);
|
||||
current = provider;
|
||||
}
|
||||
|
||||
await add(_providers.first);
|
||||
_lastProvider = current;
|
||||
|
||||
_initialChildren?.forEach(add);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> add(Component component) async {
|
||||
if (_lastProvider == null) {
|
||||
await super.add(component);
|
||||
}
|
||||
await _lastProvider?.add(component);
|
||||
}
|
||||
}
|
||||
|
||||
extension ReadFlameProvider on Component {
|
||||
T readProvider<T>() {
|
||||
final providers = ancestors().whereType<FlameProvider<T>>();
|
||||
assert(
|
||||
providers.isNotEmpty,
|
||||
'No FlameProvider<$T> available on the component tree',
|
||||
);
|
||||
|
||||
return providers.first.provider;
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final flameTester = FlameTester(FlameGame.new);
|
||||
|
||||
group(
|
||||
'FlameProvider',
|
||||
() {
|
||||
test('can be instantiated', () {
|
||||
expect(
|
||||
FlameProvider<bool>.value(true),
|
||||
isA<FlameProvider<bool>>(),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('can be loaded', (game) async {
|
||||
final component = FlameProvider<bool>.value(true);
|
||||
await game.ensureAdd(component);
|
||||
expect(game.children, contains(component));
|
||||
});
|
||||
|
||||
flameTester.test('adds children', (game) async {
|
||||
final component = Component();
|
||||
final provider = FlameProvider<bool>.value(
|
||||
true,
|
||||
children: [component],
|
||||
);
|
||||
await game.ensureAdd(provider);
|
||||
expect(provider.children, contains(component));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
group('MultiFlameProvider', () {
|
||||
test('can be instantiated', () {
|
||||
expect(
|
||||
MultiFlameProvider(
|
||||
providers: [
|
||||
FlameProvider<bool>.value(true),
|
||||
],
|
||||
),
|
||||
isA<MultiFlameProvider>(),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('adds multiple providers', (game) async {
|
||||
final provider1 = FlameProvider<bool>.value(true);
|
||||
final provider2 = FlameProvider<bool>.value(true);
|
||||
final providers = MultiFlameProvider(
|
||||
providers: [provider1, provider2],
|
||||
);
|
||||
await game.ensureAdd(providers);
|
||||
expect(providers.children, contains(provider1));
|
||||
expect(provider1.children, contains(provider2));
|
||||
});
|
||||
|
||||
flameTester.test('adds children under provider', (game) async {
|
||||
final component = Component();
|
||||
final provider = FlameProvider<bool>.value(true);
|
||||
final providers = MultiFlameProvider(
|
||||
providers: [provider],
|
||||
children: [component],
|
||||
);
|
||||
await game.ensureAdd(providers);
|
||||
expect(provider.children, contains(component));
|
||||
});
|
||||
});
|
||||
|
||||
group(
|
||||
'ReadFlameProvider',
|
||||
() {
|
||||
flameTester.test('loads provider', (game) async {
|
||||
final component = Component();
|
||||
final provider = FlameProvider<bool>.value(
|
||||
true,
|
||||
children: [component],
|
||||
);
|
||||
await game.ensureAdd(provider);
|
||||
expect(component.readProvider<bool>(), isTrue);
|
||||
});
|
||||
|
||||
flameTester.test(
|
||||
'throws assertionError when no provider is found',
|
||||
(game) async {
|
||||
final component = Component();
|
||||
await game.ensureAdd(component);
|
||||
|
||||
expect(
|
||||
() => component.readProvider<bool>(),
|
||||
throwsAssertionError,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
@ -1,54 +1,57 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'package:flame_bloc/flame_bloc.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
import '../../../helpers/helpers.dart';
|
||||
class _TestGame extends Forge2DGame {
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
images.prefix = '';
|
||||
await images.loadAll([
|
||||
Assets.images.multiball.lit.keyName,
|
||||
Assets.images.multiball.dimmed.keyName,
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> pump(Multiballs child, {GameBloc? gameBloc}) {
|
||||
return ensureAdd(
|
||||
FlameBlocProvider<GameBloc, GameState>.value(
|
||||
value: gameBloc ?? GameBloc(),
|
||||
children: [child],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final assets = [
|
||||
Assets.images.multiball.lit.keyName,
|
||||
Assets.images.multiball.dimmed.keyName,
|
||||
];
|
||||
late GameBloc gameBloc;
|
||||
|
||||
setUp(() {
|
||||
gameBloc = GameBloc();
|
||||
});
|
||||
|
||||
final flameBlocTester = FlameBlocTester<PinballGame, GameBloc>(
|
||||
gameBuilder: EmptyPinballTestGame.new,
|
||||
blocBuilder: () => gameBloc,
|
||||
assets: assets,
|
||||
);
|
||||
final flameBlocTester = FlameTester(_TestGame.new);
|
||||
|
||||
group('Multiballs', () {
|
||||
flameBlocTester.testGameWidget(
|
||||
'loads correctly',
|
||||
setUp: (game, tester) async {
|
||||
final multiballs = Multiballs();
|
||||
await game.ensureAdd(multiballs);
|
||||
|
||||
expect(game.contains(multiballs), isTrue);
|
||||
await game.pump(multiballs);
|
||||
expect(game.descendants(), contains(multiballs));
|
||||
},
|
||||
);
|
||||
|
||||
group('loads', () {
|
||||
flameBlocTester.testGameWidget(
|
||||
'four Multiball',
|
||||
setUp: (game, tester) async {
|
||||
final multiballs = Multiballs();
|
||||
await game.ensureAdd(multiballs);
|
||||
|
||||
expect(
|
||||
multiballs.descendants().whereType<Multiball>().length,
|
||||
equals(4),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
flameBlocTester.test(
|
||||
'loads four Multiball',
|
||||
(game) async {
|
||||
final multiballs = Multiballs();
|
||||
await game.pump(multiballs);
|
||||
expect(
|
||||
multiballs.descendants().whereType<Multiball>().length,
|
||||
equals(4),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -1,63 +1,65 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'package:flame_bloc/flame_bloc.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
import '../../../helpers/helpers.dart';
|
||||
class _TestGame extends Forge2DGame {
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
images.prefix = '';
|
||||
await images.loadAll([
|
||||
Assets.images.multiplier.x2.lit.keyName,
|
||||
Assets.images.multiplier.x2.dimmed.keyName,
|
||||
Assets.images.multiplier.x3.lit.keyName,
|
||||
Assets.images.multiplier.x3.dimmed.keyName,
|
||||
Assets.images.multiplier.x4.lit.keyName,
|
||||
Assets.images.multiplier.x4.dimmed.keyName,
|
||||
Assets.images.multiplier.x5.lit.keyName,
|
||||
Assets.images.multiplier.x5.dimmed.keyName,
|
||||
Assets.images.multiplier.x6.lit.keyName,
|
||||
Assets.images.multiplier.x6.dimmed.keyName,
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> pump(Multipliers child) async {
|
||||
await ensureAdd(
|
||||
FlameBlocProvider<GameBloc, GameState>.value(
|
||||
value: GameBloc(),
|
||||
children: [child],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final assets = [
|
||||
Assets.images.multiplier.x2.lit.keyName,
|
||||
Assets.images.multiplier.x2.dimmed.keyName,
|
||||
Assets.images.multiplier.x3.lit.keyName,
|
||||
Assets.images.multiplier.x3.dimmed.keyName,
|
||||
Assets.images.multiplier.x4.lit.keyName,
|
||||
Assets.images.multiplier.x4.dimmed.keyName,
|
||||
Assets.images.multiplier.x5.lit.keyName,
|
||||
Assets.images.multiplier.x5.dimmed.keyName,
|
||||
Assets.images.multiplier.x6.lit.keyName,
|
||||
Assets.images.multiplier.x6.dimmed.keyName,
|
||||
];
|
||||
|
||||
late GameBloc gameBloc;
|
||||
|
||||
setUp(() {
|
||||
gameBloc = GameBloc();
|
||||
});
|
||||
|
||||
final flameBlocTester = FlameBlocTester<PinballGame, GameBloc>(
|
||||
gameBuilder: EmptyPinballTestGame.new,
|
||||
blocBuilder: () => gameBloc,
|
||||
assets: assets,
|
||||
);
|
||||
final flameTester = FlameTester(_TestGame.new);
|
||||
|
||||
group('Multipliers', () {
|
||||
flameBlocTester.testGameWidget(
|
||||
flameTester.test(
|
||||
'loads correctly',
|
||||
setUp: (game, tester) async {
|
||||
final multipliersGroup = Multipliers();
|
||||
await game.ensureAdd(multipliersGroup);
|
||||
|
||||
expect(game.contains(multipliersGroup), isTrue);
|
||||
(game) async {
|
||||
final component = Multipliers();
|
||||
await game.pump(component);
|
||||
expect(game.descendants(), contains(component));
|
||||
},
|
||||
);
|
||||
|
||||
group('loads', () {
|
||||
flameBlocTester.testGameWidget(
|
||||
'five Multiplier',
|
||||
setUp: (game, tester) async {
|
||||
final multipliersGroup = Multipliers();
|
||||
await game.ensureAdd(multipliersGroup);
|
||||
|
||||
expect(
|
||||
multipliersGroup.descendants().whereType<Multiplier>().length,
|
||||
equals(5),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
flameTester.test(
|
||||
'loads five Multiplier',
|
||||
(game) async {
|
||||
final multipliersGroup = Multipliers();
|
||||
await game.pump(multipliersGroup);
|
||||
expect(
|
||||
multipliersGroup.descendants().whereType<Multiplier>().length,
|
||||
equals(5),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|