feat: applying assets to the spaceship

pull/101/head
Erick Zanardo 4 years ago
parent 72b8213f74
commit 9c11113c58

@ -1,5 +1,4 @@
import 'package:flame/components.dart';
import 'package:pinball/flame/blueprint.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';

@ -9,7 +9,5 @@ export 'jetpack_ramp.dart';
export 'kicker.dart';
export 'launcher_ramp.dart';
export 'plunger.dart';
export 'ramp_opening.dart';
export 'score_points.dart';
export 'spaceship.dart';
export 'wall.dart';

@ -6,7 +6,6 @@ import 'package:flame/components.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball/flame/blueprint.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';

@ -7,10 +7,11 @@ import 'package:flame/extensions.dart';
import 'package:flame/input.dart';
import 'package:flame_bloc/flame_bloc.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';
import 'package:pinball_theme/pinball_theme.dart' hide Assets;
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_theme/pinball_theme.dart';
class PinballGame extends Forge2DGame
with FlameBloc, HasKeyboardHandlerComponents {
@ -46,7 +47,13 @@ class PinballGame extends Forge2DGame
unawaited(_addPlunger());
unawaited(_addBonusWord());
unawaited(_addPaths());
unawaited(addFromBlueprint(Spaceship()));
unawaited(
addFromBlueprint(
Spaceship(
position: Vector2(-25, 32),
),
),
);
// Fix camera on the center of the board.
camera

@ -3,8 +3,6 @@
/// FlutterGen
/// *****************************************************
// ignore_for_file: directives_ordering,unnecessary_import
import 'package:flutter/widgets.dart';
class $AssetsImagesGen {
@ -17,10 +15,8 @@ class $AssetsImagesGen {
class $AssetsImagesComponentsGen {
const $AssetsImagesComponentsGen();
/// File path: assets/images/components/background.png
AssetGenImage get background =>
const AssetGenImage('assets/images/components/background.png');
$AssetsImagesComponentsSpaceshipGen get spaceship =>
const $AssetsImagesComponentsSpaceshipGen();
}
@ -28,23 +24,14 @@ class $AssetsImagesComponentsGen {
class $AssetsImagesComponentsSpaceshipGen {
const $AssetsImagesComponentsSpaceshipGen();
/// File path: assets/images/components/spaceship/android-bottom.png
AssetGenImage get androidBottom => const AssetGenImage(
'assets/images/components/spaceship/android-bottom.png');
/// File path: assets/images/components/spaceship/android-top.png
AssetGenImage get androidTop =>
const AssetGenImage('assets/images/components/spaceship/android-top.png');
/// File path: assets/images/components/spaceship/lower.png
AssetGenImage get lower =>
const AssetGenImage('assets/images/components/spaceship/lower.png');
/// File path: assets/images/components/spaceship/saucer.png
AssetGenImage get saucer =>
const AssetGenImage('assets/images/components/spaceship/saucer.png');
/// File path: assets/images/components/spaceship/upper.png
AssetGenImage get upper =>
const AssetGenImage('assets/images/components/spaceship/upper.png');
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

@ -12,6 +12,7 @@ class $AssetsImagesGen {
/// File path: assets/images/ball.png
AssetGenImage get ball => const AssetGenImage('assets/images/ball.png');
<<<<<<< HEAD
$AssetsImagesFlipperGen get flipper => const $AssetsImagesFlipperGen();
}
@ -26,6 +27,12 @@ class $AssetsImagesFlipperGen {
/// File path: assets/images/flipper/right.png
AssetGenImage get right =>
const AssetGenImage('assets/images/flipper/right.png');
=======
AssetGenImage get spaceshipBridge =>
const AssetGenImage('assets/images/spaceship_bridge.png');
AssetGenImage get spaceshipSaucer =>
const AssetGenImage('assets/images/spaceship_saucer.png');
>>>>>>> 990de50 (feat: applying assets to the spaceship)
}
class Assets {

@ -5,4 +5,6 @@ export 'flipper.dart';
export 'initial_position.dart';
export 'joint_anchor.dart';
export 'layer.dart';
export 'ramp_opening.dart';
export 'shapes/shapes.dart';
export 'spaceship.dart';

@ -1,7 +1,6 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
/// {@template ramp_orientation}
@ -110,3 +109,4 @@ class RampOpeningBallContactCallback<Opening extends RampOpening>
}
}
}

@ -5,23 +5,24 @@ import 'dart:math';
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';
import 'package:pinball_components/gen/assets.gen.dart';
import 'package:pinball_components/pinball_components.dart' hide Assets;
/// {@template spaceship}
/// A [Blueprint] which creates the spaceship feature.
/// P@endtemplate}
class Spaceship extends Forge2DBlueprint {
/// {@macro spaceship}
Spaceship({required this.position});
/// Total size of the spaceship
static const radius = 10.0;
static final size = Vector2(24, 18);
/// The [position] that the elements will be created
final Vector2 position;
@override
void build(_) {
final position = Vector2(
PinballGame.boardBounds.left + radius + 15,
PinballGame.boardBounds.center.dy + 30,
);
addAllContactCallback([
SpaceshipHoleBallContactCallback(),
SpaceshipEntranceBallContactCallback(),
@ -31,9 +32,8 @@ class Spaceship extends Forge2DBlueprint {
SpaceshipSaucer()..initialPosition = position,
SpaceshipEntrance()..initialPosition = position,
SpaceshipBridge()..initialPosition = position,
SpaceshipBridgeTop()..initialPosition = position + Vector2(0, 5.5),
SpaceshipHole()..initialPosition = position - Vector2(5, 4),
SpaceshipHole()..initialPosition = position - Vector2(-5, 4),
SpaceshipHole()..initialPosition = position - Vector2(4.8, 4.2),
SpaceshipHole()..initialPosition = position - Vector2(-7.2, 0.6),
SpaceshipWall()..initialPosition = position,
]);
}
@ -51,25 +51,15 @@ class SpaceshipSaucer extends BodyComponent with InitialPosition, Layered {
@override
Future<void> onLoad() async {
await super.onLoad();
final sprites = await Future.wait([
gameRef.loadSprite(Assets.images.components.spaceship.saucer.path),
gameRef.loadSprite(Assets.images.components.spaceship.upper.path),
]);
await add(
SpriteComponent(
sprite: sprites.first,
size: Vector2.all(Spaceship.radius * 2),
anchor: Anchor.center,
),
final sprite = await gameRef.loadSprite(
Assets.images.spaceshipSaucer.keyName,
);
await add(
SpriteComponent(
sprite: sprites.last,
size: Vector2((Spaceship.radius * 2) + 0.5, Spaceship.radius),
sprite: sprite,
size: Spaceship.size,
anchor: Anchor.center,
position: Vector2(0, -((Spaceship.radius * 2) / 3.5)),
),
);
@ -78,7 +68,7 @@ class SpaceshipSaucer extends BodyComponent with InitialPosition, Layered {
@override
Body createBody() {
final circleShape = CircleShape()..radius = Spaceship.radius;
final circleShape = CircleShape()..radius = 3;
final bodyDef = BodyDef()
..userData = this
@ -92,44 +82,9 @@ class SpaceshipSaucer extends BodyComponent with InitialPosition, Layered {
}
}
/// {@spaceship_bridge_top}
/// The bridge of the spaceship (the android head) is divided in two
// [BodyComponent]s, this is the top part of it which contains a single sprite
/// {@endtemplate}
class SpaceshipBridgeTop extends BodyComponent with InitialPosition {
/// {@macro spaceship_bridge_top}
SpaceshipBridgeTop() : super(priority: 6);
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(
Assets.images.components.spaceship.androidTop.path,
);
await add(
SpriteComponent(
sprite: sprite,
anchor: Anchor.center,
size: Vector2((Spaceship.radius * 2) / 2.5 - 1, Spaceship.radius / 2.5),
),
);
}
@override
Body createBody() {
final bodyDef = BodyDef()
..userData = this
..position = initialPosition
..type = BodyType.static;
return world.createBody(bodyDef);
}
}
/// {@template spaceship_bridge}
/// The main part of the [SpaceshipBridge], this [BodyComponent]
/// provides both the collision and the rotation animation for the bridge.
/// A [BodyComponent] that provides both the collision and the rotation
/// animation for the bridge.
/// {@endtemplate}
class SpaceshipBridge extends BodyComponent with InitialPosition, Layered {
/// {@macro spaceship_bridge}
@ -144,17 +99,20 @@ class SpaceshipBridge extends BodyComponent with InitialPosition, Layered {
renderBody = false;
final sprite = await gameRef.images.load(
Assets.images.components.spaceship.androidBottom.path,
Assets.images.spaceshipBridge.keyName,
);
await add(
SpriteAnimationComponent.fromFrameData(
sprite,
SpriteAnimationData.sequenced(
amount: 14,
stepTime: 0.2,
textureSize: Vector2(160, 114),
amount: 72,
amountPerRow: 24,
stepTime: 0.05,
textureSize: Vector2(82, 100),
),
size: Vector2.all((Spaceship.radius * 2) / 2.5),
size: Vector2(8.2, 10),
position: Vector2(0, -2),
anchor: Anchor.center,
),
);
@ -162,7 +120,7 @@ class SpaceshipBridge extends BodyComponent with InitialPosition, Layered {
@override
Body createBody() {
final circleShape = CircleShape()..radius = Spaceship.radius / 2.5;
final circleShape = CircleShape()..radius = 2;
final bodyDef = BodyDef()
..userData = this
@ -193,7 +151,8 @@ class SpaceshipEntrance extends RampOpening {
@override
Shape get shape {
const radius = Spaceship.radius * 2;
renderBody = false;
final radius = Spaceship.size.y / 2;
return PolygonShape()
..setAsEdge(
Vector2(
@ -221,7 +180,7 @@ class SpaceshipHole extends BodyComponent with InitialPosition, Layered {
@override
Body createBody() {
renderBody = false;
final circleShape = CircleShape()..radius = Spaceship.radius / 40;
final circleShape = CircleShape()..radius = 1.5;
final bodyDef = BodyDef()
..userData = this
@ -247,36 +206,19 @@ class SpaceshipWall extends BodyComponent with InitialPosition, Layered {
layer = Layer.spaceship;
}
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = await gameRef.loadSprite(
Assets.images.components.spaceship.lower.path,
);
await add(
SpriteComponent(
sprite: sprite,
size: Vector2(Spaceship.radius * 2, Spaceship.radius + 1),
anchor: Anchor.center,
position: Vector2(-Spaceship.radius / 2, 0),
angle: 90 * pi / 180,
),
);
}
@override
Body createBody() {
renderBody = false;
final minorRadius = (Spaceship.size.y - 2) / 2;
final majorRadius = (Spaceship.size.x - 2) / 2;
final wallShape = ChainShape()
..createChain(
[
for (var angle = 20; angle <= 340; angle++)
Vector2(
Spaceship.radius * cos(angle * pi / 180),
Spaceship.radius * sin(angle * pi / 180),
minorRadius * cos(angle * pi / 180),
majorRadius * sin(angle * pi / 180),
),
],
);

@ -1 +1,2 @@
export 'components/components.dart';
export 'flame/flame.dart';

@ -5,7 +5,7 @@ import 'package:flame/input.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
class BasicGame extends Forge2DGame {
abstract class BasicGame extends Forge2DGame {
BasicGame() {
images.prefix = '';
}

@ -7,6 +7,7 @@
import 'package:dashbook/dashbook.dart';
import 'package:flutter/material.dart';
import 'package:sandbox/stories/effects/effects.dart';
import 'package:sandbox/stories/spaceship/spaceship.dart';
import 'package:sandbox/stories/stories.dart';
void main() {
@ -16,5 +17,6 @@ void main() {
addLayerStories(dashbook);
addEffectsStories(dashbook);
addFlipperStories(dashbook);
addSpaceshipStories(dashbook);
runApp(dashbook);
}

@ -0,0 +1,31 @@
import 'dart:async';
import 'package:flame/input.dart';
import 'package:flutter/material.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:sandbox/common/common.dart';
class BasicSpaceship extends BasicGame with TapDetector {
static String info = 'Renders a spaceship and allows balls to be '
'spawned upon click to test their interactions';
@override
Future<void> onLoad() async {
await super.onLoad();
camera.followVector2(Vector2.zero());
unawaited(
addFromBlueprint(Spaceship(position: Vector2.zero())),
);
}
@override
void onTapUp(TapUpInfo info) {
add(
Ball(baseColor: Colors.blue)
..initialPosition = info.eventPosition.game
..layer = Layer.jetpack,
);
}
}

@ -0,0 +1,13 @@
import 'package:dashbook/dashbook.dart';
import 'package:flame/game.dart';
import 'package:sandbox/common/common.dart';
import 'package:sandbox/stories/spaceship/basic.dart';
void addSpaceshipStories(Dashbook dashbook) {
dashbook.storiesOf('Spaceship').add(
'Basic',
(context) => GameWidget(game: BasicSpaceship()),
codeLink: buildSourceLink('spaceship/basic.dart'),
info: BasicSpaceship.info,
);
}

@ -142,13 +142,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
geometry:
dependency: transitive
description:
path: "../../geometry"
relative: true
source: path
version: "1.0.0+1"
js:
dependency: transitive
description:

@ -1,5 +1,26 @@
import 'dart:ui';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart';
class MockCanvas extends Mock implements Canvas {}
class MockFilter extends Mock implements Filter {}
class MockFixture extends Mock implements Fixture {}
class MockBody extends Mock implements Body {}
class MockBall extends Mock implements Ball {}
class MockGame extends Mock implements Forge2DGame {}
class MockSpaceshipEntrance extends Mock implements SpaceshipEntrance {}
class MockSpaceshipHole extends Mock implements SpaceshipHole {}
class MockContact extends Mock implements Contact {}
class MockContactCallback extends Mock
implements ContactCallback<Object, Object> {}

@ -2,8 +2,7 @@
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockingjay/mockingjay.dart';
import 'package:pinball/game/game.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart';
@ -34,11 +33,11 @@ class TestRampOpeningBallContactCallback
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(PinballGameTest.create);
final flameTester = FlameTester(TestGame.new);
group('RampOpening', () {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(PinballGameTest.create);
final flameTester = FlameTester(TestGame.new);
flameTester.test(
'loads correctly',

@ -1,7 +1,6 @@
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../helpers/helpers.dart';
@ -11,10 +10,10 @@ void main() {
late Filter filterData;
late Fixture fixture;
late Body body;
late PinballGame game;
late Ball ball;
late SpaceshipEntrance entrance;
late SpaceshipHole hole;
late Forge2DGame game;
setUp(() {
filterData = MockFilter();
@ -25,7 +24,7 @@ void main() {
body = MockBody();
when(() => body.fixtures).thenReturn([fixture]);
game = MockPinballGame();
game = MockGame();
ball = MockBall();
when(() => ball.gameRef).thenReturn(game);

@ -1,10 +1,9 @@
import 'package:flame/components.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/flame/blueprint.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import '../helpers/helpers.dart';
import '../../helpers/helpers.dart';
class MyBlueprint extends Blueprint {
@override
@ -52,19 +51,19 @@ void main() {
});
test('components can be added to it', () {
final blueprint = MyBlueprint()..build(MockPinballGame());
final blueprint = MyBlueprint()..build(MockGame());
expect(blueprint.components.length, equals(3));
});
test('blueprints can be added to it', () {
final blueprint = MyComposedBlueprint()..build(MockPinballGame());
final blueprint = MyComposedBlueprint()..build(MockGame());
expect(blueprint.blueprints.length, equals(3));
});
test('adds the components to a game on attach', () {
final mockGame = MockPinballGame();
final mockGame = MockGame();
when(() => mockGame.addAll(any())).thenAnswer((_) async {});
MyBlueprint().attach(mockGame);
@ -72,7 +71,7 @@ void main() {
});
test('adds components from a child Blueprint the to a game on attach', () {
final mockGame = MockPinballGame();
final mockGame = MockGame();
when(() => mockGame.addAll(any())).thenAnswer((_) async {});
MyComposedBlueprint().attach(mockGame);
@ -82,7 +81,7 @@ void main() {
test(
'throws assertion error when adding to an already attached blueprint',
() async {
final mockGame = MockPinballGame();
final mockGame = MockGame();
when(() => mockGame.addAll(any())).thenAnswer((_) async {});
final blueprint = MyBlueprint();
await blueprint.attach(mockGame);
@ -99,13 +98,13 @@ void main() {
});
test('callbacks can be added to it', () {
final blueprint = MyForge2dBlueprint()..build(MockPinballGame());
final blueprint = MyForge2dBlueprint()..build(MockGame());
expect(blueprint.callbacks.length, equals(3));
});
test('adds the callbacks to a game on attach', () async {
final mockGame = MockPinballGame();
final mockGame = MockGame();
when(() => mockGame.addAll(any())).thenAnswer((_) async {});
when(() => mockGame.addContactCallback(any())).thenAnswer((_) async {});
await MyForge2dBlueprint().attach(mockGame);
@ -116,7 +115,7 @@ void main() {
test(
'throws assertion error when adding to an already attached blueprint',
() async {
final mockGame = MockPinballGame();
final mockGame = MockGame();
when(() => mockGame.addAll(any())).thenAnswer((_) async {});
when(() => mockGame.addContactCallback(any())).thenAnswer((_) async {});
final blueprint = MyForge2dBlueprint();
Loading…
Cancel
Save