Merge branch 'main' into feat/leaderboard_screen

pull/51/head
RuiAlonso 4 years ago
commit 424921415e

@ -8,3 +8,4 @@ jobs:
with:
flutter_channel: stable
flutter_version: 2.10.0
coverage_excludes: "lib/gen/*.dart"

@ -1 +1,4 @@
include: package:very_good_analysis/analysis_options.2.4.0.yaml
analyzer:
exclude:
- lib/**/*.gen.dart

@ -1,6 +1,7 @@
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/gen/assets.gen.dart';
/// {@template ball}
/// A solid, [BodyType.dynamic] sphere that rolls and bounces along the
@ -20,15 +21,10 @@ class Ball extends BodyComponent<PinballGame> with InitialPosition, Layered {
/// The size of the [Ball]
final Vector2 size = Vector2.all(2);
/// Asset location of the sprite that renders with the [Ball].
///
/// Sprite is preloaded by [PinballGameAssetsX].
static const spritePath = 'components/ball.png';
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(spritePath);
final sprite = await gameRef.loadSprite(Assets.images.components.ball.path);
final tint = gameRef.theme.characterTheme.ballColor.withOpacity(0.5);
await add(
SpriteComponent(

@ -7,25 +7,23 @@ import 'package:pinball/game/game.dart';
/// {entemplate}
class Board extends Component {
/// {@macro board}
Board({required Vector2 size}) : _size = size;
final Vector2 _size;
Board();
@override
Future<void> onLoad() async {
// TODO(alestiago): adjust positioning once sprites are added.
final bottomGroup = _BottomGroup(
position: Vector2(
_size.x / 2,
_size.y / 1.25,
PinballGame.boardBounds.center.dx,
PinballGame.boardBounds.bottom + 10,
),
spacing: 2,
);
final dashForest = _FlutterForest(
position: Vector2(
_size.x / 1.25,
_size.y / 4.25,
PinballGame.boardBounds.center.dx + 20,
PinballGame.boardBounds.center.dy + 48,
),
);

@ -36,31 +36,39 @@ class BonusWord extends Component with BlocComponent<GameBloc, GameState> {
for (var i = 0; i < letters.length; i++) {
final letter = letters[i];
letter.add(
SequenceEffect(
[
ColorEffect(
i.isOdd ? BonusLetter._activeColor : BonusLetter._disableColor,
const Offset(0, 1),
EffectController(duration: 0.25),
),
ColorEffect(
i.isOdd ? BonusLetter._disableColor : BonusLetter._activeColor,
const Offset(0, 1),
EffectController(duration: 0.25),
),
],
repeatCount: 4,
)..onFinishCallback = () {
letter.add(
letter
..isEnabled = false
..add(
SequenceEffect(
[
ColorEffect(
BonusLetter._disableColor,
i.isOdd
? BonusLetter._activeColor
: BonusLetter._disableColor,
const Offset(0, 1),
EffectController(duration: 0.25),
),
);
},
);
ColorEffect(
i.isOdd
? BonusLetter._disableColor
: BonusLetter._activeColor,
const Offset(0, 1),
EffectController(duration: 0.25),
),
],
repeatCount: 4,
)..onFinishCallback = () {
letter
..isEnabled = true
..add(
ColorEffect(
BonusLetter._disableColor,
const Offset(0, 1),
EffectController(duration: 0.25),
),
);
},
);
}
}
}
@ -107,6 +115,13 @@ class BonusLetter extends BodyComponent<PinballGame>
final String _letter;
final int _index;
/// Indicates if a [BonusLetter] can be activated on [Ball] contact.
///
/// It is disabled whilst animating and enabled again once the animation
/// completes. The animation is triggered when [GameBonus.word] is
/// awarded.
bool isEnabled = true;
@override
Future<void> onLoad() async {
await super.onLoad();
@ -172,6 +187,8 @@ class BonusLetterBallContactCallback
extends ContactCallback<Ball, BonusLetter> {
@override
void begin(Ball ball, BonusLetter bonusLetter, Contact contact) {
bonusLetter.activate();
if (bonusLetter.isEnabled) {
bonusLetter.activate();
}
}
}

@ -2,11 +2,11 @@ import 'dart:async';
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame/input.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/gen/assets.gen.dart';
/// {@template flipper}
/// A bat, typically found in pairs at the bottom of the board.
@ -53,11 +53,6 @@ class Flipper extends BodyComponent with KeyboardHandler, InitialPosition {
}
}
/// Asset location of the sprite that renders with the [Flipper].
///
/// Sprite is preloaded by [PinballGameAssetsX].
static const spritePath = 'components/flipper.png';
/// The size of the [Flipper].
static final size = Vector2(12, 2.8);
@ -91,7 +86,9 @@ class Flipper extends BodyComponent with KeyboardHandler, InitialPosition {
/// Loads the sprite that renders with the [Flipper].
Future<void> _loadSprite() async {
final sprite = await gameRef.loadSprite(spritePath);
final sprite = await gameRef.loadSprite(
Assets.images.components.flipper.path,
);
final spriteComponent = SpriteComponent(
sprite: sprite,
size: size,

@ -30,18 +30,23 @@ class JetpackRamp extends Component with HasGameRef<PinballGame> {
// TODO(ruialonso): Use a bezier curve once control points are defined.
color: const Color.fromARGB(255, 8, 218, 241),
center: position,
width: 62,
radius: 200,
width: 5,
radius: 18,
angle: math.pi,
rotation: math.pi,
)..layer = layer;
final leftOpening = _JetpackRampOpening(
outsideLayer: Layer.spaceship,
rotation: math.pi,
)
..initialPosition = position
..layer = layer;
final leftOpening = _JetpackRampOpening(outsideLayer: Layer.spaceship)
..initialPosition = position + Vector2(-27.6, 25.3)
..initialPosition = position + Vector2(-2.5, -20.2)
..layer = Layer.jetpack;
final rightOpening = _JetpackRampOpening()
..initialPosition = position + Vector2(-10.6, 25.3)
final rightOpening = _JetpackRampOpening(
rotation: math.pi,
)
..initialPosition = position + Vector2(12.9, -20.2)
..layer = Layer.opening;
await addAll([
@ -60,20 +65,26 @@ class _JetpackRampOpening extends RampOpening {
/// {@macro jetpack_ramp_opening}
_JetpackRampOpening({
Layer? outsideLayer,
}) : super(
required double rotation,
}) : _rotation = rotation,
super(
pathwayLayer: Layer.jetpack,
outsideLayer: outsideLayer,
orientation: RampOrientation.down,
);
// TODO(ruialonso): Avoid magic number 2, should be proportional to
final double _rotation;
// TODO(ruialonso): Avoid magic number 3, should be propotional to
// [JetpackRamp].
static const _size = 2;
static final Vector2 _size = Vector2(3, .1);
@override
Shape get shape => PolygonShape()
..setAsEdge(
Vector2(initialPosition.x - _size, initialPosition.y),
Vector2(initialPosition.x + _size, initialPosition.y),
..setAsBox(
_size.x,
_size.y,
initialPosition,
_rotation,
);
}

@ -26,28 +26,33 @@ class LauncherRamp extends Component with HasGameRef<PinballGame> {
RampOpeningBallContactCallback<_LauncherRampOpening>(),
);
final launcherRampRotation =
-math.atan(18.6 / PinballGame.boardBounds.height);
final straightPath = Pathway.straight(
color: const Color.fromARGB(255, 34, 255, 0),
start: Vector2(0, 0),
end: Vector2(0, 700),
width: 80,
start: position + Vector2(-1.2, 10),
end: position + Vector2(-1.2, 117),
width: 5,
rotation: launcherRampRotation,
)
..initialPosition = position
..layer = layer;
final curvedPath = Pathway.arc(
color: const Color.fromARGB(255, 251, 255, 0),
center: position + Vector2(-29, -8),
radius: 300,
angle: 10 * math.pi / 9,
width: 80,
)
..initialPosition = position + Vector2(-28.8, -6)
..layer = layer;
final leftOpening = _LauncherRampOpening(rotation: 13 * math.pi / 180)
..initialPosition = position + Vector2(-72.5, 12)
center: position + Vector2(-2.8, 87.2),
radius: 16.3,
angle: math.pi / 2,
width: 5,
rotation: 3 * math.pi / 2,
)..layer = layer;
final leftOpening = _LauncherRampOpening(rotation: math.pi / 2)
..initialPosition = position + Vector2(-11.8, 66.3)
..layer = Layer.opening;
final rightOpening = _LauncherRampOpening(rotation: 0)
..initialPosition = position + Vector2(-46.8, 17)
..initialPosition = position + Vector2(-4.9, 59.4)
..layer = Layer.opening;
await addAll([

@ -150,10 +150,7 @@ class Pathway extends BodyComponent with InitialPosition, Layered {
final fixturesDef = <FixtureDef>[];
for (final path in _paths) {
final chain = ChainShape()
..createChain(
path.map(gameRef.screenToWorld).toList(),
);
final chain = ChainShape()..createChain(path);
fixturesDef.add(FixtureDef(chain));
}

@ -1,4 +1,4 @@
import 'package:flame/input.dart';
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/services.dart';
import 'package:pinball/game/game.dart';

@ -7,6 +7,7 @@ import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/flame/blueprint.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/gen/assets.gen.dart';
/// A [Blueprint] which creates the spaceship feature.
class Spaceship extends Forge2DBlueprint {
@ -15,7 +16,10 @@ class Spaceship extends Forge2DBlueprint {
@override
void build() {
final position = Vector2(30, -50);
final position = Vector2(
PinballGame.boardBounds.left + radius + 15,
PinballGame.boardBounds.center.dy + 30,
);
addAllContactCallback([
SpaceshipHoleBallContactCallback(),
@ -43,18 +47,12 @@ class SpaceshipSaucer extends BodyComponent with InitialPosition, Layered {
layer = Layer.spaceship;
}
/// Path for the base sprite
static const saucerSpritePath = 'components/spaceship/saucer.png';
/// Path for the upper wall sprite
static const upperWallPath = 'components/spaceship/upper.png';
@override
Future<void> onLoad() async {
await super.onLoad();
final sprites = await Future.wait([
gameRef.loadSprite(saucerSpritePath),
gameRef.loadSprite(upperWallPath),
gameRef.loadSprite(Assets.images.components.spaceship.saucer.path),
gameRef.loadSprite(Assets.images.components.spaceship.upper.path),
]);
await add(
@ -101,14 +99,13 @@ class SpaceshipBridgeTop extends BodyComponent with InitialPosition {
/// {@macro spaceship_bridge_top}
SpaceshipBridgeTop() : super(priority: 6);
/// Path to the top of this sprite
static const spritePath = 'components/spaceship/android-top.png';
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(spritePath);
final sprite = await gameRef.loadSprite(
Assets.images.components.spaceship.androidTop.path,
);
await add(
SpriteComponent(
sprite: sprite,
@ -139,16 +136,15 @@ class SpaceshipBridge extends BodyComponent with InitialPosition, Layered {
layer = Layer.spaceship;
}
/// Path to the spaceship bridge
static const spritePath = 'components/spaceship/android-bottom.png';
@override
Future<void> onLoad() async {
await super.onLoad();
renderBody = false;
final sprite = await gameRef.images.load(spritePath);
final sprite = await gameRef.images.load(
Assets.images.components.spaceship.androidBottom.path,
);
await add(
SpriteAnimationComponent.fromFrameData(
sprite,
@ -250,14 +246,13 @@ class SpaceshipWall extends BodyComponent with InitialPosition, Layered {
layer = Layer.spaceship;
}
/// Sprite path for the lower wall
static const lowerWallPath = 'components/spaceship/lower.png';
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(lowerWallPath);
final sprite = await gameRef.loadSprite(
Assets.images.components.spaceship.lower.path,
);
await add(
SpriteComponent(

@ -1,7 +1,9 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'package:flame/extensions.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/components/components.dart';
import 'package:pinball/game/pinball_game.dart';
/// {@template wall}
/// A continuous generic and [BodyType.static] barrier that divides a game area.
@ -39,15 +41,18 @@ class Wall extends BodyComponent {
/// Create top, left, and right [Wall]s for the game board.
List<Wall> createBoundaries(Forge2DGame game) {
final topLeft = Vector2.zero();
final bottomRight = game.screenToWorld(game.camera.viewport.effectiveSize);
final topRight = Vector2(bottomRight.x, topLeft.y);
final bottomLeft = Vector2(topLeft.x, bottomRight.y);
final topLeft =
PinballGame.boardBounds.topLeft.toVector2() + Vector2(18.6, 0);
final bottomRight = PinballGame.boardBounds.bottomRight.toVector2();
final topRight =
PinballGame.boardBounds.topRight.toVector2() - Vector2(18.6, 0);
final bottomLeft = PinballGame.boardBounds.bottomLeft.toVector2();
return [
Wall(start: topLeft, end: topRight),
Wall(start: topRight, end: bottomRight),
Wall(start: bottomLeft, end: topLeft),
Wall(start: topLeft, end: bottomLeft),
];
}
@ -59,13 +64,10 @@ List<Wall> createBoundaries(Forge2DGame game) {
/// {@endtemplate}
class BottomWall extends Wall {
/// {@macro bottom_wall}
BottomWall(Forge2DGame game)
BottomWall()
: super(
start: game.screenToWorld(game.camera.viewport.effectiveSize),
end: Vector2(
0,
game.screenToWorld(game.camera.viewport.effectiveSize).y,
),
start: PinballGame.boardBounds.bottomLeft.toVector2(),
end: PinballGame.boardBounds.bottomRight.toVector2(),
);
}

@ -1,16 +1,17 @@
import 'package:pinball/game/game.dart';
import 'package:pinball/gen/assets.gen.dart';
/// Add methods to help loading and caching game assets.
extension PinballGameAssetsX on PinballGame {
/// Pre load the initial assets of the game.
Future<void> preLoadAssets() async {
await Future.wait([
images.load(Ball.spritePath),
images.load(Flipper.spritePath),
images.load(SpaceshipBridge.spritePath),
images.load(SpaceshipBridgeTop.spritePath),
images.load(SpaceshipWall.lowerWallPath),
images.load(SpaceshipSaucer.upperWallPath),
images.load(Assets.images.components.ball.path),
images.load(Assets.images.components.flipper.path),
images.load(Assets.images.components.spaceship.androidTop.path),
images.load(Assets.images.components.spaceship.androidBottom.path),
images.load(Assets.images.components.spaceship.lower.path),
images.load(Assets.images.components.spaceship.upper.path),
]);
}
}

@ -1,6 +1,7 @@
// ignore_for_file: public_member_api_docs
import 'dart:async';
import 'package:flame/extensions.dart';
import 'package:flame/input.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
@ -10,12 +11,21 @@ import 'package:pinball_theme/pinball_theme.dart';
class PinballGame extends Forge2DGame
with FlameBloc, HasKeyboardHandlerComponents {
PinballGame({required this.theme});
PinballGame({required this.theme}) {
images.prefix = '';
}
final PinballTheme theme;
late final Plunger plunger;
static final boardSize = Vector2(101.6, 143.8);
static final boardBounds = Rect.fromCenter(
center: Offset.zero,
width: boardSize.x,
height: -boardSize.y,
);
@override
void onAttach() {
super.onAttach();
@ -27,11 +37,16 @@ class PinballGame extends Forge2DGame
_addContactCallbacks();
await _addGameBoundaries();
unawaited(_addBoard());
unawaited(add(Board()));
unawaited(_addPlunger());
unawaited(_addBonusWord());
unawaited(_addPaths());
unawaited(addFromBlueprint(Spaceship()));
// Fix camera on the center of the board.
camera
..followVector2(Vector2.zero())
..zoom = size.y / 16;
}
void _addContactCallbacks() {
@ -41,44 +56,27 @@ class PinballGame extends Forge2DGame
}
Future<void> _addGameBoundaries() async {
await add(BottomWall(this));
await add(BottomWall());
createBoundaries(this).forEach(add);
}
Future<void> _addBoard() async {
final board = Board(
size: screenToWorld(
Vector2(
camera.viewport.effectiveSize.x,
camera.viewport.effectiveSize.y,
),
),
);
await add(board);
}
Future<void> _addPlunger() async {
plunger = Plunger(
compressionDistance: camera.viewport.effectiveSize.y / 12,
);
plunger.initialPosition = screenToWorld(
Vector2(
camera.viewport.effectiveSize.x / 2 + 450,
camera.viewport.effectiveSize.y - plunger.compressionDistance,
),
);
plunger = Plunger(compressionDistance: 2);
plunger.initialPosition = boardBounds.bottomRight.toVector2() +
Vector2(
-5,
10,
);
await add(plunger);
}
Future<void> _addBonusWord() async {
await add(
BonusWord(
position: screenToWorld(
Vector2(
camera.viewport.effectiveSize.x / 2,
camera.viewport.effectiveSize.y - 50,
),
position: Vector2(
boardBounds.center.dx,
boardBounds.bottom + 10,
),
),
);
@ -86,18 +84,22 @@ class PinballGame extends Forge2DGame
Future<void> _addPaths() async {
final jetpackRamp = JetpackRamp(
position: Vector2(42.6, -45),
position: Vector2(
PinballGame.boardBounds.left + 40.5,
PinballGame.boardBounds.top - 31.5,
),
);
final launcherRamp = LauncherRamp(
position: screenToWorld(
Vector2(
camera.viewport.effectiveSize.x / 2 + 400,
camera.viewport.effectiveSize.y / 2 - 330,
),
position: Vector2(
PinballGame.boardBounds.right - 30,
PinballGame.boardBounds.bottom + 40,
),
);
await addAll([jetpackRamp, launcherRamp]);
await addAll([
jetpackRamp,
launcherRamp,
]);
}
void spawnBall() {

@ -0,0 +1,96 @@
/// GENERATED CODE - DO NOT MODIFY BY HAND
/// *****************************************************
/// FlutterGen
/// *****************************************************
import 'package:flutter/widgets.dart';
class $AssetsImagesGen {
const $AssetsImagesGen();
$AssetsImagesComponentsGen get components =>
const $AssetsImagesComponentsGen();
}
class $AssetsImagesComponentsGen {
const $AssetsImagesComponentsGen();
AssetGenImage get ball =>
const AssetGenImage('assets/images/components/ball.png');
AssetGenImage get flipper =>
const AssetGenImage('assets/images/components/flipper.png');
AssetGenImage get sauce =>
const AssetGenImage('assets/images/components/sauce.png');
$AssetsImagesComponentsSpaceshipGen get spaceship =>
const $AssetsImagesComponentsSpaceshipGen();
}
class $AssetsImagesComponentsSpaceshipGen {
const $AssetsImagesComponentsSpaceshipGen();
AssetGenImage get androidBottom => const AssetGenImage(
'assets/images/components/spaceship/android-bottom.png');
AssetGenImage get androidTop =>
const AssetGenImage('assets/images/components/spaceship/android-top.png');
AssetGenImage get lower =>
const AssetGenImage('assets/images/components/spaceship/lower.png');
AssetGenImage get saucer =>
const AssetGenImage('assets/images/components/spaceship/saucer.png');
AssetGenImage get upper =>
const AssetGenImage('assets/images/components/spaceship/upper.png');
}
class Assets {
Assets._();
static const $AssetsImagesGen images = $AssetsImagesGen();
}
class AssetGenImage extends AssetImage {
const AssetGenImage(String assetName) : super(assetName);
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;
}

@ -182,21 +182,21 @@ packages:
name: flame
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-releasecandidate.5"
version: "1.1.0-releasecandidate.6"
flame_bloc:
dependency: "direct main"
description:
name: flame_bloc
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0-releasecandidate.5"
version: "1.2.0-releasecandidate.6"
flame_forge2d:
dependency: "direct main"
description:
name: flame_forge2d
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0-releasecandidate.5"
version: "0.9.0-releasecandidate.6"
flame_test:
dependency: "direct dev"
description:
@ -237,7 +237,7 @@ packages:
name: forge2d
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.2"
version: "0.9.0"
frontend_server_client:
dependency: transitive
description:

@ -10,9 +10,9 @@ dependencies:
bloc: ^8.0.2
cloud_firestore: ^3.1.10
equatable: ^2.0.3
flame: ^1.1.0-releasecandidate.5
flame_bloc: ^1.2.0-releasecandidate.5
flame_forge2d: ^0.9.0-releasecandidate.5
flame: ^1.1.0-releasecandidate.6
flame_bloc: ^1.2.0-releasecandidate.6
flame_forge2d: ^0.9.0-releasecandidate.6
flutter:
sdk: flutter
flutter_bloc: ^8.0.1
@ -42,3 +42,6 @@ flutter:
assets:
- assets/images/components/
- assets/images/components/spaceship/
flutter_gen:
line_length: 80

@ -1,6 +1,5 @@
// 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';
@ -9,13 +8,13 @@ import '../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(Forge2DGame.new);
final flameTester = FlameTester(PinballGameTest.create);
group('Board', () {
flameTester.test(
'loads correctly',
(game) async {
final board = Board(size: Vector2.all(500));
final board = Board();
await game.ready();
await game.ensureAdd(board);
@ -27,7 +26,7 @@ void main() {
flameTester.test(
'has one left flipper',
(game) async {
final board = Board(size: Vector2.all(500));
final board = Board();
await game.ready();
await game.ensureAdd(board);
@ -41,7 +40,7 @@ void main() {
flameTester.test(
'has one right flipper',
(game) async {
final board = Board(size: Vector2.all(500));
final board = Board();
await game.ready();
await game.ensureAdd(board);
@ -55,7 +54,7 @@ void main() {
flameTester.test(
'has two Baseboards',
(game) async {
final board = Board(size: Vector2.all(500));
final board = Board();
await game.ready();
await game.ensureAdd(board);
@ -67,7 +66,7 @@ void main() {
flameTester.test(
'has two Kickers',
(game) async {
final board = Board(size: Vector2.all(500));
final board = Board();
await game.ready();
await game.ensureAdd(board);
@ -80,7 +79,7 @@ void main() {
'has three RoundBumpers',
(game) async {
// TODO(alestiago): change to [NestBumpers] once provided.
final board = Board(size: Vector2.all(500));
final board = Board();
await game.ready();
await game.ensureAdd(board);

@ -300,12 +300,26 @@ void main() {
test('calls ball.activate', () {
final ball = MockBall();
final bonusLetter = MockBonusLetter();
final contactCallback = BonusLetterBallContactCallback();
when(() => bonusLetter.isEnabled).thenReturn(true);
contactCallback.begin(ball, bonusLetter, MockContact());
verify(bonusLetter.activate).called(1);
});
test("doesn't call ball.activate when letter is disabled", () {
final ball = MockBall();
final bonusLetter = MockBonusLetter();
final contactCallback = BonusLetterBallContactCallback();
when(() => bonusLetter.isEnabled).thenReturn(false);
contactCallback.begin(ball, bonusLetter, MockContact());
verifyNever(bonusLetter.activate);
});
});
});
}

@ -9,7 +9,7 @@ extension PinballGameTest on PinballGame {
theme: const PinballTheme(
characterTheme: DashTheme(),
),
);
)..images.prefix = '';
}
/// [DebugPinballGame] extension to reduce boilerplate in tests.

Loading…
Cancel
Save