mirror of https://github.com/flutter/pinball.git
parent
31a92c0a38
commit
5019fe1701
@ -1,2 +0,0 @@
|
||||
export 'alien_bumper_contact_behavior.dart';
|
||||
export 'alien_bumper_sprite_behavior.dart';
|
@ -1,82 +0,0 @@
|
||||
// ignore_for_file: avoid_renaming_method_parameters
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
/// {@template google_word}
|
||||
/// Loads all [GoogleLetter]s to compose a [GoogleWord].
|
||||
/// {@endtemplate}
|
||||
class GoogleWord extends Component
|
||||
with HasGameRef<PinballGame>, Controls<_GoogleWordController> {
|
||||
/// {@macro google_word}
|
||||
GoogleWord({
|
||||
required Vector2 position,
|
||||
}) : _position = position {
|
||||
controller = _GoogleWordController(this);
|
||||
}
|
||||
|
||||
final Vector2 _position;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
final offsets = [
|
||||
Vector2(-12.92, 1.82),
|
||||
Vector2(-8.33, -0.65),
|
||||
Vector2(-2.88, -1.75),
|
||||
Vector2(2.88, -1.75),
|
||||
Vector2(8.33, -0.65),
|
||||
Vector2(12.92, 1.82),
|
||||
];
|
||||
|
||||
final letters = <GoogleLetter>[];
|
||||
for (var index = 0; index < offsets.length; index++) {
|
||||
letters.add(
|
||||
GoogleLetter(index)..initialPosition = _position + offsets[index],
|
||||
);
|
||||
}
|
||||
|
||||
await addAll(letters);
|
||||
}
|
||||
}
|
||||
|
||||
class _GoogleWordController extends ComponentController<GoogleWord>
|
||||
with HasGameRef<PinballGame> {
|
||||
_GoogleWordController(GoogleWord googleWord) : super(googleWord);
|
||||
|
||||
final _activatedLetters = <GoogleLetter>{};
|
||||
|
||||
void activate(GoogleLetter googleLetter) {
|
||||
if (!_activatedLetters.add(googleLetter)) return;
|
||||
|
||||
googleLetter.activate();
|
||||
|
||||
final activatedBonus = _activatedLetters.length == 6;
|
||||
if (activatedBonus) {
|
||||
gameRef.audio.googleBonus();
|
||||
gameRef.read<GameBloc>().add(const BonusActivated(GameBonus.googleWord));
|
||||
component.children.whereType<GoogleLetter>().forEach(
|
||||
(letter) => letter.deactivate(),
|
||||
);
|
||||
_activatedLetters.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Activates a [GoogleLetter] when it contacts with a [Ball].
|
||||
// TODO(alestiago): Add animation behaviour.
|
||||
// class _GoogleLetterBallContactCallback
|
||||
// extends ContactCallback<GoogleLetter, Ball> {
|
||||
// @override
|
||||
// void begin(GoogleLetter googleLetter, _, __) {
|
||||
// final parent = googleLetter.parent;
|
||||
// if (parent is GoogleWord) {
|
||||
// parent.controller.activate(googleLetter);
|
||||
// }
|
||||
// }
|
||||
// }
|
@ -0,0 +1 @@
|
||||
export 'bonus_behaviour.dart';
|
@ -0,0 +1,37 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
class BonusBehaviour extends Component
|
||||
with HasGameRef<PinballGame>, ParentIsA<GoogleWord> {
|
||||
BonusBehaviour(
|
||||
Iterable<GoogleLetter> googleLetters,
|
||||
) : _googleLetters = googleLetters;
|
||||
|
||||
Iterable<GoogleLetter> _googleLetters;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
for (final letter in _googleLetters) {
|
||||
letter.bloc.stream.listen((_) {
|
||||
final achievedBonus = _googleLetters
|
||||
.every((letter) => letter.bloc.state == GoogleLetterState.active);
|
||||
|
||||
if (achievedBonus) {
|
||||
gameRef.audio.googleBonus();
|
||||
gameRef
|
||||
.read<GameBloc>()
|
||||
.add(const BonusActivated(GameBonus.googleWord));
|
||||
for (final letter in _googleLetters) {
|
||||
letter.bloc.onReset();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
// ignore_for_file: avoid_renaming_method_parameters
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball/game/components/google_word/behaviors/behaviors.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
/// {@template google_word}
|
||||
/// Loads all [GoogleLetter]s to compose a [GoogleWord].
|
||||
/// {@endtemplate}
|
||||
class GoogleWord extends Component with HasGameRef<PinballGame> {
|
||||
/// {@macro google_word}
|
||||
GoogleWord({
|
||||
required Vector2 position,
|
||||
}) : _position = position;
|
||||
|
||||
final Vector2 _position;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
final letters = [
|
||||
GoogleLetter(0)..initialPosition = _position + Vector2(-12.92, 1.82),
|
||||
GoogleLetter(1)..initialPosition = _position + Vector2(-8.33, -0.65),
|
||||
GoogleLetter(2)..initialPosition = _position + Vector2(-2.88, -1.75),
|
||||
GoogleLetter(3)..initialPosition = _position + Vector2(2.88, -1.75),
|
||||
GoogleLetter(4)..initialPosition = _position + Vector2(8.33, -0.65),
|
||||
GoogleLetter(5)..initialPosition = _position + Vector2(12.92, 1.82)
|
||||
];
|
||||
await addAll([
|
||||
...letters,
|
||||
BonusBehaviour(letters),
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export 'contact_behavior.dart';
|
||||
export 'sprite_behavior.dart';
|
@ -0,0 +1,33 @@
|
||||
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';
|
||||
|
||||
class ContactBehavior extends Component
|
||||
with ContactCallbacks, ParentIsA<AlienBumper> {
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
// TODO(alestiago): Consider defining a generic ContactBehaviour to get
|
||||
// rid of this repeated logic.
|
||||
final userData = parent.body.userData;
|
||||
if (userData is ContactCallbacksGroup) {
|
||||
userData.addContactCallbacks(this);
|
||||
} else if (userData is ContactCallbacks) {
|
||||
final notifier = ContactCallbacksGroup()
|
||||
..addContactCallbacks(userData)
|
||||
..addContactCallbacks(this);
|
||||
parent.body.userData = notifier;
|
||||
} else {
|
||||
parent.body.userData = this;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void beginContact(Object other, Contact contact) {
|
||||
super.beginContact(other, contact);
|
||||
if (other is! Ball) return;
|
||||
parent.bloc.onBallContacted();
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
part 'alien_bumper_state.dart';
|
||||
|
||||
class AlienBumperCubit extends Cubit<AlienBumperState> {
|
||||
AlienBumperCubit() : super(AlienBumperState.active);
|
||||
|
||||
void onBallContacted() {
|
||||
emit(AlienBumperState.inactive);
|
||||
// Future<void>.delayed(const Duration(milliseconds: 500)).whenComplete(
|
||||
// () => emit(AlienBumperState.active),
|
||||
// );
|
||||
}
|
||||
|
||||
void onAnimated() {
|
||||
emit(AlienBumperState.active);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
part of 'alien_bumper_cubit.dart';
|
||||
|
||||
/// Indicates the [AlienBumperCubit]'s current state.
|
||||
enum AlienBumperState {
|
||||
/// A lit up bumper.
|
||||
active,
|
||||
|
||||
/// A dimmed bumper.
|
||||
inactive,
|
||||
}
|
@ -0,0 +1 @@
|
||||
export 'contact_behavior.dart';
|
@ -0,0 +1,33 @@
|
||||
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';
|
||||
|
||||
class ContactBehavior extends Component
|
||||
with ContactCallbacks, ParentIsA<GoogleLetter> {
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
// TODO(alestiago): Consider defining a generic ContactBehaviour to get
|
||||
// rid of this repeated logic.
|
||||
final userData = parent.body.userData;
|
||||
if (userData is ContactCallbacksGroup) {
|
||||
userData.addContactCallbacks(this);
|
||||
} else if (userData is ContactCallbacks) {
|
||||
final notifier = ContactCallbacksGroup()
|
||||
..addContactCallbacks(userData)
|
||||
..addContactCallbacks(this);
|
||||
parent.body.userData = notifier;
|
||||
} else {
|
||||
parent.body.userData = this;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void beginContact(Object other, Contact contact) {
|
||||
super.beginContact(other, contact);
|
||||
if (other is! Ball) return;
|
||||
parent.bloc.onBallContacted();
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
|
||||
part 'google_letter_state.dart';
|
||||
|
||||
class GoogleLetterCubit extends Cubit<GoogleLetterState> {
|
||||
GoogleLetterCubit() : super(GoogleLetterState.inactive);
|
||||
|
||||
void onBallContacted() {
|
||||
emit(GoogleLetterState.active);
|
||||
}
|
||||
|
||||
void onReset() {
|
||||
emit(GoogleLetterState.inactive);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
part of 'google_letter_cubit.dart';
|
||||
|
||||
enum GoogleLetterState {
|
||||
active,
|
||||
|
||||
inactive,
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export 'contact_behavior.dart';
|
||||
export 'sprite_behavior.dart';
|
@ -0,0 +1,41 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
/// {@template alien_bumper_sprite_behavior}
|
||||
///
|
||||
/// {@endtemplate}
|
||||
class SpriteBehavior extends TimerComponent with ParentIsA<SparkyBumper> {
|
||||
/// {@macro alien_bumper_sprite_behavior}
|
||||
SpriteBehavior()
|
||||
: super(
|
||||
period: 0.05,
|
||||
removeOnFinish: false,
|
||||
);
|
||||
|
||||
void _onNewState(SparkyBumperState state) {
|
||||
switch (state) {
|
||||
case SparkyBumperState.active:
|
||||
timer.stop();
|
||||
break;
|
||||
case SparkyBumperState.inactive:
|
||||
timer
|
||||
..reset()
|
||||
..start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
timer.stop();
|
||||
parent.bloc.stream.listen(_onNewState);
|
||||
}
|
||||
|
||||
@override
|
||||
void onTick() {
|
||||
super.onTick();
|
||||
parent.bloc.onAnimated();
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
part 'sparky_bumper_state.dart';
|
||||
|
||||
class SparkyBumperCubit extends Cubit<SparkyBumperState> {
|
||||
SparkyBumperCubit() : super(SparkyBumperState.active);
|
||||
|
||||
void onBallContacted() {
|
||||
emit(SparkyBumperState.inactive);
|
||||
// Future<void>.delayed(const Duration(milliseconds: 500)).whenComplete(
|
||||
// () => emit(AlienBumperState.active),
|
||||
// );
|
||||
}
|
||||
|
||||
void onAnimated() {
|
||||
emit(SparkyBumperState.active);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
part of 'sparky_bumper_cubit.dart';
|
||||
|
||||
/// Indicates the [SparkyBumperCubit]'s current state.
|
||||
enum SparkyBumperState {
|
||||
/// A lit up bumper.
|
||||
active,
|
||||
|
||||
/// A dimmed bumper.
|
||||
inactive,
|
||||
}
|
Loading…
Reference in new issue