chore: review docs and names

pull/40/head
RuiAlonso 4 years ago
parent dab5cbbe4f
commit 7dc9ef1714

@ -1,16 +1,17 @@
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
/// Modifies maskBits of [BodyComponent] to control what other bodies it can
/// have physical interactions with.
/// {@template layered}
/// Modifies maskBits and categoryBits of all the [BodyComponent]'s [Fixture]s
/// to specify what other [BodyComponent]s it can collide with.
///
/// Changes the [Filter] data for category and maskBits of the [BodyComponent]
/// so it will only collide with bodies having the same bit value and ignore
/// bodies with a different bit value.
/// [BodyComponent]s with the same [Layer] can collide with each other, ignoring
/// those with different [Layer]s.
/// {@endtemplate}
mixin Layered<T extends Forge2DGame> on BodyComponent<T> {
Layer _layer = Layer.all;
/// Sets [Filter] category and mask bits for the [BodyComponent].
/// {@macro layered}
Layer get layer => _layer;
set layer(Layer value) {
@ -19,18 +20,18 @@ mixin Layered<T extends Forge2DGame> on BodyComponent<T> {
// TODO(alestiago): Use loaded.whenComplete once provided.
mounted.whenComplete(() {
layer = value;
_applyMaskbits();
_applyMaskBits();
});
} else {
_applyMaskbits();
_applyMaskBits();
}
}
void _applyMaskbits() {
void _applyMaskBits() {
for (final fixture in body.fixtures) {
fixture
..filterData.categoryBits = layer.maskBits
..filterData.maskBits = layer.maskBits;
..filterData.categoryBits = layer._maskBits
..filterData.maskBits = layer._maskBits;
}
}
}
@ -56,10 +57,18 @@ enum Layer {
launcher,
}
/// Utility methods for [Layer].
extension LayerX on Layer {
/// Mask of bits for each [Layer] to filter collisions.
int get maskBits {
/// {@template layer_mask_bits}
/// Specifies the maskBits of each [Layer].
///
/// Used by [Layered] to specify what other [BodyComponent]s it can collide
///
/// Note: the maximum value for maskBits is 2^16.
/// {@endtemplate}
@visibleForTesting
extension LayerMaskBits on Layer {
/// {@macro layer_mask_bits}
int get _maskBits {
// TODO(ruialonso): test bit groups once final design is implemented.
switch (this) {
case Layer.all:
return 0xFFFF;

@ -1,7 +1,6 @@
// ignore_for_file: avoid_renaming_method_parameters
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball/game/game.dart';
/// {@template ramp_orientation}
@ -21,7 +20,7 @@ enum RampOrientation {
/// [RampOpeningBallContactCallback] detects when a [Ball] passes
/// through this opening.
///
/// By default the [layer] is set to [Layer.board].
/// By default the base [layer] is set to [Layer.board].
/// {@endtemplate}
// TODO(ruialonso): Consider renaming the class.
abstract class RampOpening extends BodyComponent with InitialPosition, Layered {
@ -62,24 +61,23 @@ abstract class RampOpening extends BodyComponent with InitialPosition, Layered {
/// Detects when a [Ball] enters or exits a [Pathway] ramp through a
/// [RampOpening].
///
/// Modifies [Ball]'s maskBits while it is inside the ramp. When [Ball] exits,
/// sets maskBits to collide with all elements.
/// Modifies [Ball]'s [Layer] accordingly depending on whether the [Ball] is
/// outside or inside a ramp.
/// {@endtemplate}
class RampOpeningBallContactCallback<Opening extends RampOpening>
extends ContactCallback<Ball, Opening> {
/// Collection of balls inside ramp pathway.
@visibleForTesting
final ballsInside = <Ball>{};
/// [Ball]s currently inside the ramp.
final _ballsInside = <Ball>{};
@override
void begin(Ball ball, Opening opening, Contact _) {
late final Layer layer;
if (!ballsInside.contains(ball)) {
if (!_ballsInside.contains(ball)) {
layer = opening.pathwayLayer;
ballsInside.add(ball);
_ballsInside.add(ball);
} else {
layer = Layer.board;
ballsInside.remove(ball);
_ballsInside.remove(ball);
}
ball.layer = layer;

@ -24,9 +24,9 @@ void main() {
for (final fixture in fixtures) {
expect(
fixture.filterData.categoryBits,
equals(layer.maskBits),
equals(layer._maskBits),
);
expect(fixture.filterData.maskBits, equals(layer.maskBits));
expect(fixture.filterData.maskBits, equals(layer._maskBits));
}
}
@ -128,39 +128,20 @@ void main() {
});
});
group('LayerX', () {
group('LayerMaskBits', () {
test('all types are different', () {
expect(Layer.all.maskBits, isNot(equals(Layer.board.maskBits)));
expect(Layer.board.maskBits, isNot(equals(Layer.opening.maskBits)));
expect(Layer.opening.maskBits, isNot(equals(Layer.jetpack.maskBits)));
expect(Layer.jetpack.maskBits, isNot(equals(Layer.launcher.maskBits)));
expect(Layer.launcher.maskBits, isNot(equals(Layer.board.maskBits)));
expect(Layer.all._maskBits, isNot(equals(Layer.board._maskBits)));
expect(Layer.board._maskBits, isNot(equals(Layer.opening._maskBits)));
expect(Layer.opening._maskBits, isNot(equals(Layer.jetpack._maskBits)));
expect(Layer.jetpack._maskBits, isNot(equals(Layer.launcher._maskBits)));
expect(Layer.launcher._maskBits, isNot(equals(Layer.board._maskBits)));
});
test('ensure all maskBits are 16 bits max size', () {
final maxMaskBitSize = math.pow(2, 16);
for (final layer in Layer.values) {
expect(layer.maskBits, isNot(greaterThan(maxMaskBitSize)));
expect(layer._maskBits, isNot(greaterThan(maxMaskBitSize)));
}
});
test('all type has 0xFFFF maskBits', () {
expect(Layer.all.maskBits, equals(0xFFFF));
});
test('board type has 0x0001 maskBits', () {
expect(Layer.board.maskBits, equals(0x0001));
});
test('opening type has 0x0007 maskBits', () {
expect(Layer.opening.maskBits, equals(0x0007));
});
test('jetpack type has 0x0002 maskBits', () {
expect(Layer.jetpack.maskBits, equals(0x0002));
});
test('launcher type has 0x0005 maskBits', () {
expect(Layer.launcher.maskBits, equals(0x0005));
});
});
}

Loading…
Cancel
Save