diff --git a/packages/flame/lib/src/extensions/vector2.dart b/packages/flame/lib/src/extensions/vector2.dart index 709d2adf9a..52d11af15a 100644 --- a/packages/flame/lib/src/extensions/vector2.dart +++ b/packages/flame/lib/src/extensions/vector2.dart @@ -80,6 +80,26 @@ extension Vector2Extension on Vector2 { } } + /// Project this onto [other]. + /// + /// [other] needs to have a length > 0; + /// If [out] is specified, it will be used to provide the result. + Vector2 projection(Vector2 other, {Vector2? out}) { + assert(other.length2 > 0, 'other needs to have a length > 0'); + final dotProduct = dot(other); + final result = (out?..setFrom(other)) ?? other.clone(); + return result..scale(dotProduct / other.length2); + } + + /// Inverts the vector. + void invert() { + x *= -1; + y *= -1; + } + + /// Returns the inverse of this vector. + Vector2 inverted() => Vector2(-x, -y); + /// Smoothly moves this [Vector2] in the direction [target] by a displacement /// given by a distance [ds] in that direction. /// diff --git a/packages/flame/test/extensions/vector2_test.dart b/packages/flame/test/extensions/vector2_test.dart index a733a33872..db19e38328 100644 --- a/packages/flame/test/extensions/vector2_test.dart +++ b/packages/flame/test/extensions/vector2_test.dart @@ -208,4 +208,59 @@ void main() { expectDouble(position.screenAngle(), math.pi / 2); }); }); + + group('projection', () { + test('Project onto longer vector', () { + final u = Vector2(5, 2); + final v = Vector2(10, 0); + final result = u.projection(v); + expect(result, Vector2(5, 0)); + }); + + test('Project onto shorter vector', () { + final u = Vector2(5, 2); + final v = Vector2(2, 0); + final result = u.projection(v); + expect(result, Vector2(5, 0)); + }); + + test('Project onto vector in other direction', () { + final u = Vector2(5, 2); + final v = Vector2(-10, 0); + final result = u.projection(v); + expect(result, Vector2(5, 0)); + }); + + test('Project onto vector with out', () { + final out = Vector2.zero(); + final u = Vector2(5, 2); + final v = Vector2(-10, 0); + final result = u.projection(v, out: out); + expect(result, Vector2(5, 0)); + expect(out, Vector2(5, 0)); + }); + + test('Project onto vector with out as sane return and argument', () { + var out = Vector2.zero(); + final u = Vector2(5, 2); + final v = Vector2(-10, 0); + out = u.projection(v, out: out); + expect(out, Vector2(5, 0)); + }); + }); + + group('inversion', () { + test('invert', () { + final v = Vector2.all(1); + v.invert(); + expect(v, Vector2.all(-1)); + }); + + test('inverted', () { + final v = Vector2.all(1); + final w = v.inverted(); + expect(v, Vector2.all(1)); + expect(w, Vector2.all(-1)); + }); + }); }