Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
@ -1,2 +0,0 @@
|
|||||||
export 'alien_bumper_ball_contact_behavior.dart';
|
|
||||||
export 'alien_bumper_blinking_behavior.dart';
|
|
@ -1,17 +0,0 @@
|
|||||||
// ignore_for_file: public_member_api_docs
|
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
|
||||||
|
|
||||||
part 'alien_bumper_state.dart';
|
|
||||||
|
|
||||||
class AlienBumperCubit extends Cubit<AlienBumperState> {
|
|
||||||
AlienBumperCubit() : super(AlienBumperState.active);
|
|
||||||
|
|
||||||
void onBallContacted() {
|
|
||||||
emit(AlienBumperState.inactive);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onBlinked() {
|
|
||||||
emit(AlienBumperState.active);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
part of 'alien_bumper_cubit.dart';
|
|
||||||
|
|
||||||
/// Indicates the [AlienBumperCubit]'s current state.
|
|
||||||
enum AlienBumperState {
|
|
||||||
/// A lit up bumper.
|
|
||||||
active,
|
|
||||||
|
|
||||||
/// A dimmed bumper.
|
|
||||||
inactive,
|
|
||||||
}
|
|
@ -0,0 +1,2 @@
|
|||||||
|
export 'android_bumper_ball_contact_behavior.dart';
|
||||||
|
export 'android_bumper_blinking_behavior.dart';
|
@ -0,0 +1,17 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs
|
||||||
|
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
|
||||||
|
part 'android_bumper_state.dart';
|
||||||
|
|
||||||
|
class AndroidBumperCubit extends Cubit<AndroidBumperState> {
|
||||||
|
AndroidBumperCubit() : super(AndroidBumperState.dimmed);
|
||||||
|
|
||||||
|
void onBallContacted() {
|
||||||
|
emit(AndroidBumperState.dimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onBlinked() {
|
||||||
|
emit(AndroidBumperState.lit);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
// ignore_for_file: public_member_api_docs
|
||||||
|
|
||||||
|
part of 'android_bumper_cubit.dart';
|
||||||
|
|
||||||
|
enum AndroidBumperState {
|
||||||
|
lit,
|
||||||
|
dimmed,
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||||
|
import 'package:pinball_flame/pinball_flame.dart';
|
||||||
|
|
||||||
|
/// {@template bumping_behavior}
|
||||||
|
/// Makes any [BodyComponent] that contacts with [parent] bounce off.
|
||||||
|
/// {@endtemplate}
|
||||||
|
class BumpingBehavior extends ContactBehavior {
|
||||||
|
/// {@macro bumping_behavior}
|
||||||
|
BumpingBehavior({required double strength}) : _strength = strength;
|
||||||
|
|
||||||
|
/// Determines how strong the bump is.
|
||||||
|
final double _strength;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void postSolve(Object other, Contact contact, ContactImpulse impulse) {
|
||||||
|
super.postSolve(other, contact, impulse);
|
||||||
|
if (other is! BodyComponent) return;
|
||||||
|
|
||||||
|
other.body.applyLinearImpulse(
|
||||||
|
contact.manifold.localPoint
|
||||||
|
..normalize()
|
||||||
|
..multiply(Vector2.all(other.body.mass * _strength)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
import 'package:dashbook/dashbook.dart';
|
|
||||||
import 'package:sandbox/common/common.dart';
|
|
||||||
import 'package:sandbox/stories/alien_zone/alien_bumper_a_game.dart';
|
|
||||||
import 'package:sandbox/stories/alien_zone/alien_bumper_b_game.dart';
|
|
||||||
import 'package:sandbox/stories/alien_zone/spaceship_game.dart';
|
|
||||||
import 'package:sandbox/stories/alien_zone/spaceship_rail_game.dart';
|
|
||||||
import 'package:sandbox/stories/alien_zone/spaceship_ramp_game.dart';
|
|
||||||
|
|
||||||
void addAlienZoneStories(Dashbook dashbook) {
|
|
||||||
dashbook.storiesOf('Alien Zone')
|
|
||||||
..addGame(
|
|
||||||
title: 'Alien Bumper A',
|
|
||||||
description: AlienBumperAGame.description,
|
|
||||||
gameBuilder: (_) => AlienBumperAGame(),
|
|
||||||
)
|
|
||||||
..addGame(
|
|
||||||
title: 'Alien Bumper B',
|
|
||||||
description: AlienBumperBGame.description,
|
|
||||||
gameBuilder: (_) => AlienBumperBGame(),
|
|
||||||
)
|
|
||||||
..addGame(
|
|
||||||
title: 'Spaceship',
|
|
||||||
description: SpaceshipGame.description,
|
|
||||||
gameBuilder: (_) => SpaceshipGame(),
|
|
||||||
)
|
|
||||||
..addGame(
|
|
||||||
title: 'Spaceship Rail',
|
|
||||||
description: SpaceshipRailGame.description,
|
|
||||||
gameBuilder: (_) => SpaceshipRailGame(),
|
|
||||||
)
|
|
||||||
..addGame(
|
|
||||||
title: 'Spaceship Ramp',
|
|
||||||
description: SpaceshipRampGame.description,
|
|
||||||
gameBuilder: (_) => SpaceshipRampGame(),
|
|
||||||
);
|
|
||||||
}
|
|
@ -0,0 +1,36 @@
|
|||||||
|
import 'package:dashbook/dashbook.dart';
|
||||||
|
import 'package:sandbox/common/common.dart';
|
||||||
|
import 'package:sandbox/stories/android_acres/android_bumper_a_game.dart';
|
||||||
|
import 'package:sandbox/stories/android_acres/android_bumper_b_game.dart';
|
||||||
|
import 'package:sandbox/stories/android_acres/spaceship_game.dart';
|
||||||
|
import 'package:sandbox/stories/android_acres/spaceship_rail_game.dart';
|
||||||
|
import 'package:sandbox/stories/android_acres/spaceship_ramp_game.dart';
|
||||||
|
|
||||||
|
void addAndroidAcresStories(Dashbook dashbook) {
|
||||||
|
dashbook.storiesOf('Android Acres')
|
||||||
|
..addGame(
|
||||||
|
title: 'Android Bumper A',
|
||||||
|
description: AndroidBumperAGame.description,
|
||||||
|
gameBuilder: (_) => AndroidBumperAGame(),
|
||||||
|
)
|
||||||
|
..addGame(
|
||||||
|
title: 'Android Bumper B',
|
||||||
|
description: AndroidBumperBGame.description,
|
||||||
|
gameBuilder: (_) => AndroidBumperBGame(),
|
||||||
|
)
|
||||||
|
..addGame(
|
||||||
|
title: 'Spaceship',
|
||||||
|
description: SpaceshipGame.description,
|
||||||
|
gameBuilder: (_) => SpaceshipGame(),
|
||||||
|
)
|
||||||
|
..addGame(
|
||||||
|
title: 'Spaceship Rail',
|
||||||
|
description: SpaceshipRailGame.description,
|
||||||
|
gameBuilder: (_) => SpaceshipRailGame(),
|
||||||
|
)
|
||||||
|
..addGame(
|
||||||
|
title: 'Spaceship Ramp',
|
||||||
|
description: SpaceshipRampGame.description,
|
||||||
|
gameBuilder: (_) => SpaceshipRampGame(),
|
||||||
|
);
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
import 'package:bloc_test/bloc_test.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:pinball_components/pinball_components.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group(
|
|
||||||
'AlienBumperCubit',
|
|
||||||
() {
|
|
||||||
blocTest<AlienBumperCubit, AlienBumperState>(
|
|
||||||
'onBallContacted emits inactive',
|
|
||||||
build: AlienBumperCubit.new,
|
|
||||||
act: (bloc) => bloc.onBallContacted(),
|
|
||||||
expect: () => [AlienBumperState.inactive],
|
|
||||||
);
|
|
||||||
|
|
||||||
blocTest<AlienBumperCubit, AlienBumperState>(
|
|
||||||
'onBlinked emits active',
|
|
||||||
build: AlienBumperCubit.new,
|
|
||||||
act: (bloc) => bloc.onBlinked(),
|
|
||||||
expect: () => [AlienBumperState.active],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
@ -0,0 +1,24 @@
|
|||||||
|
import 'package:bloc_test/bloc_test.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:pinball_components/pinball_components.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group(
|
||||||
|
'AndroidBumperCubit',
|
||||||
|
() {
|
||||||
|
blocTest<AndroidBumperCubit, AndroidBumperState>(
|
||||||
|
'onBallContacted emits dimmed',
|
||||||
|
build: AndroidBumperCubit.new,
|
||||||
|
act: (bloc) => bloc.onBallContacted(),
|
||||||
|
expect: () => [AndroidBumperState.dimmed],
|
||||||
|
);
|
||||||
|
|
||||||
|
blocTest<AndroidBumperCubit, AndroidBumperState>(
|
||||||
|
'onBlinked emits lit',
|
||||||
|
build: AndroidBumperCubit.new,
|
||||||
|
act: (bloc) => bloc.onBlinked(),
|
||||||
|
expect: () => [AndroidBumperState.lit],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
// 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_components/src/components/bumping_behavior.dart';
|
||||||
|
|
||||||
|
import '../../helpers/helpers.dart';
|
||||||
|
import 'layer_test.dart';
|
||||||
|
|
||||||
|
class MockContactImpulse extends Mock implements ContactImpulse {}
|
||||||
|
|
||||||
|
class MockManifold extends Mock implements Manifold {}
|
||||||
|
|
||||||
|
class TestHeavyBodyComponent extends BodyComponent {
|
||||||
|
@override
|
||||||
|
Body createBody() {
|
||||||
|
final shape = CircleShape();
|
||||||
|
return world.createBody(
|
||||||
|
BodyDef(
|
||||||
|
type: BodyType.dynamic,
|
||||||
|
),
|
||||||
|
)..createFixtureFromShape(shape, 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
final flameTester = FlameTester(TestGame.new);
|
||||||
|
|
||||||
|
group('BumpingBehavior', () {
|
||||||
|
flameTester.test('can be added', (game) async {
|
||||||
|
final behavior = BumpingBehavior(strength: 0);
|
||||||
|
final component = TestBodyComponent();
|
||||||
|
await component.add(behavior);
|
||||||
|
await game.ensureAdd(component);
|
||||||
|
});
|
||||||
|
|
||||||
|
flameTester.testGameWidget(
|
||||||
|
'the bump is greater when the strengh is greater',
|
||||||
|
setUp: (game, tester) async {
|
||||||
|
final component1 = TestBodyComponent();
|
||||||
|
final behavior1 = BumpingBehavior(strength: 1);
|
||||||
|
await component1.add(behavior1);
|
||||||
|
|
||||||
|
final component2 = TestBodyComponent();
|
||||||
|
final behavior2 = BumpingBehavior(strength: 2);
|
||||||
|
await component2.add(behavior2);
|
||||||
|
|
||||||
|
final dummy1 = TestHeavyBodyComponent();
|
||||||
|
final dummy2 = TestHeavyBodyComponent();
|
||||||
|
|
||||||
|
await game.ensureAddAll([
|
||||||
|
component1,
|
||||||
|
component2,
|
||||||
|
dummy1,
|
||||||
|
dummy2,
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(dummy1.body.inverseMass, greaterThan(0));
|
||||||
|
expect(dummy2.body.inverseMass, greaterThan(0));
|
||||||
|
|
||||||
|
final contact = MockContact();
|
||||||
|
final manifold = MockManifold();
|
||||||
|
final contactImpulse = MockContactImpulse();
|
||||||
|
when(() => manifold.localPoint).thenReturn(Vector2.all(1));
|
||||||
|
when(() => contact.manifold).thenReturn(manifold);
|
||||||
|
|
||||||
|
behavior1.postSolve(dummy1, contact, contactImpulse);
|
||||||
|
behavior2.postSolve(dummy2, contact, contactImpulse);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
dummy2.body.linearVelocity.x,
|
||||||
|
greaterThan(dummy1.body.linearVelocity.x),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
dummy2.body.linearVelocity.y,
|
||||||
|
greaterThan(dummy1.body.linearVelocity.y),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
@ -1,48 +0,0 @@
|
|||||||
// ignore_for_file: cascade_invocations
|
|
||||||
|
|
||||||
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 'package:pinball_flame/pinball_flame.dart';
|
|
||||||
|
|
||||||
import '../../helpers/helpers.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
|
||||||
final assets = [
|
|
||||||
Assets.images.alienBumper.a.active.keyName,
|
|
||||||
Assets.images.alienBumper.a.inactive.keyName,
|
|
||||||
Assets.images.alienBumper.b.active.keyName,
|
|
||||||
Assets.images.alienBumper.b.inactive.keyName,
|
|
||||||
];
|
|
||||||
final flameTester = FlameTester(
|
|
||||||
() => EmptyPinballTestGame(assets: assets),
|
|
||||||
);
|
|
||||||
|
|
||||||
group('AlienZone', () {
|
|
||||||
flameTester.test(
|
|
||||||
'loads correctly',
|
|
||||||
(game) async {
|
|
||||||
await game.addFromBlueprint(AlienZone());
|
|
||||||
await game.ready();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
group('loads', () {
|
|
||||||
flameTester.test(
|
|
||||||
'two AlienBumper',
|
|
||||||
(game) async {
|
|
||||||
final alienZone = AlienZone();
|
|
||||||
await game.addFromBlueprint(alienZone);
|
|
||||||
await game.ready();
|
|
||||||
|
|
||||||
expect(
|
|
||||||
game.descendants().whereType<AlienBumper>().length,
|
|
||||||
equals(2),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
@ -0,0 +1,88 @@
|
|||||||
|
// ignore_for_file: cascade_invocations
|
||||||
|
|
||||||
|
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 'package:pinball_flame/pinball_flame.dart';
|
||||||
|
|
||||||
|
import '../../helpers/helpers.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
final assets = [
|
||||||
|
Assets.images.spaceship.ramp.boardOpening.keyName,
|
||||||
|
Assets.images.spaceship.ramp.railingForeground.keyName,
|
||||||
|
Assets.images.spaceship.ramp.railingBackground.keyName,
|
||||||
|
Assets.images.spaceship.ramp.main.keyName,
|
||||||
|
Assets.images.spaceship.ramp.arrow.inactive.keyName,
|
||||||
|
Assets.images.spaceship.ramp.arrow.active1.keyName,
|
||||||
|
Assets.images.spaceship.ramp.arrow.active2.keyName,
|
||||||
|
Assets.images.spaceship.ramp.arrow.active3.keyName,
|
||||||
|
Assets.images.spaceship.ramp.arrow.active4.keyName,
|
||||||
|
Assets.images.spaceship.ramp.arrow.active5.keyName,
|
||||||
|
Assets.images.androidBumper.a.lit.keyName,
|
||||||
|
Assets.images.androidBumper.a.dimmed.keyName,
|
||||||
|
Assets.images.androidBumper.b.lit.keyName,
|
||||||
|
Assets.images.androidBumper.b.dimmed.keyName,
|
||||||
|
];
|
||||||
|
final flameTester = FlameTester(
|
||||||
|
() => EmptyPinballTestGame(assets: assets),
|
||||||
|
);
|
||||||
|
|
||||||
|
group('AndroidAcres', () {
|
||||||
|
flameTester.test(
|
||||||
|
'loads correctly',
|
||||||
|
(game) async {
|
||||||
|
await game.addFromBlueprint(AndroidAcres());
|
||||||
|
await game.ready();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
group('loads', () {
|
||||||
|
flameTester.test(
|
||||||
|
'a Spaceship',
|
||||||
|
(game) async {
|
||||||
|
expect(
|
||||||
|
AndroidAcres().blueprints.whereType<Spaceship>().single,
|
||||||
|
isNotNull,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
flameTester.test(
|
||||||
|
'a SpaceshipRamp',
|
||||||
|
(game) async {
|
||||||
|
expect(
|
||||||
|
AndroidAcres().blueprints.whereType<SpaceshipRamp>().single,
|
||||||
|
isNotNull,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
flameTester.test(
|
||||||
|
'a SpaceshipRail',
|
||||||
|
(game) async {
|
||||||
|
expect(
|
||||||
|
AndroidAcres().blueprints.whereType<SpaceshipRail>().single,
|
||||||
|
isNotNull,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
flameTester.test(
|
||||||
|
'two AndroidBumper',
|
||||||
|
(game) async {
|
||||||
|
final androidZone = AndroidAcres();
|
||||||
|
await game.addFromBlueprint(androidZone);
|
||||||
|
await game.ready();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
game.descendants().whereType<AndroidBumper>().length,
|
||||||
|
equals(2),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|