refactor!: Remove the Projector interface that is no longer used for coordinate transformations (#2955)

Remove the Projector interface that is no longer used for coordinate
transformations.

While this is exposed to end-users there is not much point in doing so
as it was always an internal detail of our implementation.
Since our last batch of removals of the old event system, this was left
orphaned.

I don't think deprecation is necessary as it is very unlikely that
anyone is using this interface (and if they are, they can easily declare
their own as we do not care about it anywhere).



This interface is no longer necessary to interop with Flame in any way
shape or form.
If you wish to use it internally in your game you can just declare it
yourself.
This commit is contained in:
Luan Nico
2024-01-01 16:31:59 -05:00
committed by GitHub
parent 1dc331138b
commit 0979dc97f5
4 changed files with 0 additions and 187 deletions

View File

@ -34,5 +34,3 @@ tappable
tappables
toolset
underutilize
unproject
unscale

View File

@ -11,6 +11,5 @@ export 'src/game/game.dart';
export 'src/game/game_widget/game_widget.dart';
export 'src/game/mixins/single_game_instance.dart';
export 'src/game/notifying_vector2.dart';
export 'src/game/projector.dart';
export 'src/game/transform2d.dart';
export 'src/text/renderers/text_paint.dart';

View File

@ -1,104 +0,0 @@
import 'package:flame/extensions.dart';
/// A simple interface to mark a class that can perform projection operations
/// from one 2D Euclidean coordinate space to another.
///
/// This can be a Viewport, a Camera or anything else that exposes such
/// operations to the user.
abstract class Projector {
/// Converts a vector in the screen space to the world space.
///
/// This considers both the translation and scaling transformations.
Vector2 unprojectVector(Vector2 screenCoordinates);
/// Converts a vector in the world space to the screen space.
///
/// This considers both the translation and scaling transformations.
Vector2 projectVector(Vector2 worldCoordinates);
/// Converts a vector representing a delta in the screen space to the world
/// space.
///
/// This considers only the scaling transformation, as the translations are
/// cancelled in a delta transformation.
/// A delta can be a displacement (difference between two position
/// vectors), a velocity (displacement over time), etc.
Vector2 unscaleVector(Vector2 screenCoordinates);
/// Converts a vector representing a delta in the world space to the screen
/// space.
///
/// This considers only the scaling transformation, as the translations are
/// cancelled in a delta transformation.
/// A delta can be a displacement (difference between two position
/// vectors), a velocity (displacement over time), etc.
Vector2 scaleVector(Vector2 worldCoordinates);
/// Creates a [ComposedProjector] that will apply the provided projectors
/// in order.
///
/// Use when dealing with multiple coordinate transformations in succession.
static Projector compose(List<Projector> projectors) {
return ComposedProjector(projectors);
}
}
/// A simple Projector implementation that represents the identity operation
/// (i.e. no-op).
class IdentityProjector extends Projector {
@override
Vector2 projectVector(Vector2 v) => v;
@override
Vector2 scaleVector(Vector2 v) => v;
@override
Vector2 unprojectVector(Vector2 v) => v;
@override
Vector2 unscaleVector(Vector2 v) => v;
}
/// This is a [Projector] implementation that composes a list of projectors,
/// in the order provided.
///
/// It will call the `project*` functions in the order in the array and the
/// `unproject*` in the reversed order.
/// For a list of projectors p1, p2, ..., pn, this is equivalent of the
/// projector p = pn ∘ ... ∘ p2 ∘ p1.
class ComposedProjector extends Projector {
final List<Projector> _components;
ComposedProjector(this._components);
@override
Vector2 scaleVector(Vector2 worldCoordinates) {
return _components.fold(
worldCoordinates,
(previousValue, element) => element.scaleVector(previousValue),
);
}
@override
Vector2 projectVector(Vector2 worldCoordinates) {
return _components.fold(
worldCoordinates,
(previousValue, element) => element.projectVector(previousValue),
);
}
@override
Vector2 unscaleVector(Vector2 screenCoordinates) {
return _components.reversed.fold(
screenCoordinates,
(previousValue, element) => element.unscaleVector(previousValue),
);
}
@override
Vector2 unprojectVector(Vector2 screenCoordinates) {
return _components.reversed.fold(
screenCoordinates,
(previousValue, element) => element.unprojectVector(previousValue),
);
}
}

View File

@ -1,80 +0,0 @@
import 'dart:math';
import 'package:flame/game.dart';
import 'package:flame_test/flame_test.dart';
import 'package:test/test.dart';
void main() {
group('IdentityProjector', () {
test('basic properties', () {
final projector = IdentityProjector();
checkProjectorReversibility(projector);
final v = Vector2(3.14, -3.15);
expect(projector.projectVector(v), closeToVector(v));
expect(projector.scaleVector(v), closeToVector(v));
});
});
group('ComposedProjector', () {
test('compose 2 projectors', () {
final projector = ComposedProjector([
_ScaleProjector(3),
_ScaleProjector(-1),
]);
checkProjectorReversibility(projector);
expect(
projector.projectVector(Vector2(4, 5)),
closeToVector(Vector2(-12, -15)),
);
expect(
projector.projectVector(Vector2(1, -2)),
closeToVector(Vector2(-3, 6)),
);
});
});
}
/// This function verifies that for the given [projector], its `project` and
/// `unproject` methods are the inverses of one another.
void checkProjectorReversibility(Projector projector) {
final random = Random();
for (var i = 0; i < 10; i++) {
final point = Vector2(
random.nextDouble() * exp(random.nextDouble().abs() * 2),
random.nextDouble() * exp(random.nextDouble().abs() * 2),
);
expect(
projector.projectVector(projector.unprojectVector(point)),
closeToVector(point, 1e-13),
);
expect(
projector.unprojectVector(projector.projectVector(point)),
closeToVector(point, 1e-13),
);
expect(
projector.scaleVector(projector.unscaleVector(point)),
closeToVector(point, 1e-13),
);
expect(
projector.unscaleVector(projector.scaleVector(point)),
closeToVector(point, 1e-13),
);
}
}
class _ScaleProjector extends Projector {
_ScaleProjector(this.scale);
final double scale;
@override
Vector2 projectVector(Vector2 p) => p.scaled(scale);
@override
Vector2 scaleVector(Vector2 p) => p.scaled(scale);
@override
Vector2 unprojectVector(Vector2 p) => p.scaled(1 / scale);
@override
Vector2 unscaleVector(Vector2 p) => p.scaled(1 / scale);
}