feat: animate chrome dino (#229)

* feat: included new head and mouth assets

* feat: including sprites

* feat: sized sprites

* feat: included new sprites

* feat: adjusted SpriteAnimationComponent

* feat: adjusted tracing logic

* feat: added Traceable to ChromeDinoGame

* feat: synced dino animation

* refactor: fix crazy rendering

* test: chrome dino

* refactor: dino sandbox

* chore: revert spaceship changes

* chore: move assets for sanbox game

* refactor: move dino walls and bottom boundary

* refactor: move dino for moved dino wall

* test: update goldens

* chore: clean up dino wall fixture defs

* refactor: dino variable and comment fixes

* chore: add todo

* refactor: fix PR nits

* chore: use internal positioning

* refactor: keep positioning

* chore: fix nits and add todo

* fix: update boundaries golden

Co-authored-by: alestiago <dev@alestiago.com>
pull/260/head
Allison Ryan 3 years ago committed by GitHub
parent 8e9ef85dda
commit 97337938d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -18,17 +18,8 @@ class Board extends Component {
final flutterForest = FlutterForest();
// TODO(alestiago): adjust positioning to real design.
// TODO(alestiago): add dino in pinball game.
final dino = ChromeDino()
..initialPosition = Vector2(
BoardDimensions.bounds.center.dx + 25,
BoardDimensions.bounds.center.dy - 10,
);
await addAll([
bottomGroup,
dino,
flutterForest,
]);
}

@ -34,8 +34,10 @@ extension PinballGameAssetsX on PinballGame {
images.load(
components.Assets.images.launchRamp.backgroundRailing.keyName,
),
images.load(components.Assets.images.dino.dinoLandTop.keyName),
images.load(components.Assets.images.dino.dinoLandBottom.keyName),
images.load(components.Assets.images.dino.bottomWall.keyName),
images.load(components.Assets.images.dino.topWall.keyName),
images.load(components.Assets.images.dino.animatronic.head.keyName),
images.load(components.Assets.images.dino.animatronic.mouth.keyName),
images.load(components.Assets.images.dash.animatronic.keyName),
images.load(components.Assets.images.dash.bumper.a.active.keyName),
images.load(components.Assets.images.dash.bumper.a.inactive.keyName),
@ -81,8 +83,6 @@ extension PinballGameAssetsX on PinballGame {
images.load(components.Assets.images.androidBumper.a.dimmed.keyName),
images.load(components.Assets.images.androidBumper.b.lit.keyName),
images.load(components.Assets.images.androidBumper.b.dimmed.keyName),
images.load(components.Assets.images.chromeDino.mouth.keyName),
images.load(components.Assets.images.chromeDino.head.keyName),
images.load(components.Assets.images.sparky.computer.top.keyName),
images.load(components.Assets.images.sparky.computer.base.keyName),
images.load(components.Assets.images.sparky.animatronic.keyName),

@ -57,6 +57,7 @@ class PinballGame extends Forge2DGame
await addFromBlueprint(AndroidAcres());
unawaited(addFromBlueprint(Slingshots()));
unawaited(addFromBlueprint(DinoWalls()));
await add(ChromeDino()..initialPosition = Vector2(12.3, -6.9));
await add(
GoogleWord(
position: Vector2(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 KiB

@ -16,8 +16,6 @@ class $AssetsImagesGen {
$AssetsImagesBallGen get ball => const $AssetsImagesBallGen();
$AssetsImagesBaseboardGen get baseboard => const $AssetsImagesBaseboardGen();
$AssetsImagesBoundaryGen get boundary => const $AssetsImagesBoundaryGen();
$AssetsImagesChromeDinoGen get chromeDino =>
const $AssetsImagesChromeDinoGen();
$AssetsImagesDashGen get dash => const $AssetsImagesDashGen();
$AssetsImagesDinoGen get dino => const $AssetsImagesDinoGen();
$AssetsImagesFlipperGen get flipper => const $AssetsImagesFlipperGen();
@ -97,18 +95,6 @@ class $AssetsImagesBoundaryGen {
const AssetGenImage('assets/images/boundary/outer.png');
}
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');
}
class $AssetsImagesDashGen {
const $AssetsImagesDashGen();
@ -122,13 +108,16 @@ class $AssetsImagesDashGen {
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');
$AssetsImagesDinoAnimatronicGen get animatronic =>
const $AssetsImagesDinoAnimatronicGen();
/// File path: assets/images/dino/bottom-wall.png
AssetGenImage get bottomWall =>
const AssetGenImage('assets/images/dino/bottom-wall.png');
/// File path: assets/images/dino/dino-land-top.png
AssetGenImage get dinoLandTop =>
const AssetGenImage('assets/images/dino/dino-land-top.png');
/// File path: assets/images/dino/top-wall.png
AssetGenImage get topWall =>
const AssetGenImage('assets/images/dino/top-wall.png');
}
class $AssetsImagesFlipperGen {
@ -304,6 +293,18 @@ class $AssetsImagesDashBumperGen {
const $AssetsImagesDashBumperMainGen();
}
class $AssetsImagesDinoAnimatronicGen {
const $AssetsImagesDinoAnimatronicGen();
/// File path: assets/images/dino/animatronic/head.png
AssetGenImage get head =>
const AssetGenImage('assets/images/dino/animatronic/head.png');
/// File path: assets/images/dino/animatronic/mouth.png
AssetGenImage get mouth =>
const AssetGenImage('assets/images/dino/animatronic/mouth.png');
}
class $AssetsImagesSpaceshipRailGen {
const $AssetsImagesSpaceshipRailGen();

@ -67,7 +67,7 @@ class _BottomBoundarySpriteComponent extends SpriteComponent with HasGameRef {
_BottomBoundarySpriteComponent()
: super(
anchor: Anchor.center,
position: Vector2(-5.4, 55.6),
position: Vector2(-5, 55.6),
);
@override

@ -1,31 +1,33 @@
import 'dart:async';
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart' hide Timer;
import 'package:flutter/material.dart';
import 'package:pinball_components/pinball_components.dart';
/// {@template chrome_dino}
/// Dinosaur that gobbles up a [Ball], swivel his head around, and shoots it
/// back out.
/// Dino that swivels back and forth, opening its mouth to eat a [Ball].
///
/// Upon eating a [Ball], the dino rotates and spits the [Ball] out in a
/// different direction.
/// {@endtemplate}
class ChromeDino extends BodyComponent with InitialPosition {
/// {@macro chrome_dino}
ChromeDino()
: super(
// TODO(alestiago): Remove once sprites are defined.
paint: Paint()..color = Colors.blue,
priority: RenderPriority.dino,
renderBody: false,
);
/// The size of the dinosaur mouth.
static final size = Vector2(5, 2.5);
static final size = Vector2(5.5, 5);
/// Anchors the [ChromeDino] to the [RevoluteJoint] that controls its arc
/// motion.
Future<_ChromeDinoJoint> _anchorToJoint() async {
final anchor = _ChromeDinoAnchor();
// TODO(allisonryan0002): try moving to anchor after new body is defined.
final anchor = _ChromeDinoAnchor()
..initialPosition = initialPosition + Vector2(9, -4);
await add(anchor);
final jointDef = _ChromeDinoAnchorRevoluteJointDef(
@ -42,9 +44,11 @@ class ChromeDino extends BodyComponent with InitialPosition {
Future<void> onLoad() async {
await super.onLoad();
final joint = await _anchorToJoint();
const framesInAnimation = 98;
const animationFPS = 1 / 24;
await add(
TimerComponent(
period: 1,
period: (framesInAnimation / 2) * animationFPS,
onTick: joint._swivel,
repeat: true,
),
@ -54,44 +58,17 @@ class ChromeDino extends BodyComponent with InitialPosition {
List<FixtureDef> _createFixtureDefs() {
final fixtureDefs = <FixtureDef>[];
// TODO(alestiago): Subject to change when sprites are added.
final box = PolygonShape()..setAsBoxXY(size.x / 2, size.y / 2);
final fixtureDef = FixtureDef(
box,
density: 999,
friction: 0.3,
restitution: 0.1,
isSensor: true,
);
// TODO(allisonryan0002): Update this shape to better match sprite.
final box = PolygonShape()
..setAsBox(
size.x / 2,
size.y / 2,
initialPosition + Vector2(-4, 2),
-_ChromeDinoJoint._halfSweepingAngle,
);
final fixtureDef = FixtureDef(box, density: 1);
fixtureDefs.add(fixtureDef);
// FIXME(alestiago): Investigate why adding these fixtures is considered as
// an invalid contact type.
// final upperEdge = EdgeShape()
// ..set(
// Vector2(-size.x / 2, -size.y / 2),
// Vector2(size.x / 2, -size.y / 2),
// );
// final upperEdgeDef = FixtureDef(upperEdge)..density = 0.5;
// fixtureDefs.add(upperEdgeDef);
// final lowerEdge = EdgeShape()
// ..set(
// Vector2(-size.x / 2, size.y / 2),
// Vector2(size.x / 2, size.y / 2),
// );
// final lowerEdgeDef = FixtureDef(lowerEdge)..density = 0.5;
// fixtureDefs.add(lowerEdgeDef);
// final rightEdge = EdgeShape()
// ..set(
// Vector2(size.x / 2, -size.y / 2),
// Vector2(size.x / 2, size.y / 2),
// );
// final rightEdgeDef = FixtureDef(rightEdge)..density = 0.5;
// fixtureDefs.add(rightEdgeDef);
return fixtureDefs;
}
@ -110,13 +87,18 @@ class ChromeDino extends BodyComponent with InitialPosition {
}
}
/// {@template flipper_anchor}
/// [JointAnchor] positioned at the end of a [ChromeDino].
/// {@endtemplate}
class _ChromeDinoAnchor extends JointAnchor {
/// {@macro flipper_anchor}
_ChromeDinoAnchor() {
initialPosition = Vector2(ChromeDino.size.x / 2, 0);
_ChromeDinoAnchor();
// TODO(allisonryan0002): if these aren't moved when fixing the rendering, see
// if the joint can be created in onMount to resolve render syncing.
@override
Future<void> onLoad() async {
await super.onLoad();
await addAll([
_ChromeDinoMouthSprite(),
_ChromeDinoHeadSprite(),
]);
}
}
@ -135,22 +117,86 @@ class _ChromeDinoAnchorRevoluteJointDef extends RevoluteJointDef {
chromeDino.body.position + anchor.body.position,
);
enableLimit = true;
// TODO(alestiago): Apply design angle value.
const angle = math.pi / 3.5;
lowerAngle = -angle / 2;
upperAngle = angle / 2;
lowerAngle = -_ChromeDinoJoint._halfSweepingAngle;
upperAngle = _ChromeDinoJoint._halfSweepingAngle;
enableMotor = true;
// TODO(alestiago): Tune this values.
maxMotorTorque = motorSpeed = chromeDino.body.mass * 30;
maxMotorTorque = chromeDino.body.mass * 255;
motorSpeed = 2;
}
}
class _ChromeDinoJoint extends RevoluteJoint {
_ChromeDinoJoint(_ChromeDinoAnchorRevoluteJointDef def) : super(def);
static const _halfSweepingAngle = 0.1143;
/// Sweeps the [ChromeDino] up and down repeatedly.
void _swivel() {
setMotorSpeed(-motorSpeed);
}
}
class _ChromeDinoMouthSprite extends SpriteAnimationComponent with HasGameRef {
_ChromeDinoMouthSprite()
: super(
anchor: Anchor(Anchor.center.x + 0.47, Anchor.center.y - 0.29),
angle: _ChromeDinoJoint._halfSweepingAngle,
);
@override
Future<void> onLoad() async {
await super.onLoad();
final image = gameRef.images.fromCache(
Assets.images.dino.animatronic.mouth.keyName,
);
const amountPerRow = 11;
const amountPerColumn = 9;
final textureSize = Vector2(
image.width / amountPerRow,
image.height / amountPerColumn,
);
size = textureSize / 10;
final data = SpriteAnimationData.sequenced(
amount: (amountPerColumn * amountPerRow) - 1,
amountPerRow: amountPerRow,
stepTime: 1 / 24,
textureSize: textureSize,
);
animation = SpriteAnimation.fromFrameData(image, data)..currentIndex = 45;
}
}
class _ChromeDinoHeadSprite extends SpriteAnimationComponent with HasGameRef {
_ChromeDinoHeadSprite()
: super(
anchor: Anchor(Anchor.center.x + 0.47, Anchor.center.y - 0.29),
angle: _ChromeDinoJoint._halfSweepingAngle,
);
@override
Future<void> onLoad() async {
await super.onLoad();
final image = gameRef.images.fromCache(
Assets.images.dino.animatronic.head.keyName,
);
const amountPerRow = 11;
const amountPerColumn = 9;
final textureSize = Vector2(
image.width / amountPerRow,
image.height / amountPerColumn,
);
size = textureSize / 10;
final data = SpriteAnimationData.sequenced(
amount: (amountPerColumn * amountPerRow) - 1,
amountPerRow: amountPerRow,
stepTime: 1 / 24,
textureSize: textureSize,
);
animation = SpriteAnimation.fromFrameData(image, data)..currentIndex = 45;
}
}

@ -35,51 +35,46 @@ class _DinoTopWall extends BodyComponent with InitialPosition {
List<FixtureDef> _createFixtureDefs() {
final topStraightShape = EdgeShape()
..set(
Vector2(28.65, -35.1),
Vector2(29.5, -35.1),
Vector2(28.65, -34.3),
Vector2(29.5, -34.3),
);
final topStraightFixtureDef = FixtureDef(topStraightShape);
final topCurveShape = BezierCurveShape(
controlPoints: [
topStraightShape.vertex1,
Vector2(18.8, -27),
Vector2(26.6, -21),
Vector2(18.8, -26.2),
Vector2(26.6, -20.2),
],
);
final topCurveFixtureDef = FixtureDef(topCurveShape);
final middleCurveShape = BezierCurveShape(
controlPoints: [
topCurveShape.vertices.last,
Vector2(27.8, -20.1),
Vector2(26.8, -19.5),
Vector2(27.8, -19.3),
Vector2(26.8, -18.7),
],
);
final middleCurveFixtureDef = FixtureDef(middleCurveShape);
final bottomCurveShape = BezierCurveShape(
controlPoints: [
middleCurveShape.vertices.last,
Vector2(23, -15),
Vector2(27, -15),
Vector2(23, -14.2),
Vector2(27, -14.2),
],
);
final bottomCurveFixtureDef = FixtureDef(bottomCurveShape);
final bottomStraightShape = EdgeShape()
..set(
bottomCurveShape.vertices.last,
Vector2(31, -14.5),
Vector2(31, -13.7),
);
final bottomStraightFixtureDef = FixtureDef(bottomStraightShape);
return [
topStraightFixtureDef,
topCurveFixtureDef,
middleCurveFixtureDef,
bottomCurveFixtureDef,
bottomStraightFixtureDef,
FixtureDef(topStraightShape),
FixtureDef(topCurveShape),
FixtureDef(middleCurveShape),
FixtureDef(bottomCurveShape),
FixtureDef(bottomStraightShape),
];
}
@ -109,12 +104,12 @@ class _DinoTopWallSpriteComponent extends SpriteComponent with HasGameRef {
await super.onLoad();
final sprite = Sprite(
gameRef.images.fromCache(
Assets.images.dino.dinoLandTop.keyName,
Assets.images.dino.topWall.keyName,
),
);
this.sprite = sprite;
size = sprite.originalSize / 10;
position = Vector2(22.8, -38.9);
position = Vector2(22.8, -38.1);
}
}
@ -131,17 +126,11 @@ class _DinoBottomWall extends BodyComponent with InitialPosition {
);
List<FixtureDef> _createFixtureDefs() {
const restitution = 1.0;
final topStraightShape = EdgeShape()
..set(
Vector2(32.4, -8.8),
Vector2(25, -7.7),
);
final topStraightFixtureDef = FixtureDef(
topStraightShape,
restitution: restitution,
);
final topLeftCurveShape = BezierCurveShape(
controlPoints: [
@ -150,36 +139,24 @@ class _DinoBottomWall extends BodyComponent with InitialPosition {
Vector2(29.8, 13.8),
],
);
final topLeftCurveFixtureDef = FixtureDef(
topLeftCurveShape,
restitution: restitution,
);
final bottomLeftStraightShape = EdgeShape()
..set(
topLeftCurveShape.vertices.last,
Vector2(31.9, 44.1),
);
final bottomLeftStraightFixtureDef = FixtureDef(
bottomLeftStraightShape,
restitution: restitution,
);
final bottomStraightShape = EdgeShape()
..set(
bottomLeftStraightShape.vertex2,
Vector2(37.8, 44.1),
);
final bottomStraightFixtureDef = FixtureDef(
bottomStraightShape,
restitution: restitution,
);
return [
topStraightFixtureDef,
topLeftCurveFixtureDef,
bottomLeftStraightFixtureDef,
bottomStraightFixtureDef,
FixtureDef(topStraightShape),
FixtureDef(topLeftCurveShape),
FixtureDef(bottomLeftStraightShape),
FixtureDef(bottomStraightShape),
];
}
@ -203,11 +180,11 @@ class _DinoBottomWallSpriteComponent extends SpriteComponent with HasGameRef {
await super.onLoad();
final sprite = Sprite(
gameRef.images.fromCache(
Assets.images.dino.dinoLandBottom.keyName,
Assets.images.dino.bottomWall.keyName,
),
);
this.sprite = sprite;
size = sprite.originalSize / 10;
position = Vector2(23.6, -9.5);
position = Vector2(23.8, -9.5);
}
}

@ -50,6 +50,7 @@ flutter:
- assets/images/baseboard/
- assets/images/boundary/
- assets/images/dino/
- assets/images/dino/animatronic/
- assets/images/flipper/
- assets/images/launch_ramp/
- assets/images/dash/
@ -60,7 +61,6 @@ flutter:
- assets/images/spaceship/rail/
- assets/images/spaceship/ramp/
- assets/images/spaceship/ramp/arrow/
- assets/images/chrome_dino/
- assets/images/kicker/
- assets/images/plunger/
- assets/images/slingshot/

@ -1,8 +1,22 @@
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:sandbox/stories/ball/basic_ball_game.dart';
class ChromeDinoGame extends Forge2DGame {
static const description = 'Shows how a ChromeDino is rendered.';
class ChromeDinoGame extends BallGame {
ChromeDinoGame()
: super(
imagesFileNames: [
Assets.images.dino.animatronic.mouth.keyName,
Assets.images.dino.animatronic.head.keyName,
],
);
static const description = '''
Shows how ChromeDino is rendered.
- Activate the "trace" parameter to overlay the body.
- Tap anywhere on the screen to spawn a ball into the game.
''';
@override
Future<void> onLoad() async {
@ -10,5 +24,7 @@ class ChromeDinoGame extends Forge2DGame {
camera.followVector2(Vector2.zero());
await add(ChromeDino());
await traceAllBodies();
}
}

@ -4,7 +4,7 @@ import 'package:sandbox/stories/chrome_dino/chrome_dino_game.dart';
void addChromeDinoStories(Dashbook dashbook) {
dashbook.storiesOf('Chrome Dino').addGame(
title: 'Trace',
title: 'Traced',
description: ChromeDinoGame.description,
gameBuilder: (_) => ChromeDinoGame(),
);

@ -20,8 +20,8 @@ class DinoWallGame extends BallGame {
await super.onLoad();
await images.loadAll([
Assets.images.dino.dinoLandTop.keyName,
Assets.images.dino.dinoLandBottom.keyName,
Assets.images.dino.topWall.keyName,
Assets.images.dino.bottomWall.keyName,
]);
await addFromBlueprint(DinoWalls());

@ -1,13 +1,19 @@
// ignore_for_file: cascade_invocations
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame/components.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(Forge2DGame.new);
final assets = [
Assets.images.dino.animatronic.mouth.keyName,
Assets.images.dino.animatronic.head.keyName,
];
final flameTester = FlameTester(() => TestGame(assets));
group('ChromeDino', () {
flameTester.test(
@ -20,19 +26,84 @@ void main() {
},
);
flameTester.test(
'swivels',
(game) async {
// TODO(alestiago): Write golden tests to check the
// swivel animation.
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
flameTester.testGameWidget(
'renders correctly',
setUp: (game, tester) async {
await game.images.loadAll(assets);
await game.ensureAdd(ChromeDino());
game.camera.followVector2(Vector2.zero());
await tester.pump();
},
verify: (game, tester) async {
final sweepAnimationDuration = game
.descendants()
.whereType<SpriteAnimationComponent>()
.first
.animation!
.totalDuration() /
2;
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/up.png'),
);
final previousPosition = chromeDino.body.position.clone();
game.update(64);
game.update(sweepAnimationDuration * 0.25);
await tester.pump();
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/middle.png'),
);
expect(chromeDino.body.position, isNot(equals(previousPosition)));
game.update(sweepAnimationDuration * 0.25);
await tester.pump();
await expectLater(
find.byGame<TestGame>(),
matchesGoldenFile('golden/chrome_dino/down.png'),
);
},
);
group('swivels', () {
flameTester.test(
'up',
(game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
game.camera.followVector2(Vector2.zero());
final sweepAnimationDuration = game
.descendants()
.whereType<SpriteAnimationComponent>()
.first
.animation!
.totalDuration() /
2;
game.update(sweepAnimationDuration * 1.5);
expect(chromeDino.body.angularVelocity, isPositive);
},
);
flameTester.test(
'down',
(game) async {
final chromeDino = ChromeDino();
await game.ensureAdd(chromeDino);
game.camera.followVector2(Vector2.zero());
final sweepAnimationDuration = game
.descendants()
.whereType<SpriteAnimationComponent>()
.first
.animation!
.totalDuration() /
2;
game.update(sweepAnimationDuration * 0.5);
expect(chromeDino.body.angularVelocity, isNegative);
},
);
});
});
}

@ -45,6 +45,7 @@ void main() {
);
},
);
flameTester.test(
'loads correctly',
(game) async {

@ -12,8 +12,8 @@ void main() {
group('DinoWalls', () {
TestWidgetsFlutterBinding.ensureInitialized();
final assets = [
Assets.images.dino.dinoLandTop.keyName,
Assets.images.dino.dinoLandBottom.keyName,
Assets.images.dino.topWall.keyName,
Assets.images.dino.bottomWall.keyName,
];
final flameTester = FlameTester(() => TestGame(assets));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

@ -105,18 +105,6 @@ void main() {
expect(flutterForest.length, equals(1));
},
);
flameTester.test(
'one ChromeDino',
(game) async {
final board = Board();
await game.ready();
await game.ensureAdd(board);
final chromeDino = board.descendants().whereType<ChromeDino>();
expect(chromeDino.length, equals(1));
},
);
});
});
}

@ -27,10 +27,10 @@ void main() {
Assets.images.boundary.bottom.keyName,
Assets.images.boundary.outer.keyName,
Assets.images.boundary.outerBottom.keyName,
Assets.images.chromeDino.mouth.keyName,
Assets.images.chromeDino.head.keyName,
Assets.images.dino.dinoLandTop.keyName,
Assets.images.dino.dinoLandBottom.keyName,
Assets.images.dino.animatronic.mouth.keyName,
Assets.images.dino.animatronic.head.keyName,
Assets.images.dino.topWall.keyName,
Assets.images.dino.bottomWall.keyName,
Assets.images.dash.animatronic.keyName,
Assets.images.dash.bumper.a.active.keyName,
Assets.images.dash.bumper.a.inactive.keyName,

Loading…
Cancel
Save