diff --git a/lib/game/components/alien_zone.dart b/lib/game/components/alien_zone.dart new file mode 100644 index 00000000..3a78b74f --- /dev/null +++ b/lib/game/components/alien_zone.dart @@ -0,0 +1,90 @@ +// ignore_for_file: avoid_renaming_method_parameters + +import 'package:flame/components.dart'; +import 'package:flame_bloc/flame_bloc.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball/flame/flame.dart'; +import 'package:pinball/game/game.dart'; +import 'package:pinball_components/pinball_components.dart'; + +/// {@template alien_zone} +/// Area positioned below [Spaceship] where the [Ball] +/// can bounce off [AlienBumper]s. +/// +/// When a [Ball] hits [AlienBumper]s, they toggle between activated and +/// deactivated states. +/// {@endtemplate} +class AlienZone extends Component with HasGameRef { + /// {@macro alien_zone} + AlienZone(); + + @override + Future onLoad() async { + await super.onLoad(); + + gameRef.addContactCallback(_ControlledAlienBumperBallContactCallback()); + + final lowerLeftBumper = _ControlledAlienBumper.a() + ..initialPosition = Vector2(-31, 10); + final upperLeftBumper = _ControlledAlienBumper.b() + ..initialPosition = Vector2(-22, 17); + + await addAll([ + lowerLeftBumper, + upperLeftBumper, + ]); + } +} + +class _ControlledAlienBumper extends AlienBumper + with Controls, ScorePoints { + _ControlledAlienBumper.a() : super.a() { + controller = AlienBumperController(this); + } + + _ControlledAlienBumper.b() : super.b() { + controller = AlienBumperController(this); + } + + @override + // TODO(ruimiguel): change points when get final points map. + int get points => 10; +} + +/// {@template alien_bumper_controller} +/// Controls a [AlienBumper]. +/// {@endtemplate} +class AlienBumperController extends ComponentController + with HasGameRef { + /// {@macro alien_bumper_controller} + AlienBumperController(AlienBumper alienBumper) : super(alienBumper); + + /// Flag for activated state of the [AlienBumper]. + /// + /// Used to toggle [AlienBumper]s' state between activated and deactivated. + bool isActivated = false; + + /// Registers when a [AlienBumper] is hit by a [Ball]. + void hit() { + if (isActivated) { + component.deactivate(); + } else { + component.activate(); + } + isActivated = !isActivated; + } +} + +/// Listens when a [Ball] bounces bounces against a [SparkyBumper]. +class _ControlledAlienBumperBallContactCallback + extends ContactCallback, Ball> { + @override + void begin( + Controls controlledAlienBumper, + Ball _, + Contact __, + ) { + controlledAlienBumper.controller.hit(); + } +} diff --git a/lib/game/components/board.dart b/lib/game/components/board.dart index a312daee..0be75a6d 100644 --- a/lib/game/components/board.dart +++ b/lib/game/components/board.dart @@ -15,6 +15,7 @@ class Board extends Component { final bottomGroup = _BottomGroup(); final flutterForest = FlutterForest(); + final alienZone = AlienZone(); // TODO(alestiago): adjust positioning to real design. final dino = ChromeDino() @@ -27,6 +28,7 @@ class Board extends Component { bottomGroup, dino, flutterForest, + alienZone, ]); } } diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index 61d0f3ca..68703e79 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -1,3 +1,4 @@ +export 'alien_zone.dart'; export 'board.dart'; export 'bonus_word.dart'; export 'controlled_ball.dart';