mirror of https://github.com/flutter/pinball.git
commit
408bbb5db2
Before Width: | Height: | Size: 11 KiB |
@ -0,0 +1,26 @@
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:pinball/game/components/components.dart';
|
||||
import 'package:pinball_components/pinball_components.dart' hide Assets;
|
||||
|
||||
/// {@template launcher}
|
||||
/// A [Blueprint] which creates the [Plunger], [RocketSpriteComponent] and
|
||||
/// [LaunchRamp].
|
||||
/// {@endtemplate}
|
||||
class Launcher extends Forge2DBlueprint {
|
||||
/// {@macro launcher}
|
||||
Launcher();
|
||||
|
||||
/// [Plunger] to launch the [Ball] onto the board.
|
||||
late final Plunger plunger;
|
||||
|
||||
@override
|
||||
void build(Forge2DGame gameRef) {
|
||||
plunger = ControlledPlunger(compressionDistance: 12.3)
|
||||
..initialPosition = Vector2(40.1, -38);
|
||||
|
||||
final _rocket = RocketSpriteComponent()..position = Vector2(43, 62);
|
||||
|
||||
addAll([_rocket, plunger]);
|
||||
addBlueprint(LaunchRamp());
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
|
||||
part 'start_game_event.dart';
|
||||
part 'start_game_state.dart';
|
||||
|
||||
/// {@template start_game_bloc}
|
||||
/// Bloc that manages the app flow before the game starts.
|
||||
/// {@endtemplate}
|
||||
class StartGameBloc extends Bloc<StartGameEvent, StartGameState> {
|
||||
/// {@macro start_game_bloc}
|
||||
StartGameBloc({
|
||||
required PinballGame game,
|
||||
}) : _game = game,
|
||||
super(const StartGameState.initial()) {
|
||||
on<PlayTapped>(_onPlayTapped);
|
||||
on<CharacterSelected>(_onCharacterSelected);
|
||||
on<HowToPlayFinished>(_onHowToPlayFinished);
|
||||
}
|
||||
|
||||
final PinballGame _game;
|
||||
|
||||
void _onPlayTapped(
|
||||
PlayTapped event,
|
||||
Emitter<StartGameState> emit,
|
||||
) {
|
||||
_game.gameFlowController.start();
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: StartGameStatus.selectCharacter,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onCharacterSelected(
|
||||
CharacterSelected event,
|
||||
Emitter<StartGameState> emit,
|
||||
) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: StartGameStatus.howToPlay,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onHowToPlayFinished(
|
||||
HowToPlayFinished event,
|
||||
Emitter<StartGameState> emit,
|
||||
) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: StartGameStatus.play,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
part of 'start_game_bloc.dart';
|
||||
|
||||
/// {@template start_game_event}
|
||||
/// Event added during the start game flow.
|
||||
/// {@endtemplate}
|
||||
abstract class StartGameEvent extends Equatable {
|
||||
/// {@macro start_game_event}
|
||||
const StartGameEvent();
|
||||
}
|
||||
|
||||
/// {@template play_tapped}
|
||||
/// Play tapped event.
|
||||
/// {@endtemplate}
|
||||
class PlayTapped extends StartGameEvent {
|
||||
/// {@macro play_tapped}
|
||||
const PlayTapped();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
/// {@template character_selected}
|
||||
/// Character selected event.
|
||||
/// {@endtemplate}
|
||||
class CharacterSelected extends StartGameEvent {
|
||||
/// {@macro character_selected}
|
||||
const CharacterSelected();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
/// {@template how_to_play_finished}
|
||||
/// How to play finished event.
|
||||
/// {@endtemplate}
|
||||
class HowToPlayFinished extends StartGameEvent {
|
||||
/// {@macro how_to_play_finished}
|
||||
const HowToPlayFinished();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
part of 'start_game_bloc.dart';
|
||||
|
||||
/// Defines status of start game flow.
|
||||
enum StartGameStatus {
|
||||
/// Initial status.
|
||||
initial,
|
||||
|
||||
/// Selection characters status.
|
||||
selectCharacter,
|
||||
|
||||
/// How to play status.
|
||||
howToPlay,
|
||||
|
||||
/// Play status.
|
||||
play,
|
||||
}
|
||||
|
||||
/// {@template start_game_state}
|
||||
/// Represents the state of flow before the game starts.
|
||||
/// {@endtemplate}
|
||||
class StartGameState extends Equatable {
|
||||
/// {@macro start_game_state}
|
||||
const StartGameState({
|
||||
required this.status,
|
||||
});
|
||||
|
||||
/// Initial [StartGameState].
|
||||
const StartGameState.initial() : this(status: StartGameStatus.initial);
|
||||
|
||||
/// Status of [StartGameState].
|
||||
final StartGameStatus status;
|
||||
|
||||
/// Creates a copy of [StartGameState].
|
||||
StartGameState copyWith({
|
||||
StartGameStatus? status,
|
||||
}) {
|
||||
return StartGameState(
|
||||
status: status ?? this.status,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props => [status];
|
||||
}
|
@ -0,0 +1 @@
|
||||
export 'bloc/start_game_bloc.dart';
|
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,24 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball_components/gen/assets.gen.dart';
|
||||
import 'package:pinball_components/pinball_components.dart' hide Assets;
|
||||
|
||||
/// {@template rocket_sprite_component}
|
||||
/// A [SpriteComponent] for the rocket over [Plunger].
|
||||
/// {@endtemplate}
|
||||
class RocketSpriteComponent extends SpriteComponent with HasGameRef {
|
||||
// TODO(ruimiguel): change this priority to be over launcher ramp and bottom
|
||||
// wall.
|
||||
/// {@macro rocket_sprite_component}
|
||||
RocketSpriteComponent() : super(priority: 5);
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
final sprite = await gameRef.loadSprite(
|
||||
Assets.images.plunger.rocket.keyName,
|
||||
);
|
||||
this.sprite = sprite;
|
||||
size = sprite.originalSize / 10;
|
||||
anchor = Anchor.center;
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 57 KiB |
@ -0,0 +1,28 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
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() {
|
||||
group('RocketSpriteComponent', () {
|
||||
final tester = FlameTester(TestGame.new);
|
||||
|
||||
tester.testGameWidget(
|
||||
'renders correctly',
|
||||
setUp: (game, tester) async {
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
await game.ensureAdd(RocketSpriteComponent());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/plunger/rocket.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
import 'package:bloc_test/bloc_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball/start_game/bloc/start_game_bloc.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
late PinballGame pinballGame;
|
||||
|
||||
setUp(() {
|
||||
pinballGame = MockPinballGame();
|
||||
|
||||
when(
|
||||
() => pinballGame.gameFlowController,
|
||||
).thenReturn(
|
||||
MockGameFlowController(),
|
||||
);
|
||||
});
|
||||
|
||||
group('StartGameBloc', () {
|
||||
blocTest<StartGameBloc, StartGameState>(
|
||||
'on PlayTapped changes status to selectCharacter',
|
||||
build: () => StartGameBloc(
|
||||
game: pinballGame,
|
||||
),
|
||||
act: (bloc) => bloc.add(const PlayTapped()),
|
||||
expect: () => [
|
||||
const StartGameState(
|
||||
status: StartGameStatus.selectCharacter,
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
blocTest<StartGameBloc, StartGameState>(
|
||||
'on CharacterSelected changes status to howToPlay',
|
||||
build: () => StartGameBloc(
|
||||
game: pinballGame,
|
||||
),
|
||||
act: (bloc) => bloc.add(const CharacterSelected()),
|
||||
expect: () => [
|
||||
const StartGameState(
|
||||
status: StartGameStatus.howToPlay,
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
blocTest<StartGameBloc, StartGameState>(
|
||||
'on HowToPlayFinished changes status to play',
|
||||
build: () => StartGameBloc(
|
||||
game: pinballGame,
|
||||
),
|
||||
act: (bloc) => bloc.add(const HowToPlayFinished()),
|
||||
expect: () => [
|
||||
const StartGameState(
|
||||
status: StartGameStatus.play,
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball/start_game/bloc/start_game_bloc.dart';
|
||||
|
||||
void main() {
|
||||
group('StartGameEvent', () {
|
||||
test('PlayTapped supports value equality', () {
|
||||
expect(
|
||||
PlayTapped(),
|
||||
equals(PlayTapped()),
|
||||
);
|
||||
});
|
||||
|
||||
test('CharacterSelected supports value equality', () {
|
||||
expect(
|
||||
CharacterSelected(),
|
||||
equals(CharacterSelected()),
|
||||
);
|
||||
});
|
||||
|
||||
test('HowToPlayFinished supports value equality', () {
|
||||
expect(
|
||||
HowToPlayFinished(),
|
||||
equals(HowToPlayFinished()),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball/start_game/bloc/start_game_bloc.dart';
|
||||
|
||||
void main() {
|
||||
group('StartGameState', () {
|
||||
final testState = StartGameState(
|
||||
status: StartGameStatus.selectCharacter,
|
||||
);
|
||||
|
||||
test('initial state has correct values', () {
|
||||
final state = StartGameState(
|
||||
status: StartGameStatus.initial,
|
||||
);
|
||||
|
||||
expect(state, StartGameState.initial());
|
||||
});
|
||||
|
||||
test('supports value equality', () {
|
||||
final secondState = StartGameState(
|
||||
status: StartGameStatus.selectCharacter,
|
||||
);
|
||||
|
||||
expect(testState, secondState);
|
||||
});
|
||||
|
||||
test('supports copyWith', () {
|
||||
final secondState = testState.copyWith();
|
||||
|
||||
expect(testState, secondState);
|
||||
});
|
||||
|
||||
test('has correct props', () {
|
||||
expect(
|
||||
testState.props,
|
||||
equals([
|
||||
StartGameStatus.selectCharacter,
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in new issue