refactor: controlled spaceshipramp with new blueprint

feat/spaceship-ramp-logic
RuiAlonso 2 years ago
parent 6439b54c18
commit bcb0035687

@ -1,5 +1,6 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'dart:collection';
import 'dart:math' as math;
import 'package:flame/components.dart';
@ -10,13 +11,13 @@ import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
/// {@template controlled_spaceship_ramp}
/// [SpaceshipRamp] with a [_SpaceshipRampController] attached.
/// [SpaceshipRamp] with a [SpaceshipRampController] attached.
/// {@endtemplate}
class ControlledSpaceshipRamp extends Component
with Controls<_SpaceshipRampController>, HasGameRef<PinballGame> {
with Controls<SpaceshipRampController>, HasGameRef<PinballGame> {
/// {@macro controlled_spaceship_ramp}
ControlledSpaceshipRamp() {
controller = _SpaceshipRampController(this);
controller = SpaceshipRampController(this);
}
late final SpaceshipRamp _spaceshipRamp;
@ -27,11 +28,13 @@ class ControlledSpaceshipRamp extends Component
gameRef.addContactCallback(SpaceshipRampSensorBallContactCallback());
_spaceshipRamp = SpaceshipRamp();
final spaceshipRampSensor = SpaceshipRampSensor()
..initialPosition = Vector2(1.7, -20);
await gameRef.addFromBlueprint(_spaceshipRamp);
await add(spaceshipRampSensor);
await addFromBlueprint(_spaceshipRamp);
await addAll([
SpaceshipRampSensor(type: SpaceshipRampSensorType.door)
..initialPosition = Vector2(1.7, -20),
SpaceshipRampSensor(type: SpaceshipRampSensorType.inside)
..initialPosition = Vector2(1.7, -21.5),
]);
}
}
@ -40,11 +43,11 @@ class ControlledSpaceshipRamp extends Component
/// logic.
/// {@endtemplate}
class _SpaceshipRampController
class SpaceshipRampController
extends ComponentController<ControlledSpaceshipRamp>
with HasGameRef<PinballGame> {
/// {@macro spaceship_ramp_controller}
_SpaceshipRampController(ControlledSpaceshipRamp controlledSpaceshipRamp)
SpaceshipRampController(ControlledSpaceshipRamp controlledSpaceshipRamp)
: super(controlledSpaceshipRamp);
final int _oneMillionPointsTarget = 10;
@ -59,50 +62,27 @@ class _SpaceshipRampController
// TODO(ruimiguel): increase score multiplier x1 .
print('Multiplier x1');
gameRef.read<GameBloc>().add(const Scored(points: 100));
if (_hitsCounter % _scoreMultiplierTarget == 0) {
// TODO(ruimiguel): reset score multiplier and multiply score x6 .
print('Reset multiplier and multiply score x6');
}
if (_hitsCounter % _oneMillionPointsTarget == 0) {
gameRef.read<GameBloc>().add(const Scored(points: 1000000));
}
}
}
/// {@template spaceship_ramp_sensor}
/// Small sensor body used to detect when a ball has entered the
/// [SpaceshipRamp] with the [SpaceshipRampSensorBallContactCallback].
/// {@endtemplate}
@visibleForTesting
class SpaceshipRampSensor extends BodyComponent with InitialPosition {
/// {@macro spaceship_ramp_sensor}
SpaceshipRampSensor() {
renderBody = true;
}
@override
Body createBody() {
final shape = PolygonShape()
..setAsBox(
2,
.1,
initialPosition,
-5 * math.pi / 180,
const oneMillion = 1000000;
gameRef.read<GameBloc>().add(const Scored(points: oneMillion));
gameRef.add(
ScoreText(
text: oneMillion.toString(),
position: Vector2(1.7, -20),
),
);
final fixtureDef = FixtureDef(shape)..isSensor = true;
final bodyDef = BodyDef()
..position = initialPosition
..userData = this;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}
}
/// {@template spaceship_ramp_sensor_ball_contact_callback}
/// Turbo charges the [Ball] on contact with [SparkyTurboChargeSensor].
/// Turbo charges the [Ball] on contact with [SpaceshipRampSensor].
/// {@endtemplate}
@visibleForTesting
class SpaceshipRampSensorBallContactCallback
@ -110,15 +90,35 @@ class SpaceshipRampSensorBallContactCallback
/// {@macro spaceship_ramp_sensor_ball_contact_callback}
SpaceshipRampSensorBallContactCallback();
final Set<Ball> _balls = HashSet();
@override
void begin(
SpaceshipRampSensor spaceshipRampSensor,
_,
ControlledBall ball,
__,
) {
final parent = spaceshipRampSensor.parent;
if (parent is ControlledSpaceshipRamp) {
parent.controller.shot();
switch (spaceshipRampSensor.type) {
case SpaceshipRampSensorType.door:
print('door');
if (!_balls.contains(ball)) {
print('add new ball');
_balls.add(ball);
}
break;
case SpaceshipRampSensorType.inside:
print('inside');
if (_balls.contains(ball)) {
print('ball is in');
final parent = spaceshipRampSensor.parent;
print('parent $parent');
if (parent is ControlledSpaceshipRamp) {
parent.controller.shot();
}
print('remove ball');
_balls.remove(ball);
}
break;
}
}
}

@ -382,3 +382,41 @@ class _SpaceshipRampOpening extends LayerSensor {
);
}
}
enum SpaceshipRampSensorType {
door,
inside,
}
/// {@template spaceship_ramp_sensor}
/// Small sensor body used to detect when a ball has entered the
/// [SpaceshipRamp].
/// {@endtemplate}
class SpaceshipRampSensor extends BodyComponent with InitialPosition, Layered {
/// {@macro spaceship_ramp_sensor}
SpaceshipRampSensor({required this.type}) {
layer = Layer.spaceshipEntranceRamp;
renderBody = false;
}
final SpaceshipRampSensorType type;
@override
Body createBody() {
final shape = PolygonShape()
..setAsBox(
2,
.1,
initialPosition,
-5 * math.pi / 180,
);
final fixtureDef = FixtureDef(shape)..isSensor = true;
final bodyDef = BodyDef()
..position = initialPosition
..userData = this;
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}

@ -0,0 +1,116 @@
// ignore_for_file: cascade_invocations
import 'package:bloc_test/bloc_test.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter/rendering.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';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final assets = [
Assets.images.spaceship.ramp.boardOpening.keyName,
Assets.images.spaceship.ramp.railingForeground.keyName,
Assets.images.spaceship.ramp.railingBackground.keyName,
Assets.images.spaceship.ramp.main.keyName,
Assets.images.spaceship.ramp.arrow.inactive.keyName,
Assets.images.spaceship.ramp.arrow.active1.keyName,
Assets.images.spaceship.ramp.arrow.active2.keyName,
Assets.images.spaceship.ramp.arrow.active3.keyName,
Assets.images.spaceship.ramp.arrow.active4.keyName,
Assets.images.spaceship.ramp.arrow.active5.keyName,
];
final flameTester = FlameTester(() => EmptyPinballTestGame(assets));
group('ControlledSpaceshipRamp', () {
flameTester.test(
'loads correctly',
(game) async {
final controlledSpaceshipRamp = ControlledSpaceshipRamp();
await game.ensureAdd(controlledSpaceshipRamp);
expect(game.contains(controlledSpaceshipRamp), isTrue);
},
);
group('loads', () {
flameTester.test(
'a SpaceshipRamp',
(game) async {
final controlledSpaceshipRamp = ControlledSpaceshipRamp();
await game.ensureAdd(controlledSpaceshipRamp);
expect(
controlledSpaceshipRamp
.descendants()
.whereType<SpaceshipRamp>()
.length,
equals(1),
);
},
);
flameTester.test(
'two SpaceshipRampSensor',
(game) async {
final controlledSpaceshipRamp = ControlledSpaceshipRamp();
await game.ensureAdd(controlledSpaceshipRamp);
expect(
controlledSpaceshipRamp
.descendants()
.whereType<SpaceshipRampSensor>()
.length,
equals(2),
);
},
);
});
});
group('SpaceshipRampController', () {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(EmptyPinballTestGame.new);
late ControlledSpaceshipRamp controlledSpaceshipRamp;
setUp(() {
controlledSpaceshipRamp = ControlledSpaceshipRamp();
});
test('can be instantiated', () {
expect(
SpaceshipRampController(controlledSpaceshipRamp),
isA<SpaceshipRampController>(),
);
});
group('shot', () {});
flameTester.testGameWidget(
'SpaceshipRampSensorBallContactCallback turbo charges the ball',
setUp: (game, tester) async {
final controlledSpaceshipRamp = MockControlledSpaceshipRamp();
final controller = MockSpaceshipRampController();
final contactCallback = SpaceshipRampSensorBallContactCallback();
final spaceshipRampSensor = MockSpaceshipRampSensor();
final ball = MockControlledBall();
when(() => spaceshipRampSensor.type)
.thenReturn(SpaceshipRampSensorType.door);
when(() => spaceshipRampSensor.parent)
.thenReturn(controlledSpaceshipRamp);
when(() => controlledSpaceshipRamp.controller).thenReturn(controller);
when(controller.shot).thenAnswer((_) async {});
contactCallback.begin(spaceshipRampSensor, ball, MockContact());
verify(controller.shot).called(1);
},
);
});
}

@ -71,6 +71,14 @@ class MockPinballAudio extends Mock implements PinballAudio {}
class MockSparkyComputerSensor extends Mock implements SparkyComputerSensor {}
class MockControlledSpaceshipRamp extends Mock
implements ControlledSpaceshipRamp {}
class MockSpaceshipRampController extends Mock
implements SpaceshipRampController {}
class MockSpaceshipRampSensor extends Mock implements SpaceshipRampSensor {}
class MockAssetsManagerCubit extends Mock implements AssetsManagerCubit {}
class MockBackboard extends Mock implements Backboard {}

Loading…
Cancel
Save