feat: kicker assets and dimension (#144)

* refactor: added kicker asset and fixed dimensions and sizes

* refactor: loadsprite for kicker

* test: added golden test for kicker

* feat: included Kicker sandbox

* refactor: analyzer fixes

Co-authored-by: alestiago <dev@alestiago.com>
pull/146/head
Rui Miguel Alonso 4 years ago committed by GitHub
parent d25643ce9a
commit 39b04c1393
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -83,8 +83,8 @@ class _BottomGroupSide extends Component {
final kicker = Kicker( final kicker = Kicker(
side: _side, side: _side,
)..initialPosition = Vector2( )..initialPosition = Vector2(
(22.0 * direction) + centerXAdjustment, (22.4 * direction) + centerXAdjustment,
-26, -25,
); );
await addAll([flipper, baseboard, kicker]); await addAll([flipper, baseboard, kicker]);

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@ -3,12 +3,16 @@
/// FlutterGen /// FlutterGen
/// ***************************************************** /// *****************************************************
// ignore_for_file: directives_ordering,unnecessary_import
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
class $AssetsImagesGen { class $AssetsImagesGen {
const $AssetsImagesGen(); const $AssetsImagesGen();
/// File path: assets/images/ball.png
AssetGenImage get ball => const AssetGenImage('assets/images/ball.png'); AssetGenImage get ball => const AssetGenImage('assets/images/ball.png');
$AssetsImagesBaseboardGen get baseboard => const $AssetsImagesBaseboardGen(); $AssetsImagesBaseboardGen get baseboard => const $AssetsImagesBaseboardGen();
$AssetsImagesBoundaryGen get boundary => const $AssetsImagesBoundaryGen(); $AssetsImagesBoundaryGen get boundary => const $AssetsImagesBoundaryGen();
$AssetsImagesChromeDinoGen get chromeDino => $AssetsImagesChromeDinoGen get chromeDino =>
@ -17,8 +21,12 @@ class $AssetsImagesGen {
const $AssetsImagesDashBumperGen(); const $AssetsImagesDashBumperGen();
$AssetsImagesDinoGen get dino => const $AssetsImagesDinoGen(); $AssetsImagesDinoGen get dino => const $AssetsImagesDinoGen();
$AssetsImagesFlipperGen get flipper => const $AssetsImagesFlipperGen(); $AssetsImagesFlipperGen get flipper => const $AssetsImagesFlipperGen();
/// File path: assets/images/flutter_sign_post.png
AssetGenImage get flutterSignPost => AssetGenImage get flutterSignPost =>
const AssetGenImage('assets/images/flutter_sign_post.png'); const AssetGenImage('assets/images/flutter_sign_post.png');
$AssetsImagesKickerGen get kicker => const $AssetsImagesKickerGen();
$AssetsImagesLaunchRampGen get launchRamp => $AssetsImagesLaunchRampGen get launchRamp =>
const $AssetsImagesLaunchRampGen(); const $AssetsImagesLaunchRampGen();
$AssetsImagesSpaceshipGen get spaceship => const $AssetsImagesSpaceshipGen(); $AssetsImagesSpaceshipGen get spaceship => const $AssetsImagesSpaceshipGen();
@ -27,8 +35,11 @@ class $AssetsImagesGen {
class $AssetsImagesBaseboardGen { class $AssetsImagesBaseboardGen {
const $AssetsImagesBaseboardGen(); const $AssetsImagesBaseboardGen();
/// File path: assets/images/baseboard/left.png
AssetGenImage get left => AssetGenImage get left =>
const AssetGenImage('assets/images/baseboard/left.png'); const AssetGenImage('assets/images/baseboard/left.png');
/// File path: assets/images/baseboard/right.png
AssetGenImage get right => AssetGenImage get right =>
const AssetGenImage('assets/images/baseboard/right.png'); const AssetGenImage('assets/images/baseboard/right.png');
} }
@ -36,8 +47,11 @@ class $AssetsImagesBaseboardGen {
class $AssetsImagesBoundaryGen { class $AssetsImagesBoundaryGen {
const $AssetsImagesBoundaryGen(); const $AssetsImagesBoundaryGen();
/// File path: assets/images/boundary/bottom.png
AssetGenImage get bottom => AssetGenImage get bottom =>
const AssetGenImage('assets/images/boundary/bottom.png'); const AssetGenImage('assets/images/boundary/bottom.png');
/// File path: assets/images/boundary/outer.png
AssetGenImage get outer => AssetGenImage get outer =>
const AssetGenImage('assets/images/boundary/outer.png'); const AssetGenImage('assets/images/boundary/outer.png');
} }
@ -45,8 +59,11 @@ class $AssetsImagesBoundaryGen {
class $AssetsImagesChromeDinoGen { class $AssetsImagesChromeDinoGen {
const $AssetsImagesChromeDinoGen(); const $AssetsImagesChromeDinoGen();
/// File path: assets/images/chrome_dino/head.png
AssetGenImage get head => AssetGenImage get head =>
const AssetGenImage('assets/images/chrome_dino/head.png'); const AssetGenImage('assets/images/chrome_dino/head.png');
/// File path: assets/images/chrome_dino/mouth.png
AssetGenImage get mouth => AssetGenImage get mouth =>
const AssetGenImage('assets/images/chrome_dino/mouth.png'); const AssetGenImage('assets/images/chrome_dino/mouth.png');
} }
@ -63,8 +80,11 @@ class $AssetsImagesDashBumperGen {
class $AssetsImagesDinoGen { class $AssetsImagesDinoGen {
const $AssetsImagesDinoGen(); const $AssetsImagesDinoGen();
/// File path: assets/images/dino/dino-land-bottom.png
AssetGenImage get dinoLandBottom => AssetGenImage get dinoLandBottom =>
const AssetGenImage('assets/images/dino/dino-land-bottom.png'); const AssetGenImage('assets/images/dino/dino-land-bottom.png');
/// File path: assets/images/dino/dino-land-top.png
AssetGenImage get dinoLandTop => AssetGenImage get dinoLandTop =>
const AssetGenImage('assets/images/dino/dino-land-top.png'); const AssetGenImage('assets/images/dino/dino-land-top.png');
} }
@ -72,17 +92,35 @@ class $AssetsImagesDinoGen {
class $AssetsImagesFlipperGen { class $AssetsImagesFlipperGen {
const $AssetsImagesFlipperGen(); const $AssetsImagesFlipperGen();
/// File path: assets/images/flipper/left.png
AssetGenImage get left => AssetGenImage get left =>
const AssetGenImage('assets/images/flipper/left.png'); const AssetGenImage('assets/images/flipper/left.png');
/// File path: assets/images/flipper/right.png
AssetGenImage get right => AssetGenImage get right =>
const AssetGenImage('assets/images/flipper/right.png'); const AssetGenImage('assets/images/flipper/right.png');
} }
class $AssetsImagesKickerGen {
const $AssetsImagesKickerGen();
/// File path: assets/images/kicker/left.png
AssetGenImage get left =>
const AssetGenImage('assets/images/kicker/left.png');
/// File path: assets/images/kicker/right.png
AssetGenImage get right =>
const AssetGenImage('assets/images/kicker/right.png');
}
class $AssetsImagesLaunchRampGen { class $AssetsImagesLaunchRampGen {
const $AssetsImagesLaunchRampGen(); const $AssetsImagesLaunchRampGen();
/// File path: assets/images/launch_ramp/foreground-railing.png
AssetGenImage get foregroundRailing => AssetGenImage get foregroundRailing =>
const AssetGenImage('assets/images/launch_ramp/foreground-railing.png'); const AssetGenImage('assets/images/launch_ramp/foreground-railing.png');
/// File path: assets/images/launch_ramp/ramp.png
AssetGenImage get ramp => AssetGenImage get ramp =>
const AssetGenImage('assets/images/launch_ramp/ramp.png'); const AssetGenImage('assets/images/launch_ramp/ramp.png');
} }
@ -90,12 +128,16 @@ class $AssetsImagesLaunchRampGen {
class $AssetsImagesSpaceshipGen { class $AssetsImagesSpaceshipGen {
const $AssetsImagesSpaceshipGen(); const $AssetsImagesSpaceshipGen();
/// File path: assets/images/spaceship/bridge.png
AssetGenImage get bridge => AssetGenImage get bridge =>
const AssetGenImage('assets/images/spaceship/bridge.png'); const AssetGenImage('assets/images/spaceship/bridge.png');
$AssetsImagesSpaceshipRailGen get rail => $AssetsImagesSpaceshipRailGen get rail =>
const $AssetsImagesSpaceshipRailGen(); const $AssetsImagesSpaceshipRailGen();
$AssetsImagesSpaceshipRampGen get ramp => $AssetsImagesSpaceshipRampGen get ramp =>
const $AssetsImagesSpaceshipRampGen(); const $AssetsImagesSpaceshipRampGen();
/// File path: assets/images/spaceship/saucer.png
AssetGenImage get saucer => AssetGenImage get saucer =>
const AssetGenImage('assets/images/spaceship/saucer.png'); const AssetGenImage('assets/images/spaceship/saucer.png');
} }
@ -103,8 +145,11 @@ class $AssetsImagesSpaceshipGen {
class $AssetsImagesDashBumperAGen { class $AssetsImagesDashBumperAGen {
const $AssetsImagesDashBumperAGen(); const $AssetsImagesDashBumperAGen();
/// File path: assets/images/dash_bumper/a/active.png
AssetGenImage get active => AssetGenImage get active =>
const AssetGenImage('assets/images/dash_bumper/a/active.png'); const AssetGenImage('assets/images/dash_bumper/a/active.png');
/// File path: assets/images/dash_bumper/a/inactive.png
AssetGenImage get inactive => AssetGenImage get inactive =>
const AssetGenImage('assets/images/dash_bumper/a/inactive.png'); const AssetGenImage('assets/images/dash_bumper/a/inactive.png');
} }
@ -112,8 +157,11 @@ class $AssetsImagesDashBumperAGen {
class $AssetsImagesDashBumperBGen { class $AssetsImagesDashBumperBGen {
const $AssetsImagesDashBumperBGen(); const $AssetsImagesDashBumperBGen();
/// File path: assets/images/dash_bumper/b/active.png
AssetGenImage get active => AssetGenImage get active =>
const AssetGenImage('assets/images/dash_bumper/b/active.png'); const AssetGenImage('assets/images/dash_bumper/b/active.png');
/// File path: assets/images/dash_bumper/b/inactive.png
AssetGenImage get inactive => AssetGenImage get inactive =>
const AssetGenImage('assets/images/dash_bumper/b/inactive.png'); const AssetGenImage('assets/images/dash_bumper/b/inactive.png');
} }
@ -121,8 +169,11 @@ class $AssetsImagesDashBumperBGen {
class $AssetsImagesDashBumperMainGen { class $AssetsImagesDashBumperMainGen {
const $AssetsImagesDashBumperMainGen(); const $AssetsImagesDashBumperMainGen();
/// File path: assets/images/dash_bumper/main/active.png
AssetGenImage get active => AssetGenImage get active =>
const AssetGenImage('assets/images/dash_bumper/main/active.png'); const AssetGenImage('assets/images/dash_bumper/main/active.png');
/// File path: assets/images/dash_bumper/main/inactive.png
AssetGenImage get inactive => AssetGenImage get inactive =>
const AssetGenImage('assets/images/dash_bumper/main/inactive.png'); const AssetGenImage('assets/images/dash_bumper/main/inactive.png');
} }
@ -130,8 +181,11 @@ class $AssetsImagesDashBumperMainGen {
class $AssetsImagesSpaceshipRailGen { class $AssetsImagesSpaceshipRailGen {
const $AssetsImagesSpaceshipRailGen(); const $AssetsImagesSpaceshipRailGen();
/// File path: assets/images/spaceship/rail/foreground.png
AssetGenImage get foreground => AssetGenImage get foreground =>
const AssetGenImage('assets/images/spaceship/rail/foreground.png'); const AssetGenImage('assets/images/spaceship/rail/foreground.png');
/// File path: assets/images/spaceship/rail/main.png
AssetGenImage get main => AssetGenImage get main =>
const AssetGenImage('assets/images/spaceship/rail/main.png'); const AssetGenImage('assets/images/spaceship/rail/main.png');
} }
@ -139,10 +193,15 @@ class $AssetsImagesSpaceshipRailGen {
class $AssetsImagesSpaceshipRampGen { class $AssetsImagesSpaceshipRampGen {
const $AssetsImagesSpaceshipRampGen(); const $AssetsImagesSpaceshipRampGen();
/// File path: assets/images/spaceship/ramp/main.png
AssetGenImage get main => AssetGenImage get main =>
const AssetGenImage('assets/images/spaceship/ramp/main.png'); const AssetGenImage('assets/images/spaceship/ramp/main.png');
/// File path: assets/images/spaceship/ramp/railing-background.png
AssetGenImage get railingBackground => const AssetGenImage( AssetGenImage get railingBackground => const AssetGenImage(
'assets/images/spaceship/ramp/railing-background.png'); 'assets/images/spaceship/ramp/railing-background.png');
/// File path: assets/images/spaceship/ramp/railing-foreground.png
AssetGenImage get railingForeground => const AssetGenImage( AssetGenImage get railingForeground => const AssetGenImage(
'assets/images/spaceship/ramp/railing-foreground.png'); 'assets/images/spaceship/ramp/railing-foreground.png');
} }

@ -1,10 +1,10 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flame/extensions.dart'; import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:geometry/geometry.dart' as geometry show centroid; import 'package:geometry/geometry.dart' as geometry show centroid;
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/gen/assets.gen.dart';
import 'package:pinball_components/pinball_components.dart' hide Assets;
/// {@template kicker} /// {@template kicker}
/// Triangular [BodyType.static] body that propels the [Ball] towards the /// Triangular [BodyType.static] body that propels the [Ball] towards the
@ -16,12 +16,7 @@ class Kicker extends BodyComponent with InitialPosition {
/// {@macro kicker} /// {@macro kicker}
Kicker({ Kicker({
required BoardSide side, required BoardSide side,
}) : _side = side { }) : _side = side;
// TODO(alestiago): Use sprite instead of color when provided.
paint = Paint()
..color = const Color(0xFF00FF00)
..style = PaintingStyle.fill;
}
/// Whether the [Kicker] is on the left or right side of the board. /// Whether the [Kicker] is on the left or right side of the board.
/// ///
@ -31,24 +26,22 @@ class Kicker extends BodyComponent with InitialPosition {
final BoardSide _side; final BoardSide _side;
/// The size of the [Kicker] body. /// The size of the [Kicker] body.
// TODO(alestiago): Use size from PositionedBodyComponent instead, static final Vector2 size = Vector2(4.4, 15);
// once a sprite is given.
static final Vector2 size = Vector2(4, 10);
List<FixtureDef> _createFixtureDefs() { List<FixtureDef> _createFixtureDefs() {
final fixturesDefs = <FixtureDef>[]; final fixturesDefs = <FixtureDef>[];
final direction = _side.direction; final direction = _side.direction;
const quarterPi = math.pi / 4; const quarterPi = math.pi / 4;
final upperCircle = CircleShape()..radius = 1.45; final upperCircle = CircleShape()..radius = 1.6;
upperCircle.position.setValues(0, -upperCircle.radius / 2); upperCircle.position.setValues(0, -upperCircle.radius / 2);
final upperCircleFixtureDef = FixtureDef(upperCircle)..friction = 0; final upperCircleFixtureDef = FixtureDef(upperCircle)..friction = 0;
fixturesDefs.add(upperCircleFixtureDef); fixturesDefs.add(upperCircleFixtureDef);
final lowerCircle = CircleShape()..radius = 1.45; final lowerCircle = CircleShape()..radius = 1.6;
lowerCircle.position.setValues( lowerCircle.position.setValues(
size.x * -direction, size.x * -direction,
-size.y, -size.y - 0.8,
); );
final lowerCircleFixtureDef = FixtureDef(lowerCircle)..friction = 0; final lowerCircleFixtureDef = FixtureDef(lowerCircle)..friction = 0;
fixturesDefs.add(lowerCircleFixtureDef); fixturesDefs.add(lowerCircleFixtureDef);
@ -60,8 +53,7 @@ class Kicker extends BodyComponent with InitialPosition {
upperCircle.radius * direction, upperCircle.radius * direction,
0, 0,
), ),
// TODO(alestiago): Use values from design. Vector2(2.5 * direction, -size.y + 2),
Vector2(2.0 * direction, -size.y + 2),
); );
final wallFacingLineFixtureDef = FixtureDef(wallFacingEdge)..friction = 0; final wallFacingLineFixtureDef = FixtureDef(wallFacingEdge)..friction = 0;
fixturesDefs.add(wallFacingLineFixtureDef); fixturesDefs.add(wallFacingLineFixtureDef);
@ -125,6 +117,27 @@ class Kicker extends BodyComponent with InitialPosition {
return body; return body;
} }
@override
Future<void> onLoad() async {
await super.onLoad();
renderBody = false;
final sprite = await gameRef.loadSprite(
(_side.isLeft)
? Assets.images.kicker.left.keyName
: Assets.images.kicker.right.keyName,
);
await add(
SpriteComponent(
sprite: sprite,
size: Vector2(8.7, 19),
anchor: Anchor.center,
position: Vector2(0.7 * -_side.direction, -2.2),
),
);
}
} }
// TODO(alestiago): Evaluate if there's value on generalising this to // TODO(alestiago): Evaluate if there's value on generalising this to

@ -38,6 +38,7 @@ flutter:
- assets/images/spaceship/rail/ - assets/images/spaceship/rail/
- assets/images/spaceship/ramp/ - assets/images/spaceship/ramp/
- assets/images/chrome_dino/ - assets/images/chrome_dino/
- assets/images/kicker/
flutter_gen: flutter_gen:
line_length: 80 line_length: 80

@ -6,6 +6,7 @@
// https://opensource.org/licenses/MIT. // https://opensource.org/licenses/MIT.
import 'package:dashbook/dashbook.dart'; import 'package:dashbook/dashbook.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:sandbox/stories/kicker/stories.dart';
import 'package:sandbox/stories/stories.dart'; import 'package:sandbox/stories/stories.dart';
void main() { void main() {
@ -19,5 +20,6 @@ void main() {
addBaseboardStories(dashbook); addBaseboardStories(dashbook);
addChromeDinoStories(dashbook); addChromeDinoStories(dashbook);
addDashNestBumperStories(dashbook); addDashNestBumperStories(dashbook);
addKickerStories(dashbook);
runApp(dashbook); runApp(dashbook);
} }

@ -0,0 +1,39 @@
import 'package:flame/extensions.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:sandbox/common/common.dart';
import 'package:sandbox/stories/ball/basic_ball_game.dart';
class KickerGame extends BasicBallGame {
KickerGame({
required this.trace,
}) : super(color: const Color(0xFFFF0000));
static const info = '''
Shows how Kickers are rendered.
- Activate the "trace" parameter to overlay the body.
- Tap anywhere on the screen to spawn a ball into the game.
''';
final bool trace;
@override
Future<void> onLoad() async {
await super.onLoad();
final center = screenToWorld(camera.viewport.canvasSize! / 2);
final leftKicker = Kicker(side: BoardSide.left)
..initialPosition = Vector2(center.x - (Kicker.size.x * 2), center.y);
await add(leftKicker);
final rightKicker = Kicker(side: BoardSide.right)
..initialPosition = Vector2(center.x + (Kicker.size.x * 2), center.y);
await add(rightKicker);
if (trace) {
leftKicker.trace();
rightKicker.trace();
}
}
}

@ -0,0 +1,17 @@
import 'package:dashbook/dashbook.dart';
import 'package:flame/game.dart';
import 'package:sandbox/common/common.dart';
import 'package:sandbox/stories/kicker/kicker_game.dart';
void addKickerStories(Dashbook dashbook) {
dashbook.storiesOf('Kickers').add(
'Basic',
(context) => GameWidget(
game: KickerGame(
trace: context.boolProperty('Trace', true),
),
),
codeLink: buildSourceLink('kicker_game/basic.dart'),
info: KickerGame.info,
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

@ -5,10 +5,34 @@ import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart';
void main() { void main() {
group('Kicker', () { group('Kicker', () {
// TODO(alestiago): Include golden tests for left and right. final flameTester = FlameTester(TestGame.new);
final flameTester = FlameTester(Forge2DGame.new);
flameTester.testGameWidget(
'renders correctly',
setUp: (game, tester) async {
final leftKicker = Kicker(
side: BoardSide.left,
)..initialPosition = Vector2(-20, 0);
final rightKicker = Kicker(
side: BoardSide.right,
)..initialPosition = Vector2(20, 0);
await game.addAll([leftKicker, rightKicker]);
await game.ready();
game.camera.followVector2(Vector2.zero());
},
// TODO(ruimiguel): enable test when workflows are fixed.
//verify: (game, tester) async {
// await expectLater(
// find.byGame<Forge2DGame>(),
// matchesGoldenFile('golden/kickers.png'),
// );
//},
);
flameTester.test( flameTester.test(
'loads correctly', 'loads correctly',

Loading…
Cancel
Save