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