mirror of https://github.com/flutter/pinball.git
parent
fdb9075738
commit
f0428d74bc
@ -0,0 +1 @@
|
|||||||
|
export 'blinking_behavior.dart';
|
@ -0,0 +1,111 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flame/components.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// {@template blinking_behavior}
|
||||||
|
/// Looping behavior that performs an action at the end of each loop.
|
||||||
|
/// {@endtemplate}
|
||||||
|
class BlinkingBehavior<T> extends Component {
|
||||||
|
/// {@macro blinking_behavior}
|
||||||
|
BlinkingBehavior({
|
||||||
|
required double loopDuration,
|
||||||
|
int loops = 1,
|
||||||
|
VoidCallback? onLoop,
|
||||||
|
VoidCallback? onFinished,
|
||||||
|
Stream<T>? stream,
|
||||||
|
bool Function(T? previousState, T newState)? listenWhen,
|
||||||
|
}) : _loopDuration = loopDuration,
|
||||||
|
_loops = loops,
|
||||||
|
_onLoop = onLoop,
|
||||||
|
_onFinished = onFinished,
|
||||||
|
_stream = stream,
|
||||||
|
_listenWhen = listenWhen;
|
||||||
|
|
||||||
|
final double _loopDuration;
|
||||||
|
final int _loops;
|
||||||
|
final VoidCallback? _onLoop;
|
||||||
|
final VoidCallback? _onFinished;
|
||||||
|
final Stream<T>? _stream;
|
||||||
|
final bool Function(T? previousState, T newState)? _listenWhen;
|
||||||
|
|
||||||
|
T? _previousState;
|
||||||
|
StreamSubscription<T>? _subscription;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onLoad() async {
|
||||||
|
await super.onLoad();
|
||||||
|
if (_stream == null && _listenWhen == null) {
|
||||||
|
await add(
|
||||||
|
LoopableTimerComponent(
|
||||||
|
period: _loopDuration,
|
||||||
|
loops: _loops,
|
||||||
|
onLoop: _onLoop,
|
||||||
|
onFinished: _onFinished,
|
||||||
|
)..start(),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_subscription = _stream!.listen((newState) async {
|
||||||
|
if (_listenWhen!(_previousState, newState)) {
|
||||||
|
await add(
|
||||||
|
LoopableTimerComponent(
|
||||||
|
period: _loopDuration,
|
||||||
|
loops: _loops,
|
||||||
|
onLoop: _onLoop,
|
||||||
|
onFinished: _onFinished,
|
||||||
|
)..start(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_previousState = newState;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onRemove() {
|
||||||
|
_subscription?.cancel();
|
||||||
|
super.onRemove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@template loopable_timer_component}
|
||||||
|
/// Timer that performs an action at the end of each loop.
|
||||||
|
/// {@endtemplate}
|
||||||
|
@visibleForTesting
|
||||||
|
class LoopableTimerComponent extends TimerComponent {
|
||||||
|
/// {@macro loopable_timer_component}
|
||||||
|
LoopableTimerComponent({
|
||||||
|
required double period,
|
||||||
|
int loops = 1,
|
||||||
|
VoidCallback? onLoop,
|
||||||
|
VoidCallback? onFinished,
|
||||||
|
}) : _periods = loops,
|
||||||
|
_onFinished = onFinished,
|
||||||
|
super(
|
||||||
|
period: period,
|
||||||
|
repeat: true,
|
||||||
|
onTick: onLoop,
|
||||||
|
autoStart: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
final int _periods;
|
||||||
|
|
||||||
|
final VoidCallback? _onFinished;
|
||||||
|
|
||||||
|
int _currentLoop = 0;
|
||||||
|
|
||||||
|
/// Begin the looping.
|
||||||
|
void start() => timer.start();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onTick() {
|
||||||
|
super.onTick();
|
||||||
|
|
||||||
|
_currentLoop++;
|
||||||
|
if (_currentLoop == _periods) {
|
||||||
|
timer.stop();
|
||||||
|
_onFinished?.call();
|
||||||
|
shouldRemove = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,39 +0,0 @@
|
|||||||
import 'package:flame/components.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_flame/pinball_flame.dart';
|
|
||||||
|
|
||||||
/// {@template android_bumper_blinking_behavior}
|
|
||||||
/// Makes an [AndroidBumper] blink back to [AndroidBumperState.lit] when
|
|
||||||
/// [AndroidBumperState.dimmed].
|
|
||||||
/// {@endtemplate}
|
|
||||||
class AndroidBumperBlinkingBehavior extends TimerComponent
|
|
||||||
with ParentIsA<AndroidBumper> {
|
|
||||||
/// {@macro android_bumper_blinking_behavior}
|
|
||||||
AndroidBumperBlinkingBehavior() : super(period: 0.05);
|
|
||||||
|
|
||||||
void _onNewState(AndroidBumperState state) {
|
|
||||||
switch (state) {
|
|
||||||
case AndroidBumperState.lit:
|
|
||||||
break;
|
|
||||||
case AndroidBumperState.dimmed:
|
|
||||||
timer
|
|
||||||
..reset()
|
|
||||||
..start();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> onLoad() async {
|
|
||||||
await super.onLoad();
|
|
||||||
timer.stop();
|
|
||||||
parent.bloc.stream.listen(_onNewState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onTick() {
|
|
||||||
super.onTick();
|
|
||||||
timer.stop();
|
|
||||||
parent.bloc.onBlinked();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
import 'package:flame/components.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_flame/pinball_flame.dart';
|
|
||||||
|
|
||||||
/// {@template kicker_blinking_behavior}
|
|
||||||
/// Makes a [Kicker] blink back to [KickerState.lit] when [KickerState.dimmed].
|
|
||||||
/// {@endtemplate}
|
|
||||||
class KickerBlinkingBehavior extends TimerComponent with ParentIsA<Kicker> {
|
|
||||||
/// {@macro kicker_blinking_behavior}
|
|
||||||
KickerBlinkingBehavior() : super(period: 0.05);
|
|
||||||
|
|
||||||
void _onNewState(KickerState state) {
|
|
||||||
switch (state) {
|
|
||||||
case KickerState.lit:
|
|
||||||
break;
|
|
||||||
case KickerState.dimmed:
|
|
||||||
timer
|
|
||||||
..reset()
|
|
||||||
..start();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> onLoad() async {
|
|
||||||
await super.onLoad();
|
|
||||||
timer.stop();
|
|
||||||
parent.bloc.stream.listen(_onNewState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onTick() {
|
|
||||||
super.onTick();
|
|
||||||
timer.stop();
|
|
||||||
parent.bloc.onBlinked();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export 'multiball_blinking_behavior.dart';
|
|
@ -1,78 +0,0 @@
|
|||||||
import 'package:flame/components.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_flame/pinball_flame.dart';
|
|
||||||
|
|
||||||
/// {@template multiball_blinking_behavior}
|
|
||||||
/// Makes a [Multiball] blink back to [MultiballLightState.lit] when
|
|
||||||
/// [MultiballLightState.dimmed].
|
|
||||||
/// {@endtemplate}
|
|
||||||
class MultiballBlinkingBehavior extends TimerComponent
|
|
||||||
with ParentIsA<Multiball> {
|
|
||||||
/// {@macro multiball_blinking_behavior}
|
|
||||||
MultiballBlinkingBehavior() : super(period: 0.1);
|
|
||||||
|
|
||||||
final _maxBlinks = 10;
|
|
||||||
|
|
||||||
int _blinksCounter = 0;
|
|
||||||
|
|
||||||
bool _isAnimating = false;
|
|
||||||
|
|
||||||
void _onNewState(MultiballState state) {
|
|
||||||
final animationEnabled =
|
|
||||||
state.animationState == MultiballAnimationState.blinking;
|
|
||||||
final canBlink = _blinksCounter < _maxBlinks;
|
|
||||||
|
|
||||||
if (animationEnabled && canBlink) {
|
|
||||||
_start();
|
|
||||||
} else {
|
|
||||||
_stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _start() {
|
|
||||||
if (!_isAnimating) {
|
|
||||||
_isAnimating = true;
|
|
||||||
timer
|
|
||||||
..reset()
|
|
||||||
..start();
|
|
||||||
_animate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _animate() {
|
|
||||||
parent.bloc.onBlink();
|
|
||||||
_blinksCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _stop() {
|
|
||||||
if (_isAnimating) {
|
|
||||||
_isAnimating = false;
|
|
||||||
timer.stop();
|
|
||||||
_blinksCounter = 0;
|
|
||||||
parent.bloc.onStop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> onLoad() async {
|
|
||||||
await super.onLoad();
|
|
||||||
parent.bloc.stream.listen(_onNewState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onTick() {
|
|
||||||
super.onTick();
|
|
||||||
if (!_isAnimating) {
|
|
||||||
timer.stop();
|
|
||||||
} else {
|
|
||||||
if (_blinksCounter < _maxBlinks) {
|
|
||||||
_animate();
|
|
||||||
timer
|
|
||||||
..reset()
|
|
||||||
..start();
|
|
||||||
} else {
|
|
||||||
timer.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +1,35 @@
|
|||||||
part of 'multiball_cubit.dart';
|
part of 'multiball_cubit.dart';
|
||||||
|
|
||||||
enum MultiballLightState {
|
enum MultiballSpriteState {
|
||||||
lit,
|
lit,
|
||||||
dimmed,
|
dimmed,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indicates if the blinking animation is running.
|
|
||||||
enum MultiballAnimationState {
|
|
||||||
idle,
|
|
||||||
blinking,
|
|
||||||
}
|
|
||||||
|
|
||||||
class MultiballState extends Equatable {
|
class MultiballState extends Equatable {
|
||||||
const MultiballState({
|
const MultiballState({
|
||||||
required this.lightState,
|
required this.spriteState,
|
||||||
required this.animationState,
|
required this.isAnimating,
|
||||||
});
|
});
|
||||||
|
|
||||||
const MultiballState.initial()
|
const MultiballState.initial()
|
||||||
: this(
|
: this(
|
||||||
lightState: MultiballLightState.dimmed,
|
spriteState: MultiballSpriteState.dimmed,
|
||||||
animationState: MultiballAnimationState.idle,
|
isAnimating: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
final MultiballLightState lightState;
|
final MultiballSpriteState spriteState;
|
||||||
final MultiballAnimationState animationState;
|
final bool isAnimating;
|
||||||
|
|
||||||
MultiballState copyWith({
|
MultiballState copyWith({
|
||||||
MultiballLightState? lightState,
|
MultiballSpriteState? lightState,
|
||||||
MultiballAnimationState? animationState,
|
bool? isAnimating,
|
||||||
}) {
|
}) {
|
||||||
return MultiballState(
|
return MultiballState(
|
||||||
lightState: lightState ?? this.lightState,
|
spriteState: lightState ?? this.spriteState,
|
||||||
animationState: animationState ?? this.animationState,
|
isAnimating: isAnimating ?? this.isAnimating,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [lightState, animationState];
|
List<Object> get props => [spriteState, isAnimating];
|
||||||
}
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
import 'package:flame/components.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_flame/pinball_flame.dart';
|
|
||||||
|
|
||||||
/// {@template skill_shot_blinking_behavior}
|
|
||||||
/// Makes a [SkillShot] blink between [SkillShotSpriteState.lit] and
|
|
||||||
/// [SkillShotSpriteState.dimmed] for a set amount of blinks.
|
|
||||||
/// {@endtemplate}
|
|
||||||
class SkillShotBlinkingBehavior extends TimerComponent
|
|
||||||
with ParentIsA<SkillShot> {
|
|
||||||
/// {@macro skill_shot_blinking_behavior}
|
|
||||||
SkillShotBlinkingBehavior() : super(period: 0.15);
|
|
||||||
|
|
||||||
final _maxBlinks = 4;
|
|
||||||
int _blinks = 0;
|
|
||||||
|
|
||||||
void _onNewState(SkillShotState state) {
|
|
||||||
if (state.isBlinking) {
|
|
||||||
timer
|
|
||||||
..reset()
|
|
||||||
..start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> onLoad() async {
|
|
||||||
await super.onLoad();
|
|
||||||
timer.stop();
|
|
||||||
parent.bloc.stream.listen(_onNewState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onTick() {
|
|
||||||
super.onTick();
|
|
||||||
if (_blinks != _maxBlinks * 2) {
|
|
||||||
parent.bloc.switched();
|
|
||||||
_blinks++;
|
|
||||||
} else {
|
|
||||||
_blinks = 0;
|
|
||||||
timer.stop();
|
|
||||||
parent.bloc.onBlinkingFinished();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
import 'package:flame/components.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_flame/pinball_flame.dart';
|
|
||||||
|
|
||||||
/// {@template sparky_bumper_blinking_behavior}
|
|
||||||
/// Makes a [SparkyBumper] blink back to [SparkyBumperState.lit] when
|
|
||||||
/// [SparkyBumperState.dimmed].
|
|
||||||
/// {@endtemplate}
|
|
||||||
class SparkyBumperBlinkingBehavior extends TimerComponent
|
|
||||||
with ParentIsA<SparkyBumper> {
|
|
||||||
/// {@macro sparky_bumper_blinking_behavior}
|
|
||||||
SparkyBumperBlinkingBehavior() : super(period: 0.05);
|
|
||||||
|
|
||||||
void _onNewState(SparkyBumperState state) {
|
|
||||||
switch (state) {
|
|
||||||
case SparkyBumperState.lit:
|
|
||||||
break;
|
|
||||||
case SparkyBumperState.dimmed:
|
|
||||||
timer
|
|
||||||
..reset()
|
|
||||||
..start();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> onLoad() async {
|
|
||||||
await super.onLoad();
|
|
||||||
timer.stop();
|
|
||||||
parent.bloc.stream.listen(_onNewState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onTick() {
|
|
||||||
super.onTick();
|
|
||||||
timer.stop();
|
|
||||||
parent.bloc.onBlinked();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +1,3 @@
|
|||||||
|
export 'behaviors/behaviors.dart';
|
||||||
export 'components/components.dart';
|
export 'components/components.dart';
|
||||||
export 'extensions/extensions.dart';
|
export 'extensions/extensions.dart';
|
||||||
|
@ -0,0 +1,163 @@
|
|||||||
|
// ignore_for_file: prefer_const_constructors, cascade_invocations
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flame/components.dart';
|
||||||
|
import 'package:flame_test/flame_test.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:mocktail/mocktail.dart';
|
||||||
|
import 'package:pinball_components/pinball_components.dart';
|
||||||
|
|
||||||
|
import '../../helpers/helpers.dart';
|
||||||
|
|
||||||
|
class _MockStream extends Mock implements Stream<void> {}
|
||||||
|
|
||||||
|
class _MockStreamSubscription extends Mock implements StreamSubscription<void> {
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
final flameTester = FlameTester(TestGame.new);
|
||||||
|
|
||||||
|
group('BlinkingBehavior', () {
|
||||||
|
flameTester.testGameWidget(
|
||||||
|
'loops for the given loops and loopDuration '
|
||||||
|
'and calls onLoop after each loop',
|
||||||
|
setUp: (game, tester) async {
|
||||||
|
const loopDuration = 0.1;
|
||||||
|
var loopCount = 0;
|
||||||
|
final behavior = BlinkingBehavior<void>(
|
||||||
|
loopDuration: loopDuration,
|
||||||
|
loops: 2,
|
||||||
|
onLoop: () => loopCount++,
|
||||||
|
);
|
||||||
|
final component = Component();
|
||||||
|
await component.add(behavior);
|
||||||
|
await game.ensureAdd(component);
|
||||||
|
|
||||||
|
await tester.pump();
|
||||||
|
game.update(loopDuration);
|
||||||
|
|
||||||
|
expect(loopCount, equals(1));
|
||||||
|
|
||||||
|
await tester.pump();
|
||||||
|
game.update(loopDuration);
|
||||||
|
|
||||||
|
expect(loopCount, equals(2));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
flameTester.testGameWidget(
|
||||||
|
'calls onFinished after all loops',
|
||||||
|
setUp: (game, tester) async {
|
||||||
|
const loopDuration = 0.1;
|
||||||
|
var onFinishedCalled = false;
|
||||||
|
final behavior = BlinkingBehavior<void>(
|
||||||
|
loopDuration: loopDuration,
|
||||||
|
loops: 2,
|
||||||
|
onFinished: () => onFinishedCalled = true,
|
||||||
|
);
|
||||||
|
final component = Component();
|
||||||
|
await component.add(behavior);
|
||||||
|
await game.ensureAdd(component);
|
||||||
|
|
||||||
|
await tester.pump();
|
||||||
|
game.update(loopDuration);
|
||||||
|
|
||||||
|
await tester.pump();
|
||||||
|
game.update(loopDuration);
|
||||||
|
|
||||||
|
expect(onFinishedCalled, isTrue);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
flameTester.test(
|
||||||
|
'adds a LoopableTimerComponent when stream and listenWhen '
|
||||||
|
'are not provided',
|
||||||
|
(game) async {
|
||||||
|
const loopDuration = 0.1;
|
||||||
|
final behavior = BlinkingBehavior<void>(
|
||||||
|
loopDuration: loopDuration,
|
||||||
|
);
|
||||||
|
final component = Component();
|
||||||
|
await component.add(behavior);
|
||||||
|
await game.ensureAdd(component);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
behavior.firstChild<LoopableTimerComponent>(),
|
||||||
|
isA<LoopableTimerComponent>(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
flameTester.testGameWidget(
|
||||||
|
'adds a LoopableTimerComponent only when the stream emits '
|
||||||
|
'a state satisfying listenWhen',
|
||||||
|
setUp: (game, tester) async {
|
||||||
|
const loopDuration = 0.1;
|
||||||
|
final streamController = StreamController<bool>();
|
||||||
|
final behavior = BlinkingBehavior<bool>(
|
||||||
|
loopDuration: loopDuration,
|
||||||
|
stream: streamController.stream,
|
||||||
|
listenWhen: (previousState, newState) => previousState != newState,
|
||||||
|
);
|
||||||
|
final component = Component();
|
||||||
|
await component.add(behavior);
|
||||||
|
await game.ensureAdd(component);
|
||||||
|
|
||||||
|
streamController.add(true);
|
||||||
|
await game.ready();
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
behavior.firstChild<LoopableTimerComponent>(),
|
||||||
|
isA<LoopableTimerComponent>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
game.update(loopDuration);
|
||||||
|
streamController.add(true);
|
||||||
|
await game.ready();
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
behavior.firstChild<LoopableTimerComponent>(),
|
||||||
|
isNull,
|
||||||
|
);
|
||||||
|
|
||||||
|
streamController.add(false);
|
||||||
|
await game.ready();
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
behavior.firstChild<LoopableTimerComponent>(),
|
||||||
|
isA<LoopableTimerComponent>(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
flameTester.testGameWidget(
|
||||||
|
'closes stream subscription when behavior is removed',
|
||||||
|
setUp: (game, tester) async {
|
||||||
|
const loopDuration = 0.1;
|
||||||
|
final stream = _MockStream();
|
||||||
|
final streamSubscription = _MockStreamSubscription();
|
||||||
|
when(() => stream.listen(any())).thenReturn(streamSubscription);
|
||||||
|
when(streamSubscription.cancel).thenAnswer((_) async {});
|
||||||
|
final behavior = BlinkingBehavior<void>(
|
||||||
|
loopDuration: loopDuration,
|
||||||
|
stream: stream,
|
||||||
|
listenWhen: (_, __) => false,
|
||||||
|
);
|
||||||
|
final component = Component();
|
||||||
|
await component.add(behavior);
|
||||||
|
await game.ensureAdd(component);
|
||||||
|
|
||||||
|
behavior.shouldRemove = true;
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(component.contains(behavior), isFalse);
|
||||||
|
verify(streamSubscription.cancel).called(1);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:bloc_test/bloc_test.dart';
|
|
||||||
import 'package:flame_test/flame_test.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:mocktail/mocktail.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_components/src/components/android_bumper/behaviors/behaviors.dart';
|
|
||||||
|
|
||||||
import '../../../../helpers/helpers.dart';
|
|
||||||
|
|
||||||
class _MockAndroidBumperCubit extends Mock implements AndroidBumperCubit {}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
final flameTester = FlameTester(TestGame.new);
|
|
||||||
|
|
||||||
group(
|
|
||||||
'AndroidBumperBlinkingBehavior',
|
|
||||||
() {
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'calls onBlinked after 0.05 seconds when dimmed',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = AndroidBumperBlinkingBehavior();
|
|
||||||
final bloc = _MockAndroidBumperCubit();
|
|
||||||
final streamController = StreamController<AndroidBumperState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: AndroidBumperState.lit,
|
|
||||||
);
|
|
||||||
|
|
||||||
final androidBumper = AndroidBumper.test(bloc: bloc);
|
|
||||||
await androidBumper.add(behavior);
|
|
||||||
await game.ensureAdd(androidBumper);
|
|
||||||
|
|
||||||
streamController.add(AndroidBumperState.dimmed);
|
|
||||||
await tester.pump();
|
|
||||||
game.update(0.05);
|
|
||||||
|
|
||||||
await streamController.close();
|
|
||||||
verify(bloc.onBlinked).called(1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:bloc_test/bloc_test.dart';
|
|
||||||
import 'package:flame_test/flame_test.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:mocktail/mocktail.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_components/src/components/kicker/behaviors/behaviors.dart';
|
|
||||||
|
|
||||||
import '../../../../helpers/helpers.dart';
|
|
||||||
|
|
||||||
class _MockKickerCubit extends Mock implements KickerCubit {}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
final flameTester = FlameTester(TestGame.new);
|
|
||||||
|
|
||||||
group(
|
|
||||||
'KickerBlinkingBehavior',
|
|
||||||
() {
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'calls onBlinked after 0.05 seconds when dimmed',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = KickerBlinkingBehavior();
|
|
||||||
final bloc = _MockKickerCubit();
|
|
||||||
final streamController = StreamController<KickerState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: KickerState.lit,
|
|
||||||
);
|
|
||||||
|
|
||||||
final kicker = Kicker.test(
|
|
||||||
side: BoardSide.left,
|
|
||||||
bloc: bloc,
|
|
||||||
);
|
|
||||||
await kicker.add(behavior);
|
|
||||||
await game.ensureAdd(kicker);
|
|
||||||
|
|
||||||
streamController.add(KickerState.dimmed);
|
|
||||||
await tester.pump();
|
|
||||||
game.update(0.05);
|
|
||||||
|
|
||||||
await streamController.close();
|
|
||||||
verify(bloc.onBlinked).called(1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,160 +0,0 @@
|
|||||||
// ignore_for_file: prefer_const_constructors, cascade_invocations
|
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:bloc_test/bloc_test.dart';
|
|
||||||
import 'package:flame_test/flame_test.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:mocktail/mocktail.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_components/src/components/multiball/behaviors/behaviors.dart';
|
|
||||||
|
|
||||||
import '../../../../helpers/helpers.dart';
|
|
||||||
|
|
||||||
class _MockMultiballCubit extends Mock implements MultiballCubit {}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
final flameTester = FlameTester(TestGame.new);
|
|
||||||
|
|
||||||
group(
|
|
||||||
'MultiballBlinkingBehavior',
|
|
||||||
() {
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'calls onBlink every 0.1 seconds when animation state is animated',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = MultiballBlinkingBehavior();
|
|
||||||
final bloc = _MockMultiballCubit();
|
|
||||||
final streamController = StreamController<MultiballState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: MultiballState.initial(),
|
|
||||||
);
|
|
||||||
|
|
||||||
final multiball = Multiball.test(bloc: bloc);
|
|
||||||
await multiball.add(behavior);
|
|
||||||
await game.ensureAdd(multiball);
|
|
||||||
|
|
||||||
streamController.add(
|
|
||||||
MultiballState(
|
|
||||||
animationState: MultiballAnimationState.blinking,
|
|
||||||
lightState: MultiballLightState.lit,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
game.update(0);
|
|
||||||
|
|
||||||
verify(bloc.onBlink).called(1);
|
|
||||||
|
|
||||||
await tester.pump();
|
|
||||||
game.update(0.1);
|
|
||||||
|
|
||||||
await streamController.close();
|
|
||||||
verify(bloc.onBlink).called(1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'calls onStop when animation state is stopped',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = MultiballBlinkingBehavior();
|
|
||||||
final bloc = _MockMultiballCubit();
|
|
||||||
final streamController = StreamController<MultiballState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: MultiballState.initial(),
|
|
||||||
);
|
|
||||||
when(bloc.onBlink).thenAnswer((_) async {});
|
|
||||||
|
|
||||||
final multiball = Multiball.test(bloc: bloc);
|
|
||||||
await multiball.add(behavior);
|
|
||||||
await game.ensureAdd(multiball);
|
|
||||||
|
|
||||||
streamController.add(
|
|
||||||
MultiballState(
|
|
||||||
animationState: MultiballAnimationState.blinking,
|
|
||||||
lightState: MultiballLightState.lit,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
streamController.add(
|
|
||||||
MultiballState(
|
|
||||||
animationState: MultiballAnimationState.idle,
|
|
||||||
lightState: MultiballLightState.lit,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await streamController.close();
|
|
||||||
verify(bloc.onStop).called(1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'onTick stops when there is no animation',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = MultiballBlinkingBehavior();
|
|
||||||
final bloc = _MockMultiballCubit();
|
|
||||||
final streamController = StreamController<MultiballState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: MultiballState.initial(),
|
|
||||||
);
|
|
||||||
when(bloc.onBlink).thenAnswer((_) async {});
|
|
||||||
|
|
||||||
final multiball = Multiball.test(bloc: bloc);
|
|
||||||
await multiball.add(behavior);
|
|
||||||
await game.ensureAdd(multiball);
|
|
||||||
|
|
||||||
streamController.add(
|
|
||||||
MultiballState(
|
|
||||||
animationState: MultiballAnimationState.idle,
|
|
||||||
lightState: MultiballLightState.lit,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
behavior.onTick();
|
|
||||||
|
|
||||||
expect(behavior.timer.isRunning(), false);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'onTick stops after 10 blinks repetitions',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = MultiballBlinkingBehavior();
|
|
||||||
final bloc = _MockMultiballCubit();
|
|
||||||
final streamController = StreamController<MultiballState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: MultiballState.initial(),
|
|
||||||
);
|
|
||||||
when(bloc.onBlink).thenAnswer((_) async {});
|
|
||||||
|
|
||||||
final multiball = Multiball.test(bloc: bloc);
|
|
||||||
await multiball.add(behavior);
|
|
||||||
await game.ensureAdd(multiball);
|
|
||||||
|
|
||||||
streamController.add(
|
|
||||||
MultiballState(
|
|
||||||
animationState: MultiballAnimationState.blinking,
|
|
||||||
lightState: MultiballLightState.dimmed,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
for (var i = 0; i < 10; i++) {
|
|
||||||
behavior.onTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(behavior.timer.isRunning(), false);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,125 +0,0 @@
|
|||||||
// ignore_for_file: cascade_invocations
|
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:bloc_test/bloc_test.dart';
|
|
||||||
import 'package:flame_test/flame_test.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:mocktail/mocktail.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_components/src/components/skill_shot/behaviors/behaviors.dart';
|
|
||||||
|
|
||||||
import '../../../../helpers/helpers.dart';
|
|
||||||
|
|
||||||
class _MockSkillShotCubit extends Mock implements SkillShotCubit {}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
final flameTester = FlameTester(TestGame.new);
|
|
||||||
|
|
||||||
group(
|
|
||||||
'SkillShotBlinkingBehavior',
|
|
||||||
() {
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'calls switched after 0.15 seconds when isBlinking and lit',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = SkillShotBlinkingBehavior();
|
|
||||||
final bloc = _MockSkillShotCubit();
|
|
||||||
final streamController = StreamController<SkillShotState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: const SkillShotState.initial(),
|
|
||||||
);
|
|
||||||
|
|
||||||
final skillShot = SkillShot.test(bloc: bloc);
|
|
||||||
await skillShot.add(behavior);
|
|
||||||
await game.ensureAdd(skillShot);
|
|
||||||
|
|
||||||
streamController.add(
|
|
||||||
const SkillShotState(
|
|
||||||
spriteState: SkillShotSpriteState.lit,
|
|
||||||
isBlinking: true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
game.update(0.15);
|
|
||||||
|
|
||||||
await streamController.close();
|
|
||||||
verify(bloc.switched).called(1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'calls switched after 0.15 seconds when isBlinking and dimmed',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = SkillShotBlinkingBehavior();
|
|
||||||
final bloc = _MockSkillShotCubit();
|
|
||||||
final streamController = StreamController<SkillShotState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: const SkillShotState.initial(),
|
|
||||||
);
|
|
||||||
|
|
||||||
final skillShot = SkillShot.test(bloc: bloc);
|
|
||||||
await skillShot.add(behavior);
|
|
||||||
await game.ensureAdd(skillShot);
|
|
||||||
|
|
||||||
streamController.add(
|
|
||||||
const SkillShotState(
|
|
||||||
spriteState: SkillShotSpriteState.dimmed,
|
|
||||||
isBlinking: true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
game.update(0.15);
|
|
||||||
|
|
||||||
await streamController.close();
|
|
||||||
verify(bloc.switched).called(1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'calls onBlinkingFinished after all blinks complete',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = SkillShotBlinkingBehavior();
|
|
||||||
final bloc = _MockSkillShotCubit();
|
|
||||||
final streamController = StreamController<SkillShotState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: const SkillShotState.initial(),
|
|
||||||
);
|
|
||||||
|
|
||||||
final skillShot = SkillShot.test(bloc: bloc);
|
|
||||||
await skillShot.add(behavior);
|
|
||||||
await game.ensureAdd(skillShot);
|
|
||||||
|
|
||||||
for (var i = 0; i <= 8; i++) {
|
|
||||||
if (i.isEven) {
|
|
||||||
streamController.add(
|
|
||||||
const SkillShotState(
|
|
||||||
spriteState: SkillShotSpriteState.lit,
|
|
||||||
isBlinking: true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
streamController.add(
|
|
||||||
const SkillShotState(
|
|
||||||
spriteState: SkillShotSpriteState.dimmed,
|
|
||||||
isBlinking: true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await tester.pump();
|
|
||||||
game.update(0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
await streamController.close();
|
|
||||||
verify(bloc.onBlinkingFinished).called(1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:bloc_test/bloc_test.dart';
|
|
||||||
import 'package:flame_test/flame_test.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:mocktail/mocktail.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
import 'package:pinball_components/src/components/sparky_bumper/behaviors/behaviors.dart';
|
|
||||||
|
|
||||||
import '../../../../helpers/helpers.dart';
|
|
||||||
|
|
||||||
class _MockSparkyBumperCubit extends Mock implements SparkyBumperCubit {}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
final flameTester = FlameTester(TestGame.new);
|
|
||||||
|
|
||||||
group(
|
|
||||||
'SparkyBumperBlinkingBehavior',
|
|
||||||
() {
|
|
||||||
flameTester.testGameWidget(
|
|
||||||
'calls onBlinked after 0.05 seconds when dimmed',
|
|
||||||
setUp: (game, tester) async {
|
|
||||||
final behavior = SparkyBumperBlinkingBehavior();
|
|
||||||
final bloc = _MockSparkyBumperCubit();
|
|
||||||
final streamController = StreamController<SparkyBumperState>();
|
|
||||||
whenListen(
|
|
||||||
bloc,
|
|
||||||
streamController.stream,
|
|
||||||
initialState: SparkyBumperState.lit,
|
|
||||||
);
|
|
||||||
|
|
||||||
final sparkyBumper = SparkyBumper.test(bloc: bloc);
|
|
||||||
await sparkyBumper.add(behavior);
|
|
||||||
await game.ensureAdd(sparkyBumper);
|
|
||||||
|
|
||||||
streamController.add(SparkyBumperState.dimmed);
|
|
||||||
await tester.pump();
|
|
||||||
game.update(0.05);
|
|
||||||
|
|
||||||
await streamController.close();
|
|
||||||
verify(bloc.onBlinked).called(1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
Reference in new issue