feat: implements `GoogleLetter` (#172)

* feat: implementing GoogleLetter

* feat: implemented GoogleLetterGame

* feat: included temp assets

* feat: exported google_letter

* feat: defined GoogleLetterActivationEffect

* feat: included story

* feat: included activate and deactivate tests

* refactor: simplified GoogleLetter

* refactor: updated constructor

* refactor: removed condition

* feat: included GoogleLetterOrder

* feat: updated constructor

* refactor: removed extension for index

* refactor: removed unnecessary async

Co-authored-by: Erick <erickzanardoo@gmail.com>

* refactor: removed unnecessary async

Co-authored-by: Erick <erickzanardoo@gmail.com>

* Update packages/pinball_components/lib/src/components/google_letter.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* refactor: changed method typo

Co-authored-by: Erick <erickzanardoo@gmail.com>
Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>
pull/177/head
Alejandro Santiago 3 years ago committed by GitHub
parent 1fd6d9bf46
commit baf06ca737
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

@ -3,13 +3,18 @@
/// FlutterGen
/// *****************************************************
// ignore_for_file: directives_ordering,unnecessary_import
import 'package:flutter/widgets.dart';
class $AssetsImagesGen {
const $AssetsImagesGen();
$AssetsImagesBackboardGen get backboard => const $AssetsImagesBackboardGen();
/// File path: assets/images/ball.png
AssetGenImage get ball => const AssetGenImage('assets/images/ball.png');
$AssetsImagesBaseboardGen get baseboard => const $AssetsImagesBaseboardGen();
$AssetsImagesBoundaryGen get boundary => const $AssetsImagesBoundaryGen();
$AssetsImagesChromeDinoGen get chromeDino =>
@ -18,8 +23,13 @@ class $AssetsImagesGen {
const $AssetsImagesDashBumperGen();
$AssetsImagesDinoGen get dino => const $AssetsImagesDinoGen();
$AssetsImagesFlipperGen get flipper => const $AssetsImagesFlipperGen();
/// File path: assets/images/flutter_sign_post.png
AssetGenImage get flutterSignPost =>
const AssetGenImage('assets/images/flutter_sign_post.png');
$AssetsImagesGoogleWordGen get googleWord =>
const $AssetsImagesGoogleWordGen();
$AssetsImagesKickerGen get kicker => const $AssetsImagesKickerGen();
$AssetsImagesLaunchRampGen get launchRamp =>
const $AssetsImagesLaunchRampGen();
@ -31,8 +41,11 @@ class $AssetsImagesGen {
class $AssetsImagesBackboardGen {
const $AssetsImagesBackboardGen();
/// File path: assets/images/backboard/backboard_game_over.png
AssetGenImage get backboardGameOver =>
const AssetGenImage('assets/images/backboard/backboard_game_over.png');
/// File path: assets/images/backboard/backboard_scores.png
AssetGenImage get backboardScores =>
const AssetGenImage('assets/images/backboard/backboard_scores.png');
}
@ -40,8 +53,11 @@ class $AssetsImagesBackboardGen {
class $AssetsImagesBaseboardGen {
const $AssetsImagesBaseboardGen();
/// File path: assets/images/baseboard/left.png
AssetGenImage get left =>
const AssetGenImage('assets/images/baseboard/left.png');
/// File path: assets/images/baseboard/right.png
AssetGenImage get right =>
const AssetGenImage('assets/images/baseboard/right.png');
}
@ -49,8 +65,11 @@ class $AssetsImagesBaseboardGen {
class $AssetsImagesBoundaryGen {
const $AssetsImagesBoundaryGen();
/// File path: assets/images/boundary/bottom.png
AssetGenImage get bottom =>
const AssetGenImage('assets/images/boundary/bottom.png');
/// File path: assets/images/boundary/outer.png
AssetGenImage get outer =>
const AssetGenImage('assets/images/boundary/outer.png');
}
@ -58,8 +77,11 @@ class $AssetsImagesBoundaryGen {
class $AssetsImagesChromeDinoGen {
const $AssetsImagesChromeDinoGen();
/// File path: assets/images/chrome_dino/head.png
AssetGenImage get head =>
const AssetGenImage('assets/images/chrome_dino/head.png');
/// File path: assets/images/chrome_dino/mouth.png
AssetGenImage get mouth =>
const AssetGenImage('assets/images/chrome_dino/mouth.png');
}
@ -76,8 +98,11 @@ class $AssetsImagesDashBumperGen {
class $AssetsImagesDinoGen {
const $AssetsImagesDinoGen();
/// File path: assets/images/dino/dino-land-bottom.png
AssetGenImage get dinoLandBottom =>
const AssetGenImage('assets/images/dino/dino-land-bottom.png');
/// File path: assets/images/dino/dino-land-top.png
AssetGenImage get dinoLandTop =>
const AssetGenImage('assets/images/dino/dino-land-top.png');
}
@ -85,17 +110,51 @@ class $AssetsImagesDinoGen {
class $AssetsImagesFlipperGen {
const $AssetsImagesFlipperGen();
/// File path: assets/images/flipper/left.png
AssetGenImage get left =>
const AssetGenImage('assets/images/flipper/left.png');
/// File path: assets/images/flipper/right.png
AssetGenImage get right =>
const AssetGenImage('assets/images/flipper/right.png');
}
class $AssetsImagesGoogleWordGen {
const $AssetsImagesGoogleWordGen();
/// File path: assets/images/google_word/letter1.png
AssetGenImage get letter1 =>
const AssetGenImage('assets/images/google_word/letter1.png');
/// File path: assets/images/google_word/letter2.png
AssetGenImage get letter2 =>
const AssetGenImage('assets/images/google_word/letter2.png');
/// File path: assets/images/google_word/letter3.png
AssetGenImage get letter3 =>
const AssetGenImage('assets/images/google_word/letter3.png');
/// File path: assets/images/google_word/letter4.png
AssetGenImage get letter4 =>
const AssetGenImage('assets/images/google_word/letter4.png');
/// File path: assets/images/google_word/letter5.png
AssetGenImage get letter5 =>
const AssetGenImage('assets/images/google_word/letter5.png');
/// File path: assets/images/google_word/letter6.png
AssetGenImage get letter6 =>
const AssetGenImage('assets/images/google_word/letter6.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');
}
@ -103,8 +162,11 @@ class $AssetsImagesKickerGen {
class $AssetsImagesLaunchRampGen {
const $AssetsImagesLaunchRampGen();
/// File path: assets/images/launch_ramp/foreground-railing.png
AssetGenImage get foregroundRailing =>
const AssetGenImage('assets/images/launch_ramp/foreground-railing.png');
/// File path: assets/images/launch_ramp/ramp.png
AssetGenImage get ramp =>
const AssetGenImage('assets/images/launch_ramp/ramp.png');
}
@ -112,12 +174,19 @@ class $AssetsImagesLaunchRampGen {
class $AssetsImagesSlingshotGen {
const $AssetsImagesSlingshotGen();
/// File path: assets/images/slingshot/left_lower.png
AssetGenImage get leftLower =>
const AssetGenImage('assets/images/slingshot/left_lower.png');
/// File path: assets/images/slingshot/left_upper.png
AssetGenImage get leftUpper =>
const AssetGenImage('assets/images/slingshot/left_upper.png');
/// File path: assets/images/slingshot/right_lower.png
AssetGenImage get rightLower =>
const AssetGenImage('assets/images/slingshot/right_lower.png');
/// File path: assets/images/slingshot/right_upper.png
AssetGenImage get rightUpper =>
const AssetGenImage('assets/images/slingshot/right_upper.png');
}
@ -125,12 +194,16 @@ class $AssetsImagesSlingshotGen {
class $AssetsImagesSpaceshipGen {
const $AssetsImagesSpaceshipGen();
/// File path: assets/images/spaceship/bridge.png
AssetGenImage get bridge =>
const AssetGenImage('assets/images/spaceship/bridge.png');
$AssetsImagesSpaceshipRailGen get rail =>
const $AssetsImagesSpaceshipRailGen();
$AssetsImagesSpaceshipRampGen get ramp =>
const $AssetsImagesSpaceshipRampGen();
/// File path: assets/images/spaceship/saucer.png
AssetGenImage get saucer =>
const AssetGenImage('assets/images/spaceship/saucer.png');
}
@ -147,8 +220,11 @@ class $AssetsImagesSparkyGen {
class $AssetsImagesDashBumperAGen {
const $AssetsImagesDashBumperAGen();
/// File path: assets/images/dash_bumper/a/active.png
AssetGenImage get active =>
const AssetGenImage('assets/images/dash_bumper/a/active.png');
/// File path: assets/images/dash_bumper/a/inactive.png
AssetGenImage get inactive =>
const AssetGenImage('assets/images/dash_bumper/a/inactive.png');
}
@ -156,8 +232,11 @@ class $AssetsImagesDashBumperAGen {
class $AssetsImagesDashBumperBGen {
const $AssetsImagesDashBumperBGen();
/// File path: assets/images/dash_bumper/b/active.png
AssetGenImage get active =>
const AssetGenImage('assets/images/dash_bumper/b/active.png');
/// File path: assets/images/dash_bumper/b/inactive.png
AssetGenImage get inactive =>
const AssetGenImage('assets/images/dash_bumper/b/inactive.png');
}
@ -165,8 +244,11 @@ class $AssetsImagesDashBumperBGen {
class $AssetsImagesDashBumperMainGen {
const $AssetsImagesDashBumperMainGen();
/// File path: assets/images/dash_bumper/main/active.png
AssetGenImage get active =>
const AssetGenImage('assets/images/dash_bumper/main/active.png');
/// File path: assets/images/dash_bumper/main/inactive.png
AssetGenImage get inactive =>
const AssetGenImage('assets/images/dash_bumper/main/inactive.png');
}
@ -174,8 +256,11 @@ class $AssetsImagesDashBumperMainGen {
class $AssetsImagesSpaceshipRailGen {
const $AssetsImagesSpaceshipRailGen();
/// File path: assets/images/spaceship/rail/foreground.png
AssetGenImage get foreground =>
const AssetGenImage('assets/images/spaceship/rail/foreground.png');
/// File path: assets/images/spaceship/rail/main.png
AssetGenImage get main =>
const AssetGenImage('assets/images/spaceship/rail/main.png');
}
@ -183,10 +268,15 @@ class $AssetsImagesSpaceshipRailGen {
class $AssetsImagesSpaceshipRampGen {
const $AssetsImagesSpaceshipRampGen();
/// File path: assets/images/spaceship/ramp/main.png
AssetGenImage get main =>
const AssetGenImage('assets/images/spaceship/ramp/main.png');
/// File path: assets/images/spaceship/ramp/railing-background.png
AssetGenImage get railingBackground => const AssetGenImage(
'assets/images/spaceship/ramp/railing-background.png');
/// File path: assets/images/spaceship/ramp/railing-foreground.png
AssetGenImage get railingForeground => const AssetGenImage(
'assets/images/spaceship/ramp/railing-foreground.png');
}

@ -11,6 +11,7 @@ export 'dino_walls.dart';
export 'fire_effect.dart';
export 'flipper.dart';
export 'flutter_sign_post.dart';
export 'google_letter.dart';
export 'initial_position.dart';
export 'joint_anchor.dart';
export 'kicker.dart';

@ -0,0 +1,95 @@
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball_components/pinball_components.dart';
/// {@template google_letter}
/// Circular sensor that represents a letter in "GOOGLE" for a given index.
/// {@endtemplate}
class GoogleLetter extends BodyComponent with InitialPosition {
/// {@macro google_letter}
GoogleLetter(int index)
: _sprite = _GoogleLetterSprite(
_GoogleLetterSprite.spritePaths[index],
);
final _GoogleLetterSprite _sprite;
/// Activates this [GoogleLetter].
// TODO(alestiago): Improve doc comment once activate and deactivate
// are implemented with the actual assets.
Future<void> activate() => _sprite.activate();
/// Deactivates this [GoogleLetter].
Future<void> deactivate() => _sprite.deactivate();
@override
Future<void> onLoad() async {
await super.onLoad();
await add(_sprite);
}
@override
Body createBody() {
final shape = CircleShape()..radius = 1.85;
final fixtureDef = FixtureDef(shape)..isSensor = true;
final bodyDef = BodyDef()
..position = initialPosition
..userData = this
..type = BodyType.static;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}
class _GoogleLetterSprite extends SpriteComponent with HasGameRef {
_GoogleLetterSprite(String path) : _path = path;
static final spritePaths = [
Assets.images.googleWord.letter1.keyName,
Assets.images.googleWord.letter2.keyName,
Assets.images.googleWord.letter3.keyName,
Assets.images.googleWord.letter4.keyName,
Assets.images.googleWord.letter5.keyName,
Assets.images.googleWord.letter6.keyName,
];
final String _path;
// TODO(alestiago): Correctly implement activate and deactivate once the
// assets are provided.
Future<void> activate() async {
await add(
_GoogleLetterColorEffect(color: Colors.green),
);
}
Future<void> deactivate() async {
await add(
_GoogleLetterColorEffect(color: Colors.red),
);
}
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(_path);
this.sprite = sprite;
// TODO(alestiago): Size correctly once the assets are provided.
size = sprite.originalSize / 5;
anchor = Anchor.center;
}
}
class _GoogleLetterColorEffect extends ColorEffect {
_GoogleLetterColorEffect({
required Color color,
}) : super(
color,
const Offset(0, 1),
EffectController(duration: 0.25),
);
}

@ -55,6 +55,7 @@ flutter:
- assets/images/sparky/bumper/b/
- assets/images/sparky/bumper/c/
- assets/images/backboard/
- assets/images/google_word/
flutter_gen:
line_length: 80

@ -25,6 +25,7 @@ void main() {
addSparkyBumperStories(dashbook);
addZoomStories(dashbook);
addBoundariesStories(dashbook);
addGoogleWordStories(dashbook);
addSpaceshipRampStories(dashbook);
addSpaceshipRailStories(dashbook);
addLaunchRampStories(dashbook);

@ -13,7 +13,7 @@ class BasicBallGame extends BasicGame with TapDetector, Traceable {
static const info = '''
Shows how a Ball works.
Tap anywhere on the screen to spawn a ball into the game.
- Tap anywhere on the screen to spawn a ball into the game.
''';
final Color color;

@ -0,0 +1,36 @@
import 'dart:ui';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:sandbox/stories/ball/basic_ball_game.dart';
class GoogleLetterGame extends BasicBallGame {
GoogleLetterGame() : super(color: const Color(0xFF009900));
static const info = '''
Shows how a GoogleLetter is rendered.
- Tap anywhere on the screen to spawn a ball into the game.
''';
@override
Future<void> onLoad() async {
await super.onLoad();
addContactCallback(_BallGoogleLetterContactCallback());
camera.followVector2(Vector2.zero());
await add(GoogleLetter(0));
await traceAllBodies();
}
}
class _BallGoogleLetterContactCallback
extends ContactCallback<Ball, GoogleLetter> {
@override
void begin(Ball<Forge2DGame> a, GoogleLetter b, Contact contact) {
super.begin(a, b, contact);
b.activate();
}
}

@ -0,0 +1,15 @@
import 'package:dashbook/dashbook.dart';
import 'package:flame/game.dart';
import 'package:sandbox/common/common.dart';
import 'package:sandbox/stories/google_word/google_letter_game.dart';
void addGoogleWordStories(Dashbook dashbook) {
dashbook.storiesOf('Google Word').add(
'Letter',
(context) => GameWidget(
game: GoogleLetterGame()..trace = context.boolProperty('Trace', true),
),
codeLink: buildSourceLink('google_word/letter.dart'),
info: GoogleLetterGame.info,
);
}

@ -5,6 +5,7 @@ export 'chrome_dino/stories.dart';
export 'effects/stories.dart';
export 'flipper/stories.dart';
export 'flutter_forest/stories.dart';
export 'google_word/stories.dart';
export 'launch_ramp/stories.dart';
export 'layer/stories.dart';
export 'score_text/stories.dart';

@ -0,0 +1,126 @@
// ignore_for_file: cascade_invocations
import 'package:flame/effects.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(TestGame.new);
group('Google Letter', () {
flameTester.test(
'0th loads correctly',
(game) async {
final googleLetter = GoogleLetter(0);
await game.ready();
await game.ensureAdd(googleLetter);
expect(game.contains(googleLetter), isTrue);
},
);
flameTester.test(
'1st loads correctly',
(game) async {
final googleLetter = GoogleLetter(1);
await game.ready();
await game.ensureAdd(googleLetter);
expect(game.contains(googleLetter), isTrue);
},
);
flameTester.test(
'2nd loads correctly',
(game) async {
final googleLetter = GoogleLetter(2);
await game.ready();
await game.ensureAdd(googleLetter);
expect(game.contains(googleLetter), isTrue);
},
);
flameTester.test(
'3d loads correctly',
(game) async {
final googleLetter = GoogleLetter(3);
await game.ready();
await game.ensureAdd(googleLetter);
expect(game.contains(googleLetter), isTrue);
},
);
flameTester.test(
'4th loads correctly',
(game) async {
final googleLetter = GoogleLetter(4);
await game.ready();
await game.ensureAdd(googleLetter);
expect(game.contains(googleLetter), isTrue);
},
);
flameTester.test(
'5th loads correctly',
(game) async {
final googleLetter = GoogleLetter(5);
await game.ready();
await game.ensureAdd(googleLetter);
expect(game.contains(googleLetter), isTrue);
},
);
test('throws error when index out of range', () {
expect(() => GoogleLetter(-1), throwsA(isA<RangeError>()));
expect(() => GoogleLetter(6), throwsA(isA<RangeError>()));
});
group('activate', () {
flameTester.test('returns normally', (game) async {
final googleLetter = GoogleLetter(0);
await game.ensureAdd(googleLetter);
await expectLater(googleLetter.activate, returnsNormally);
});
flameTester.test('adds an Effect', (game) async {
final googleLetter = GoogleLetter(0);
await game.ensureAdd(googleLetter);
await googleLetter.activate();
await game.ready();
expect(
googleLetter.descendants().whereType<Effect>().length,
equals(1),
);
});
});
group('deactivate', () {
flameTester.test('returns normally', (game) async {
final googleLetter = GoogleLetter(0);
await game.ensureAdd(googleLetter);
await expectLater(googleLetter.deactivate, returnsNormally);
});
flameTester.test('adds an Effect', (game) async {
final googleLetter = GoogleLetter(0);
await game.ensureAdd(googleLetter);
await googleLetter.deactivate();
await game.ready();
expect(
googleLetter.descendants().whereType<Effect>().length,
equals(1),
);
});
});
});
}
Loading…
Cancel
Save