From b2741a34613291fef1cd7d185a61636f74a2ca1e Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Thu, 24 Mar 2022 13:35:41 +0100 Subject: [PATCH] refactor: changed Elevated mixin to Priority extension --- lib/game/components/ball.dart | 3 +- lib/game/components/components.dart | 2 +- lib/game/components/elevation.dart | 71 ------------------- lib/game/components/priority.dart | 32 +++++++++ lib/game/components/spaceship.dart | 50 +++++++------ ...elevation_test.dart => priority_test.dart} | 6 +- 6 files changed, 65 insertions(+), 99 deletions(-) delete mode 100644 lib/game/components/elevation.dart create mode 100644 lib/game/components/priority.dart rename test/game/components/{elevation_test.dart => priority_test.dart} (96%) diff --git a/lib/game/components/ball.dart b/lib/game/components/ball.dart index f47f7b48..def21929 100644 --- a/lib/game/components/ball.dart +++ b/lib/game/components/ball.dart @@ -7,8 +7,7 @@ import 'package:pinball/gen/assets.gen.dart'; /// A solid, [BodyType.dynamic] sphere that rolls and bounces along the /// [PinballGame]. /// {@endtemplate} -class Ball extends BodyComponent - with InitialPosition, Layered, Elevated { +class Ball extends BodyComponent with InitialPosition, Layered { /// {@macro ball} Ball() { // TODO(ruimiguel): while developing Ball can be launched by clicking mouse, diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index 037ee8a8..84d2833a 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -3,7 +3,6 @@ export 'baseboard.dart'; export 'board.dart'; export 'board_side.dart'; export 'bonus_word.dart'; -export 'elevation.dart'; export 'flipper.dart'; export 'initial_position.dart'; export 'jetpack_ramp.dart'; @@ -13,6 +12,7 @@ export 'launcher_ramp.dart'; export 'layer.dart'; export 'pathway.dart'; export 'plunger.dart'; +export 'priority.dart'; export 'ramp_opening.dart'; export 'round_bumper.dart'; export 'score_points.dart'; diff --git a/lib/game/components/elevation.dart b/lib/game/components/elevation.dart deleted file mode 100644 index b5e0531b..00000000 --- a/lib/game/components/elevation.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'package:flame_forge2d/flame_forge2d.dart'; -import 'package:flutter/material.dart'; - -/// {@template elevated} -/// Modifies priority of the [BodyComponent] to specify in which z-index level -/// [BodyComponent] is. -/// {@endtemplate} -mixin Elevated on BodyComponent { - int _elevation = Elevation.board.order; - - /// {@macro elevated} - int get elevation => _elevation; - - set elevation(int value) { - _elevation = value; - if (!isLoaded) { - // TODO(ruimiguel): Use loaded.whenComplete once provided. - mounted.whenComplete(_applyElevation); - } else { - _applyElevation(); - } - } - - void _applyElevation() { - priority = elevation; - reorderChildren(); - } -} - -/// The [Elevation]s a [BodyComponent] can be in. -/// -/// Each [Elevation] is associated with a different board level from ground, to -/// define several z-index heights. -/// -/// Usually used with [Elevated]. -enum Elevation { - /// The ground level. - board, - - /// Level for Jetpack group elements. - jetpack, - - /// Level for Spaceship group elements. - spaceship, - - /// Level for SpaceshipExitRail. - spaceshipExitRail, -} - -/// {@template elevation_order} -/// Specifies the order of each [Elevation]. -/// -/// Used by [Elevated] to specify what is the priority of [BodyComponent]. -/// {@endtemplate} -@visibleForTesting -extension ElevationOrder on Elevation { - /// {@macro elevation_order} - - int get order { - switch (this) { - case Elevation.board: - return 1; - case Elevation.jetpack: - return 2; - case Elevation.spaceship: - return 3; - case Elevation.spaceshipExitRail: - return 2; - } - } -} diff --git a/lib/game/components/priority.dart b/lib/game/components/priority.dart new file mode 100644 index 00000000..c4f9b312 --- /dev/null +++ b/lib/game/components/priority.dart @@ -0,0 +1,32 @@ +// TODO(ruimiguel): move file to appropiate location. +import 'dart:math' as math; +import 'package:flame/components.dart'; + +/// Helper methods to change the [priority] of a [Component]. +extension ComponentPriorityX on Component { + static const _lowestPriority = 0; + + /// Changes the priority to the lowest possible. + void sendToBack() { + if (priority != _lowestPriority) { + priority = _lowestPriority; + reorderChildren(); + } + } + + /// Decreases the priority to be lower than another [Component]. + void showBehindOf(Component other) { + if (priority >= other.priority) { + priority = math.max(other.priority - 1, _lowestPriority); + reorderChildren(); + } + } + + /// Increases the priority to be higher than another [Component]. + void showInFrontOf(Component other) { + if (priority <= other.priority) { + priority = other.priority + 1; + reorderChildren(); + } + } +} diff --git a/lib/game/components/spaceship.dart b/lib/game/components/spaceship.dart index d3ff9151..15fa959f 100644 --- a/lib/game/components/spaceship.dart +++ b/lib/game/components/spaceship.dart @@ -1,4 +1,4 @@ -// ignore_for_file: avoid_renaming_method_parameters +// ignore_for_file: avoid_renaming_method_parameters, avoid_function_literals_in_foreach_calls import 'dart:async'; import 'dart:math'; @@ -26,14 +26,28 @@ class Spaceship extends Forge2DBlueprint { SpaceshipEntranceBallContactCallback(), ]); - addAll([ - SpaceshipSaucer()..initialPosition = position, + const ballPriorityWhenOnSpaceship = 3; + + final rendersBehindBall = [ SpaceshipEntrance()..initialPosition = position, + SpaceshipSaucer()..initialPosition = position, + ]..forEach( + (component) => component.priority = ballPriorityWhenOnSpaceship - 1, + ); + + final rendersInFrontOfBall = [ SpaceshipBridge()..initialPosition = position, SpaceshipBridgeTop()..initialPosition = position + Vector2(0, 5.5), + SpaceshipWall()..initialPosition = position, + ]..forEach( + (component) => component.priority = ballPriorityWhenOnSpaceship + 1, + ); + + addAll([ + ...rendersBehindBall, + ...rendersInFrontOfBall, SpaceshipHole()..initialPosition = position - Vector2(5, 4), SpaceshipHole()..initialPosition = position - Vector2(-5, 4), - SpaceshipWall()..initialPosition = position, ]); } } @@ -41,12 +55,10 @@ class Spaceship extends Forge2DBlueprint { /// {@template spaceship_saucer} /// A [BodyComponent] for the base, or the saucer of the spaceship /// {@endtemplate} -class SpaceshipSaucer extends BodyComponent - with InitialPosition, Layered, Elevated { +class SpaceshipSaucer extends BodyComponent with InitialPosition, Layered { /// {@macro spaceship_saucer} SpaceshipSaucer() { layer = Layer.spaceship; - elevation = Elevation.spaceship.order - 1; } @override @@ -97,11 +109,9 @@ class SpaceshipSaucer extends BodyComponent /// The bridge of the spaceship (the android head) is divided in two // [BodyComponent]s, this is the top part of it which contains a single sprite /// {@endtemplate} -class SpaceshipBridgeTop extends BodyComponent with InitialPosition, Elevated { +class SpaceshipBridgeTop extends BodyComponent with InitialPosition { /// {@macro spaceship_bridge_top} - SpaceshipBridgeTop() { - elevation = Elevation.spaceship.order * 2; - } + SpaceshipBridgeTop(); @override Future onLoad() async { @@ -134,12 +144,10 @@ class SpaceshipBridgeTop extends BodyComponent with InitialPosition, Elevated { /// The main part of the [SpaceshipBridge], this [BodyComponent] /// provides both the collision and the rotation animation for the bridge. /// {@endtemplate} -class SpaceshipBridge extends BodyComponent - with InitialPosition, Layered, Elevated { +class SpaceshipBridge extends BodyComponent with InitialPosition, Layered { /// {@macro spaceship_bridge} SpaceshipBridge() { layer = Layer.spaceship; - elevation = Elevation.spaceship.order; } @override @@ -246,12 +254,10 @@ class SpaceshipHole extends BodyComponent with InitialPosition, Layered { /// [Ball] to get inside the spaceship saucer. /// It also contains the [SpriteComponent] for the lower wall /// {@endtemplate} -class SpaceshipWall extends BodyComponent - with InitialPosition, Layered, Elevated { +class SpaceshipWall extends BodyComponent with InitialPosition, Layered { /// {@macro spaceship_wall} - SpaceshipWall() : super(priority: 4) { + SpaceshipWall() { layer = Layer.spaceship; - elevation = Elevation.spaceship.order + 1; } @override @@ -311,8 +317,8 @@ class SpaceshipEntranceBallContactCallback @override void begin(SpaceshipEntrance entrance, Ball ball, _) { ball - ..elevation = Elevation.spaceship.order - ..layer = Layer.spaceship; + ..layer = Layer.spaceship + ..showInFrontOf(entrance); } } @@ -326,7 +332,7 @@ class SpaceshipHoleBallContactCallback @override void begin(SpaceshipHole hole, Ball ball, _) { ball - ..elevation = Elevation.board.order - ..layer = Layer.board; + ..layer = Layer.board + ..sendToBack(); } } diff --git a/test/game/components/elevation_test.dart b/test/game/components/priority_test.dart similarity index 96% rename from test/game/components/elevation_test.dart rename to test/game/components/priority_test.dart index 166e68aa..7871cb7b 100644 --- a/test/game/components/elevation_test.dart +++ b/test/game/components/priority_test.dart @@ -2,10 +2,10 @@ import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:pinball/game/components/elevation.dart'; +import 'package:pinball/game/components/priority.dart'; import 'package:pinball/game/game.dart'; -class TestBodyComponent extends BodyComponent with Elevated { +class TestBodyComponent extends BodyComponent { @override Body createBody() { final fixtureDef = FixtureDef(CircleShape()); @@ -16,7 +16,7 @@ class TestBodyComponent extends BodyComponent with Elevated { void main() { final flameTester = FlameTester(Forge2DGame.new); - group('Elevated', () { + group('ComponentPriorityX', () { test('correctly sets and gets', () { final component = TestBodyComponent() ..elevation = Elevation.spaceship.order;