Merge branch 'main' into feat/game-bloc-multiplier

pull/213/head
RuiAlonso 3 years ago
commit a3306d7219

@ -29,9 +29,12 @@ void main() {
'loads correctly',
(game) async {
final spaceshipRamp = SpaceshipRamp();
await game.ensureAdd(spaceshipRamp);
await game.addFromBlueprint(spaceshipRamp);
await game.ready();
expect(game.contains(spaceshipRamp), isTrue);
for (final component in spaceshipRamp.components) {
expect(game.contains(component), isTrue);
}
},
);

@ -3,3 +3,4 @@ library pinball_flame;
export 'src/blueprint.dart';
export 'src/component_controller.dart';
export 'src/keyboard_input_controller.dart';
export 'src/sprite_animation.dart';

@ -1,16 +1,13 @@
import 'package:flame/components.dart';
import 'package:flame/game.dart';
// TODO(erickzanardo): Keeping this inside our code base
// so we can experiment with the idea, but this is a
// potential upstream change on Flame.
// TODO(erickzanardo): Keeping this inside our code base so we can experiment
// with the idea, but this is a potential upstream change on Flame.
/// {@template blueprint}
/// A [Blueprint] is a virtual way of grouping [Component]s that are related,
/// but they need to be added directly on the [FlameGame] level.
/// A [Blueprint] is a virtual way of grouping [Component]s that are related.
/// {@endtemplate blueprint}
// TODO(alestiago): refactor with feat/make-blueprint-extend-component.
class Blueprint extends Component {
class Blueprint {
/// {@macro blueprint}
Blueprint({
Iterable<Component>? components,
@ -27,7 +24,7 @@ class Blueprint extends Component {
final List<Component> _components = [];
final List<Component> _blueprints = [];
final List<Blueprint> _blueprints = [];
Future<void> _addToParent(Component parent) async {
await parent.addAll(_components);
@ -37,7 +34,7 @@ class Blueprint extends Component {
List<Component> get components => List.unmodifiable(_components);
/// Returns a copy of the blueprints built by this blueprint.
List<Component> get blueprints => List.unmodifiable(_blueprints);
List<Blueprint> get blueprints => List.unmodifiable(_blueprints);
}
/// Adds helper methods regarding [Blueprint]s to [FlameGame].

@ -0,0 +1,102 @@
// ignore_for_file: public_member_api_docs
import 'dart:math';
import 'package:flame/components.dart';
import 'package:flame/image_composition.dart';
import 'package:flutter/material.dart' hide Animation;
/// {@template flame.widgets.sprite_animation_widget}
/// A [StatelessWidget] that renders a [SpriteAnimation].
/// {@endtemplate}
// TODO(arturplaczek): Remove when this PR will be merged.
// https://github.com/flame-engine/flame/pull/1552
class SpriteAnimationWidget extends StatelessWidget {
/// {@macro flame.widgets.sprite_animation_widget}
const SpriteAnimationWidget({
required this.controller,
this.anchor = Anchor.topLeft,
Key? key,
}) : super(key: key);
/// The positioning [Anchor].
final Anchor anchor;
final SpriteAnimationController controller;
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: controller,
builder: (_, __) {
return CustomPaint(
painter: SpritePainter(
controller.animation.getSprite(),
anchor,
),
);
},
);
}
}
class SpriteAnimationController extends AnimationController {
SpriteAnimationController({
required TickerProvider vsync,
required this.animation,
}) : super(vsync: vsync) {
duration = Duration(seconds: animation.totalDuration().ceil());
}
final SpriteAnimation animation;
double? _lastUpdated;
@override
void notifyListeners() {
super.notifyListeners();
final now = DateTime.now().millisecond.toDouble();
final dt = max<double>(0, (now - (_lastUpdated ?? 0)) / 1000);
animation.update(dt);
_lastUpdated = now;
}
}
class SpritePainter extends CustomPainter {
SpritePainter(
this._sprite,
this._anchor, {
double angle = 0,
}) : _angle = angle;
final Sprite _sprite;
final Anchor _anchor;
final double _angle;
@override
bool shouldRepaint(SpritePainter oldDelegate) {
return oldDelegate._sprite != _sprite ||
oldDelegate._anchor != _anchor ||
oldDelegate._angle != _angle;
}
@override
void paint(Canvas canvas, Size size) {
final boxSize = size.toVector2();
final rate = boxSize.clone()..divide(_sprite.srcSize);
final minRate = min(rate.x, rate.y);
final paintSize = _sprite.srcSize * minRate;
final anchorPosition = _anchor.toVector2();
final boxAnchorPosition = boxSize.clone()..multiply(anchorPosition);
final spriteAnchorPosition = anchorPosition..multiply(paintSize);
canvas
..translateVector(boxAnchorPosition..sub(spriteAnchorPosition))
..renderRotated(
_angle,
spriteAnchorPosition,
(canvas) => _sprite.render(canvas, size: paintSize),
);
}
}

@ -0,0 +1,74 @@
import 'package:flame/components.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball_flame/pinball_flame.dart';
class MockSpriteAnimationController extends Mock
implements SpriteAnimationController {}
class MockSpriteAnimation extends Mock implements SpriteAnimation {}
class MockSprite extends Mock implements Sprite {}
// TODO(arturplaczek): Remove when this PR will be merged.
// https://github.com/flame-engine/flame/pull/1552
void main() {
group('PinballSpriteAnimationWidget', () {
late SpriteAnimationController controller;
late SpriteAnimation animation;
late Sprite sprite;
setUp(() {
controller = MockSpriteAnimationController();
animation = MockSpriteAnimation();
sprite = MockSprite();
when(() => controller.animation).thenAnswer((_) => animation);
when(() => animation.totalDuration()).thenAnswer((_) => 1);
when(() => animation.getSprite()).thenAnswer((_) => sprite);
when(() => sprite.srcSize).thenAnswer((_) => Vector2(1, 1));
when(() => sprite.srcSize).thenAnswer((_) => Vector2(1, 1));
});
testWidgets('renders correctly', (tester) async {
await tester.pumpWidget(
SpriteAnimationWidget(
controller: controller,
),
);
await tester.pumpAndSettle();
await tester.pumpAndSettle();
expect(find.byType(SpriteAnimationWidget), findsOneWidget);
});
test('SpriteAnimationController is updating animations', () {
SpriteAnimationController(
vsync: const TestVSync(),
animation: animation,
).notifyListeners();
verify(() => animation.update(any())).called(1);
});
testWidgets('SpritePainter shouldRepaint returns true when Sprite changed',
(tester) async {
final spritePainter = SpritePainter(
sprite,
Anchor.center,
angle: 45,
);
final anotherPainter = SpritePainter(
sprite,
Anchor.center,
angle: 30,
);
expect(spritePainter.shouldRepaint(anotherPainter), isTrue);
});
});
}

@ -27,8 +27,8 @@ void main() {
group('SparkyFireZone', () {
flameTester.test('loads correctly', (game) async {
final sparkyFireZone = SparkyFireZone();
await game.ensureAdd(sparkyFireZone);
await game.addFromBlueprint(SparkyFireZone());
await game.ready();
});
group('loads', () {

Loading…
Cancel
Save