refactor: moved gravity logic to `BallGravitatingBehavior` (#314)

pull/316/head
Alejandro Santiago 3 years ago committed by GitHub
parent c67db0e55c
commit 01dc3f387a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,6 +5,7 @@ import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/widgets.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/ball/behaviors/ball_gravitating_behavior.dart';
import 'package:pinball_components/src/components/ball/behaviors/ball_scaling_behavior.dart';
import 'package:pinball_flame/pinball_flame.dart';
@ -21,6 +22,7 @@ class Ball<T extends Forge2DGame> extends BodyComponent<T>
children: [
_BallSpriteComponent()..tint(baseColor.withOpacity(0.5)),
BallScalingBehavior(),
BallGravitatingBehavior(),
],
) {
// TODO(ruimiguel): while developing Ball can be launched by clicking mouse,
@ -86,31 +88,6 @@ class Ball<T extends Forge2DGame> extends BodyComponent<T>
body.linearVelocity = impulse;
await add(_TurboChargeSpriteAnimationComponent());
}
@override
void update(double dt) {
super.update(dt);
_setPositionalGravity();
}
void _setPositionalGravity() {
final defaultGravity = gameRef.world.gravity.y;
final maxXDeviationFromCenter = BoardDimensions.bounds.width / 2;
const maxXGravityPercentage =
(1 - BoardDimensions.perspectiveShrinkFactor) / 2;
final xDeviationFromCenter = body.position.x;
final positionalXForce = ((xDeviationFromCenter / maxXDeviationFromCenter) *
maxXGravityPercentage) *
defaultGravity;
final positionalYForce = math.sqrt(
math.pow(defaultGravity, 2) - math.pow(positionalXForce, 2),
);
body.gravityOverride = Vector2(positionalXForce, positionalYForce);
}
}
class _BallSpriteComponent extends SpriteComponent with HasGameRef {

@ -0,0 +1,35 @@
import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
/// Scales the ball's gravity according to its position on the board.
class BallGravitatingBehavior extends Component
with ParentIsA<Ball>, HasGameRef<Forge2DGame> {
@override
void update(double dt) {
super.update(dt);
final defaultGravity = gameRef.world.gravity.y;
final maxXDeviationFromCenter = BoardDimensions.bounds.width / 2;
const maxXGravityPercentage =
(1 - BoardDimensions.perspectiveShrinkFactor) / 2;
final xDeviationFromCenter = parent.body.position.x;
final positionalXForce = ((xDeviationFromCenter / maxXDeviationFromCenter) *
maxXGravityPercentage) *
defaultGravity;
final positionalYForce = math.sqrt(
math.pow(defaultGravity, 2) - math.pow(positionalXForce, 2),
);
final gravityOverride = parent.body.gravityOverride;
if (gravityOverride != null) {
gravityOverride.setValues(positionalXForce, positionalYForce);
} else {
parent.body.gravityOverride = Vector2(positionalXForce, positionalYForce);
}
}
}

@ -1 +1,2 @@
export 'ball_gravitating_behavior.dart';
export 'ball_scaling_behavior.dart';

@ -36,7 +36,8 @@ void main() {
},
);
flameTester.test('add a BallScalingBehavior', (game) async {
group('adds', () {
flameTester.test('a BallScalingBehavior', (game) async {
final ball = Ball(baseColor: baseColor);
await game.ensureAdd(ball);
expect(
@ -45,6 +46,16 @@ void main() {
);
});
flameTester.test('a BallGravitatingBehavior', (game) async {
final ball = Ball(baseColor: baseColor);
await game.ensureAdd(ball);
expect(
ball.descendants().whereType<BallGravitatingBehavior>().length,
equals(1),
);
});
});
group('body', () {
flameTester.test(
'is dynamic',

@ -0,0 +1,63 @@
// ignore_for_file: cascade_invocations
import 'dart:ui';
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 'package:pinball_components/src/components/ball/behaviors/behaviors.dart';
import '../../../../helpers/helpers.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final asset = Assets.images.ball.ball.keyName;
final flameTester = FlameTester(() => TestGame([asset]));
group('BallGravitatingBehavior', () {
const baseColor = Color(0xFFFFFFFF);
test('can be instantiated', () {
expect(
BallGravitatingBehavior(),
isA<BallGravitatingBehavior>(),
);
});
flameTester.test('can be loaded', (game) async {
final ball = Ball.test(baseColor: baseColor);
final behavior = BallGravitatingBehavior();
await ball.add(behavior);
await game.ensureAdd(ball);
expect(
ball.firstChild<BallGravitatingBehavior>(),
equals(behavior),
);
});
flameTester.test(
"overrides the body's horizontal gravity symmetrically",
(game) async {
final ball1 = Ball.test(baseColor: baseColor)
..initialPosition = Vector2(10, 0);
await ball1.add(BallGravitatingBehavior());
final ball2 = Ball.test(baseColor: baseColor)
..initialPosition = Vector2(-10, 0);
await ball2.add(BallGravitatingBehavior());
await game.ensureAddAll([ball1, ball2]);
game.update(1);
expect(
ball1.body.gravityOverride!.x,
equals(-ball2.body.gravityOverride!.x),
);
expect(
ball1.body.gravityOverride!.y,
equals(ball2.body.gravityOverride!.y),
);
},
);
});
}

@ -35,17 +35,6 @@ void main() {
);
});
flameTester.test('can be loaded', (game) async {
final ball = Ball.test(baseColor: baseColor);
final behavior = BallScalingBehavior();
await ball.add(behavior);
await game.ensureAdd(ball);
expect(
ball.firstChild<BallScalingBehavior>(),
equals(behavior),
);
});
flameTester.test('scales the shape radius', (game) async {
final ball1 = Ball.test(baseColor: baseColor)
..initialPosition = Vector2(0, 10);
@ -66,9 +55,9 @@ void main() {
);
});
flameTester.testGameWidget(
flameTester.test(
'scales the sprite',
setUp: (game, tester) async {
(game) async {
final ball1 = Ball.test(baseColor: baseColor)
..initialPosition = Vector2(0, 10);
await ball1.add(BallScalingBehavior());
@ -80,9 +69,6 @@ void main() {
await game.ensureAddAll([ball1, ball2]);
game.update(1);
await tester.pump();
await game.ready();
final sprite1 = ball1.firstChild<SpriteComponent>()!;
final sprite2 = ball2.firstChild<SpriteComponent>()!;
expect(

Loading…
Cancel
Save