mirror of https://github.com/flutter/pinball.git
commit
536c34484f
@ -0,0 +1,23 @@
|
||||
name: pinball_ui
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "packages/pinball_ui/**"
|
||||
- ".github/workflows/pinball_ui.yaml"
|
||||
|
||||
pull_request:
|
||||
paths:
|
||||
- "packages/pinball_ui/**"
|
||||
- ".github/workflows/pinball_ui.yaml"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1
|
||||
with:
|
||||
working_directory: packages/pinball_ui
|
||||
coverage_excludes: "lib/gen/*.dart"
|
@ -1,86 +0,0 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
/// {@template board}
|
||||
/// The main flat surface of the [PinballGame].
|
||||
/// {endtemplate}
|
||||
class Board extends Component {
|
||||
/// {@macro board}
|
||||
// TODO(alestiago): Make Board a Blueprint and sort out priorities.
|
||||
Board() : super(priority: 1);
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
// TODO(allisonryan0002): add bottom group and flutter forest to pinball
|
||||
// game directly. Then remove board.
|
||||
final bottomGroup = _BottomGroup();
|
||||
|
||||
final flutterForest = FlutterForest();
|
||||
|
||||
await addAll([
|
||||
bottomGroup,
|
||||
flutterForest,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/// {@template bottom_group}
|
||||
/// Grouping of the board's bottom [Component]s.
|
||||
///
|
||||
/// The [_BottomGroup] consists of[Flipper]s, [Baseboard]s and [Kicker]s.
|
||||
/// {@endtemplate}
|
||||
// TODO(alestiago): Consider renaming once entire Board is defined.
|
||||
class _BottomGroup extends Component {
|
||||
/// {@macro bottom_group}
|
||||
_BottomGroup() : super(priority: RenderPriority.bottomGroup);
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
final rightSide = _BottomGroupSide(
|
||||
side: BoardSide.right,
|
||||
);
|
||||
final leftSide = _BottomGroupSide(
|
||||
side: BoardSide.left,
|
||||
);
|
||||
|
||||
await addAll([rightSide, leftSide]);
|
||||
}
|
||||
}
|
||||
|
||||
/// {@template bottom_group_side}
|
||||
/// Group with one side of [_BottomGroup]'s symmetric [Component]s.
|
||||
///
|
||||
/// For example, [Flipper]s are symmetric components.
|
||||
/// {@endtemplate}
|
||||
class _BottomGroupSide extends Component {
|
||||
/// {@macro bottom_group_side}
|
||||
_BottomGroupSide({
|
||||
required BoardSide side,
|
||||
}) : _side = side;
|
||||
|
||||
final BoardSide _side;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
final direction = _side.direction;
|
||||
final centerXAdjustment = _side.isLeft ? 0 : -6.5;
|
||||
|
||||
final flipper = ControlledFlipper(
|
||||
side: _side,
|
||||
)..initialPosition = Vector2((11.8 * direction) + centerXAdjustment, 43.6);
|
||||
final baseboard = Baseboard(side: _side)
|
||||
..initialPosition = Vector2(
|
||||
(25.58 * direction) + centerXAdjustment,
|
||||
28.69,
|
||||
);
|
||||
final kicker = Kicker(
|
||||
side: _side,
|
||||
)..initialPosition = Vector2(
|
||||
(22.4 * direction) + centerXAdjustment,
|
||||
25,
|
||||
);
|
||||
|
||||
await addAll([flipper, baseboard, kicker]);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
/// {@template bottom_group}
|
||||
/// Grouping of the board's symmetrical bottom [Component]s.
|
||||
///
|
||||
/// The [BottomGroup] consists of [Flipper]s, [Baseboard]s and [Kicker]s.
|
||||
/// {@endtemplate}
|
||||
// TODO(allisonryan0002): Consider renaming.
|
||||
class BottomGroup extends Component {
|
||||
/// {@macro bottom_group}
|
||||
BottomGroup()
|
||||
: super(
|
||||
children: [
|
||||
_BottomGroupSide(side: BoardSide.right),
|
||||
_BottomGroupSide(side: BoardSide.left),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// {@template bottom_group_side}
|
||||
/// Group with one side of [BottomGroup]'s symmetric [Component]s.
|
||||
///
|
||||
/// For example, [Flipper]s are symmetric components.
|
||||
/// {@endtemplate}
|
||||
class _BottomGroupSide extends Component {
|
||||
/// {@macro bottom_group_side}
|
||||
_BottomGroupSide({
|
||||
required BoardSide side,
|
||||
}) : _side = side,
|
||||
super(priority: RenderPriority.bottomGroup);
|
||||
|
||||
final BoardSide _side;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
final direction = _side.direction;
|
||||
final centerXAdjustment = _side.isLeft ? 0 : -6.5;
|
||||
|
||||
final flipper = ControlledFlipper(
|
||||
side: _side,
|
||||
)..initialPosition = Vector2((11.8 * direction) + centerXAdjustment, 43.6);
|
||||
final baseboard = Baseboard(side: _side)
|
||||
..initialPosition = Vector2(
|
||||
(25.58 * direction) + centerXAdjustment,
|
||||
28.69,
|
||||
);
|
||||
final kicker = Kicker(
|
||||
side: _side,
|
||||
)..initialPosition = Vector2(
|
||||
(22.4 * direction) + centerXAdjustment,
|
||||
25,
|
||||
);
|
||||
|
||||
await addAll([flipper, baseboard, kicker]);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
/// {@template dino_desert}
|
||||
/// Area located next to the [Launcher] containing the [ChromeDino] and
|
||||
/// [DinoWalls].
|
||||
/// {@endtemplate}
|
||||
// TODO(allisonryan0002): use a controller to initiate dino bonus when dino is
|
||||
// fully implemented.
|
||||
class DinoDesert extends Blueprint {
|
||||
/// {@macro dino_desert}
|
||||
DinoDesert()
|
||||
: super(
|
||||
components: [
|
||||
ChromeDino()..initialPosition = Vector2(12.3, -6.9),
|
||||
],
|
||||
blueprints: [
|
||||
DinoWalls(),
|
||||
],
|
||||
);
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import 'package:flame/extensions.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
/// {@template drain}
|
||||
/// Area located at the bottom of the board to detect when a [Ball] is lost.
|
||||
/// {@endtemplate}
|
||||
// TODO(allisonryan0002): move to components package when possible.
|
||||
class Drain extends BodyComponent with ContactCallbacks {
|
||||
/// {@macro drain}
|
||||
Drain() : super(renderBody: false);
|
||||
|
||||
@override
|
||||
Body createBody() {
|
||||
final shape = EdgeShape()
|
||||
..set(
|
||||
BoardDimensions.bounds.bottomLeft.toVector2(),
|
||||
BoardDimensions.bounds.bottomRight.toVector2(),
|
||||
);
|
||||
final fixtureDef = FixtureDef(shape, isSensor: true);
|
||||
final bodyDef = BodyDef(userData: this);
|
||||
|
||||
return world.createBody(bodyDef)..createFixture(fixtureDef);
|
||||
}
|
||||
|
||||
// TODO(allisonryan0002): move this to ball.dart when BallLost is removed.
|
||||
@override
|
||||
void beginContact(Object other, Contact contact) {
|
||||
super.beginContact(other, contact);
|
||||
if (other is! ControlledBall) return;
|
||||
other.controller.lost();
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
// ignore_for_file: avoid_renaming_method_parameters
|
||||
|
||||
import 'package:flame/extensions.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart' hide Assets;
|
||||
|
||||
/// {@template wall}
|
||||
/// A continuous generic and [BodyType.static] barrier that divides a game area.
|
||||
/// {@endtemplate}
|
||||
// TODO(alestiago): Remove [Wall] for [Pathway.straight].
|
||||
class Wall extends BodyComponent {
|
||||
/// {@macro wall}
|
||||
Wall({
|
||||
required this.start,
|
||||
required this.end,
|
||||
});
|
||||
|
||||
/// The [start] of the [Wall].
|
||||
final Vector2 start;
|
||||
|
||||
/// The [end] of the [Wall].
|
||||
final Vector2 end;
|
||||
|
||||
@override
|
||||
Body createBody() {
|
||||
final shape = EdgeShape()..set(start, end);
|
||||
|
||||
final fixtureDef = FixtureDef(shape)
|
||||
..restitution = 0.1
|
||||
..friction = 0;
|
||||
|
||||
final bodyDef = BodyDef()
|
||||
..userData = this
|
||||
..position = Vector2.zero()
|
||||
..type = BodyType.static;
|
||||
|
||||
return world.createBody(bodyDef)..createFixture(fixtureDef);
|
||||
}
|
||||
}
|
||||
|
||||
/// {@template bottom_wall}
|
||||
/// [Wall] located at the bottom of the board.
|
||||
///
|
||||
/// {@endtemplate}
|
||||
class BottomWall extends Wall with ContactCallbacks {
|
||||
/// {@macro bottom_wall}
|
||||
BottomWall()
|
||||
: super(
|
||||
start: BoardDimensions.bounds.bottomLeft.toVector2(),
|
||||
end: BoardDimensions.bounds.bottomRight.toVector2(),
|
||||
);
|
||||
|
||||
@override
|
||||
void beginContact(Object other, Contact contact) {
|
||||
super.beginContact(other, contact);
|
||||
if (other is! ControlledBall) return;
|
||||
other.controller.lost();
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
import 'package:sandbox/stories/baseboard/baseboard_game.dart';
|
||||
|
||||
void addBaseboardStories(Dashbook dashbook) {
|
||||
dashbook.storiesOf('Baseboard').addGame(
|
||||
title: 'Traced',
|
||||
description: BaseboardGame.description,
|
||||
gameBuilder: (_) => BaseboardGame(),
|
||||
);
|
||||
}
|
@ -0,0 +1 @@
|
||||
export 'stories.dart';
|
@ -0,0 +1,24 @@
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
import 'package:sandbox/stories/bottom_group/baseboard_game.dart';
|
||||
import 'package:sandbox/stories/bottom_group/flipper_game.dart';
|
||||
import 'package:sandbox/stories/bottom_group/kicker_game.dart';
|
||||
|
||||
void addBottomGroupStories(Dashbook dashbook) {
|
||||
dashbook.storiesOf('Bottom Group')
|
||||
..addGame(
|
||||
title: 'Flipper',
|
||||
description: FlipperGame.description,
|
||||
gameBuilder: (_) => FlipperGame(),
|
||||
)
|
||||
..addGame(
|
||||
title: 'Kicker',
|
||||
description: KickerGame.description,
|
||||
gameBuilder: (_) => KickerGame(),
|
||||
)
|
||||
..addGame(
|
||||
title: 'Baseboard',
|
||||
description: BaseboardGame.description,
|
||||
gameBuilder: (_) => BaseboardGame(),
|
||||
);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
import 'package:sandbox/stories/flipper/flipper_game.dart';
|
||||
|
||||
void addFlipperStories(Dashbook dashbook) {
|
||||
dashbook.storiesOf('Flipper').addGame(
|
||||
title: 'Traced',
|
||||
description: FlipperGame.description,
|
||||
gameBuilder: (_) => FlipperGame(),
|
||||
);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
import 'package:sandbox/stories/kicker/kicker_game.dart';
|
||||
|
||||
void addKickerStories(Dashbook dashbook) {
|
||||
dashbook.storiesOf('Kickers').addGame(
|
||||
title: 'Traced',
|
||||
description: KickerGame.description,
|
||||
gameBuilder: (_) => KickerGame(),
|
||||
);
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# VSCode related
|
||||
.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
@ -0,0 +1,11 @@
|
||||
# pinball_ui
|
||||
|
||||
[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link]
|
||||
[![License: MIT][license_badge]][license_link]
|
||||
|
||||
UI Toolkit for the Pinball Flutter Application
|
||||
|
||||
[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[license_link]: https://opensource.org/licenses/MIT
|
||||
[very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg
|
||||
[very_good_analysis_link]: https://pub.dev/packages/very_good_analysis
|
@ -0,0 +1,4 @@
|
||||
include: package:very_good_analysis/analysis_options.2.4.0.yaml
|
||||
analyzer:
|
||||
exclude:
|
||||
- lib/**/*.gen.dart
|
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,78 @@
|
||||
/// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
/// *****************************************************
|
||||
/// FlutterGen
|
||||
/// *****************************************************
|
||||
|
||||
// ignore_for_file: directives_ordering,unnecessary_import
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class $AssetsImagesGen {
|
||||
const $AssetsImagesGen();
|
||||
|
||||
$AssetsImagesDialogGen get dialog => const $AssetsImagesDialogGen();
|
||||
}
|
||||
|
||||
class $AssetsImagesDialogGen {
|
||||
const $AssetsImagesDialogGen();
|
||||
|
||||
/// File path: assets/images/dialog/background.png
|
||||
AssetGenImage get background =>
|
||||
const AssetGenImage('assets/images/dialog/background.png');
|
||||
}
|
||||
|
||||
class Assets {
|
||||
Assets._();
|
||||
|
||||
static const $AssetsImagesGen images = $AssetsImagesGen();
|
||||
}
|
||||
|
||||
class AssetGenImage extends AssetImage {
|
||||
const AssetGenImage(String assetName)
|
||||
: super(assetName, package: 'pinball_ui');
|
||||
|
||||
Image image({
|
||||
Key? key,
|
||||
ImageFrameBuilder? frameBuilder,
|
||||
ImageLoadingBuilder? loadingBuilder,
|
||||
ImageErrorWidgetBuilder? errorBuilder,
|
||||
String? semanticLabel,
|
||||
bool excludeFromSemantics = false,
|
||||
double? width,
|
||||
double? height,
|
||||
Color? color,
|
||||
BlendMode? colorBlendMode,
|
||||
BoxFit? fit,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
ImageRepeat repeat = ImageRepeat.noRepeat,
|
||||
Rect? centerSlice,
|
||||
bool matchTextDirection = false,
|
||||
bool gaplessPlayback = false,
|
||||
bool isAntiAlias = false,
|
||||
FilterQuality filterQuality = FilterQuality.low,
|
||||
}) {
|
||||
return Image(
|
||||
key: key,
|
||||
image: this,
|
||||
frameBuilder: frameBuilder,
|
||||
loadingBuilder: loadingBuilder,
|
||||
errorBuilder: errorBuilder,
|
||||
semanticLabel: semanticLabel,
|
||||
excludeFromSemantics: excludeFromSemantics,
|
||||
width: width,
|
||||
height: height,
|
||||
color: color,
|
||||
colorBlendMode: colorBlendMode,
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
repeat: repeat,
|
||||
centerSlice: centerSlice,
|
||||
matchTextDirection: matchTextDirection,
|
||||
gaplessPlayback: gaplessPlayback,
|
||||
isAntiAlias: isAntiAlias,
|
||||
filterQuality: filterQuality,
|
||||
);
|
||||
}
|
||||
|
||||
String get path => assetName;
|
||||
}
|
@ -0,0 +1 @@
|
||||
export 'assets.gen.dart';
|
@ -0,0 +1,3 @@
|
||||
library pinball_ui;
|
||||
|
||||
export 'src/dialog/dialog.dart';
|
@ -0,0 +1 @@
|
||||
export 'pixelated_decoration.dart';
|
@ -0,0 +1,56 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pinball_ui/gen/gen.dart';
|
||||
|
||||
/// {@template pixelated_decoration}
|
||||
/// Widget with pixelated background and layout defined for dialog displays.
|
||||
/// {@endtemplate}
|
||||
class PixelatedDecoration extends StatelessWidget {
|
||||
/// {@macro pixelated_decoration}
|
||||
const PixelatedDecoration({
|
||||
Key? key,
|
||||
required Widget header,
|
||||
required Widget body,
|
||||
}) : _header = header,
|
||||
_body = body,
|
||||
super(key: key);
|
||||
|
||||
final Widget _header;
|
||||
final Widget _body;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const radius = BorderRadius.all(Radius.circular(12));
|
||||
|
||||
return Material(
|
||||
borderRadius: radius,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: radius,
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fill,
|
||||
image: AssetImage(Assets.images.dialog.background.keyName),
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: radius,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: _header,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: _body,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
name: pinball_ui
|
||||
description: UI Toolkit for the Pinball Flutter Application
|
||||
version: 1.0.0+1
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ">=2.16.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
test: ^1.19.2
|
||||
very_good_analysis: ^2.4.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
generate: true
|
||||
|
||||
assets:
|
||||
- assets/images/dialog/
|
||||
|
||||
flutter_gen:
|
||||
line_length: 80
|
||||
assets:
|
||||
package_parameter_enabled: true
|
@ -0,0 +1,26 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
void main() {
|
||||
group('PixelatedDecoration', () {
|
||||
testWidgets('renders header and body', (tester) async {
|
||||
const headerText = 'header';
|
||||
const bodyText = 'body';
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: PixelatedDecoration(
|
||||
header: Text(headerText),
|
||||
body: Text(bodyText),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text(headerText), findsOneWidget);
|
||||
expect(find.text(bodyText), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
@ -1,110 +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 '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final assets = [
|
||||
Assets.images.dash.bumper.main.active.keyName,
|
||||
Assets.images.dash.bumper.main.inactive.keyName,
|
||||
Assets.images.dash.bumper.a.active.keyName,
|
||||
Assets.images.dash.bumper.a.inactive.keyName,
|
||||
Assets.images.dash.bumper.b.active.keyName,
|
||||
Assets.images.dash.bumper.b.inactive.keyName,
|
||||
Assets.images.dash.animatronic.keyName,
|
||||
Assets.images.signpost.inactive.keyName,
|
||||
Assets.images.signpost.active1.keyName,
|
||||
Assets.images.signpost.active2.keyName,
|
||||
Assets.images.signpost.active3.keyName,
|
||||
Assets.images.baseboard.left.keyName,
|
||||
Assets.images.baseboard.right.keyName,
|
||||
Assets.images.flipper.left.keyName,
|
||||
Assets.images.flipper.right.keyName,
|
||||
];
|
||||
final flameTester = FlameTester(
|
||||
() => EmptyPinballTestGame(assets: assets),
|
||||
);
|
||||
|
||||
group('Board', () {
|
||||
flameTester.test(
|
||||
'loads correctly',
|
||||
(game) async {
|
||||
final board = Board();
|
||||
await game.ready();
|
||||
await game.ensureAdd(board);
|
||||
|
||||
expect(game.contains(board), isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
group('loads', () {
|
||||
flameTester.test(
|
||||
'one left flipper',
|
||||
(game) async {
|
||||
final board = Board();
|
||||
await game.ready();
|
||||
await game.ensureAdd(board);
|
||||
|
||||
final leftFlippers = board.descendants().whereType<Flipper>().where(
|
||||
(flipper) => flipper.side.isLeft,
|
||||
);
|
||||
expect(leftFlippers.length, equals(1));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'one right flipper',
|
||||
(game) async {
|
||||
final board = Board();
|
||||
await game.ready();
|
||||
await game.ensureAdd(board);
|
||||
final rightFlippers = board.descendants().whereType<Flipper>().where(
|
||||
(flipper) => flipper.side.isRight,
|
||||
);
|
||||
expect(rightFlippers.length, equals(1));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'two Baseboards',
|
||||
(game) async {
|
||||
final board = Board();
|
||||
await game.ready();
|
||||
await game.ensureAdd(board);
|
||||
|
||||
final baseboards = board.descendants().whereType<Baseboard>();
|
||||
expect(baseboards.length, equals(2));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'two Kickers',
|
||||
(game) async {
|
||||
final board = Board();
|
||||
await game.ready();
|
||||
await game.ensureAdd(board);
|
||||
|
||||
final kickers = board.descendants().whereType<Kicker>();
|
||||
expect(kickers.length, equals(2));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'one FlutterForest',
|
||||
(game) async {
|
||||
final board = Board();
|
||||
await game.ready();
|
||||
await game.ensureAdd(board);
|
||||
|
||||
final flutterForest = board.descendants().whereType<FlutterForest>();
|
||||
expect(flutterForest.length, equals(1));
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
// 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 '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final assets = [
|
||||
Assets.images.baseboard.left.keyName,
|
||||
Assets.images.baseboard.right.keyName,
|
||||
Assets.images.flipper.left.keyName,
|
||||
Assets.images.flipper.right.keyName,
|
||||
];
|
||||
final flameTester = FlameTester(
|
||||
() => EmptyPinballTestGame(assets: assets),
|
||||
);
|
||||
|
||||
group('BottomGroup', () {
|
||||
flameTester.test(
|
||||
'loads correctly',
|
||||
(game) async {
|
||||
final bottomGroup = BottomGroup();
|
||||
await game.ensureAdd(bottomGroup);
|
||||
|
||||
expect(game.contains(bottomGroup), isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
group('loads', () {
|
||||
flameTester.test(
|
||||
'one left flipper',
|
||||
(game) async {
|
||||
final bottomGroup = BottomGroup();
|
||||
await game.ensureAdd(bottomGroup);
|
||||
|
||||
final leftFlippers =
|
||||
bottomGroup.descendants().whereType<Flipper>().where(
|
||||
(flipper) => flipper.side.isLeft,
|
||||
);
|
||||
expect(leftFlippers.length, equals(1));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'one right flipper',
|
||||
(game) async {
|
||||
final bottomGroup = BottomGroup();
|
||||
await game.ensureAdd(bottomGroup);
|
||||
|
||||
final rightFlippers =
|
||||
bottomGroup.descendants().whereType<Flipper>().where(
|
||||
(flipper) => flipper.side.isRight,
|
||||
);
|
||||
expect(rightFlippers.length, equals(1));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'two Baseboards',
|
||||
(game) async {
|
||||
final bottomGroup = BottomGroup();
|
||||
await game.ensureAdd(bottomGroup);
|
||||
|
||||
final basebottomGroups =
|
||||
bottomGroup.descendants().whereType<Baseboard>();
|
||||
expect(basebottomGroups.length, equals(2));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'two Kickers',
|
||||
(game) async {
|
||||
final bottomGroup = BottomGroup();
|
||||
await game.ensureAdd(bottomGroup);
|
||||
|
||||
final kickers = bottomGroup.descendants().whereType<Kicker>();
|
||||
expect(kickers.length, equals(2));
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
// 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/game.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final flameTester = FlameTester(TestGame.new);
|
||||
|
||||
group('Drain', () {
|
||||
flameTester.test(
|
||||
'loads correctly',
|
||||
(game) async {
|
||||
final drain = Drain();
|
||||
await game.ensureAdd(drain);
|
||||
|
||||
expect(game.contains(drain), isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'body is static',
|
||||
(game) async {
|
||||
final drain = Drain();
|
||||
await game.ensureAdd(drain);
|
||||
|
||||
expect(drain.body.bodyType, equals(BodyType.static));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'is sensor',
|
||||
(game) async {
|
||||
final drain = Drain();
|
||||
await game.ensureAdd(drain);
|
||||
|
||||
expect(drain.body.fixtures.first.isSensor, isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'calls lost on contact with ball',
|
||||
() async {
|
||||
final drain = Drain();
|
||||
final ball = MockControlledBall();
|
||||
final controller = MockBallController();
|
||||
when(() => ball.controller).thenReturn(controller);
|
||||
|
||||
drain.beginContact(ball, MockContact());
|
||||
|
||||
verify(controller.lost).called(1);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
// 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:pinball/game/game.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final flameTester = FlameTester(EmptyPinballTestGame.new);
|
||||
|
||||
group('Wall', () {
|
||||
flameTester.test(
|
||||
'loads correctly',
|
||||
(game) async {
|
||||
await game.ready();
|
||||
final wall = Wall(
|
||||
start: Vector2.zero(),
|
||||
end: Vector2(100, 0),
|
||||
);
|
||||
await game.ensureAdd(wall);
|
||||
|
||||
expect(game.contains(wall), isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
group('body', () {
|
||||
flameTester.test(
|
||||
'positions correctly',
|
||||
(game) async {
|
||||
final wall = Wall(
|
||||
start: Vector2.zero(),
|
||||
end: Vector2(100, 0),
|
||||
);
|
||||
await game.ensureAdd(wall);
|
||||
game.contains(wall);
|
||||
|
||||
expect(wall.body.position, Vector2.zero());
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'is static',
|
||||
(game) async {
|
||||
final wall = Wall(
|
||||
start: Vector2.zero(),
|
||||
end: Vector2(100, 0),
|
||||
);
|
||||
await game.ensureAdd(wall);
|
||||
|
||||
expect(wall.body.bodyType, equals(BodyType.static));
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('fixture', () {
|
||||
flameTester.test(
|
||||
'exists',
|
||||
(game) async {
|
||||
final wall = Wall(
|
||||
start: Vector2.zero(),
|
||||
end: Vector2(100, 0),
|
||||
);
|
||||
await game.ensureAdd(wall);
|
||||
|
||||
expect(wall.body.fixtures[0], isA<Fixture>());
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'has restitution',
|
||||
(game) async {
|
||||
final wall = Wall(
|
||||
start: Vector2.zero(),
|
||||
end: Vector2(100, 0),
|
||||
);
|
||||
await game.ensureAdd(wall);
|
||||
|
||||
final fixture = wall.body.fixtures[0];
|
||||
expect(fixture.restitution, greaterThan(0));
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'has no friction',
|
||||
(game) async {
|
||||
final wall = Wall(
|
||||
start: Vector2.zero(),
|
||||
end: Vector2(100, 0),
|
||||
);
|
||||
await game.ensureAdd(wall);
|
||||
|
||||
final fixture = wall.body.fixtures[0];
|
||||
expect(fixture.friction, equals(0));
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group(
|
||||
'BottomWall',
|
||||
() {
|
||||
group('removes ball on contact', () {
|
||||
late GameBloc gameBloc;
|
||||
|
||||
setUp(() {
|
||||
gameBloc = GameBloc();
|
||||
});
|
||||
|
||||
final flameBlocTester = FlameBlocTester<PinballGame, GameBloc>(
|
||||
gameBuilder: EmptyPinballTestGame.new,
|
||||
blocBuilder: () => gameBloc,
|
||||
);
|
||||
|
||||
flameBlocTester.testGameWidget(
|
||||
'when ball is launch',
|
||||
setUp: (game, tester) async {
|
||||
final ball = ControlledBall.launch(
|
||||
characterTheme: game.characterTheme,
|
||||
);
|
||||
final wall = BottomWall();
|
||||
await game.ensureAddAll([ball, wall]);
|
||||
|
||||
beginContact(game, ball, wall);
|
||||
await game.ready();
|
||||
|
||||
expect(game.contains(ball), isFalse);
|
||||
},
|
||||
);
|
||||
|
||||
flameBlocTester.testGameWidget(
|
||||
'when ball is bonus',
|
||||
setUp: (game, tester) async {
|
||||
final ball = ControlledBall.bonus(
|
||||
characterTheme: game.characterTheme,
|
||||
);
|
||||
final wall = BottomWall();
|
||||
await game.ensureAddAll([ball, wall]);
|
||||
|
||||
beginContact(game, ball, wall);
|
||||
await game.ready();
|
||||
|
||||
expect(game.contains(ball), isFalse);
|
||||
},
|
||||
);
|
||||
|
||||
flameBlocTester.testGameWidget(
|
||||
'when ball is debug',
|
||||
setUp: (game, tester) async {
|
||||
final ball = ControlledBall.debug();
|
||||
final wall = BottomWall();
|
||||
await game.ensureAddAll([ball, wall]);
|
||||
|
||||
beginContact(game, ball, wall);
|
||||
await game.ready();
|
||||
|
||||
expect(game.contains(ball), isFalse);
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
Loading…
Reference in new issue