Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion buildconfig/stubs/pygame/math.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ class _GenericVector(Collection[float]):
self: _TVec, other: Union[SequenceLike[float], _TVec], /
) -> float: ...
def lerp(
self: _TVec, other: Union[SequenceLike[float], _TVec], value: float, /
self: _TVec,
other: Union[SequenceLike[float], _TVec],
value: float,
do_clamp: bool = True,
/,
) -> _TVec: ...
def slerp(
self: _TVec, other: Union[SequenceLike[float], _TVec], value: float, /
Expand Down
6 changes: 6 additions & 0 deletions docs/reST/ref/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -386,12 +386,18 @@ Conversion can be combined with swizzling or slicing to create a new order

| :sl:`returns a linear interpolation to the given vector.`
| :sg:`lerp(Vector2, float, /) -> Vector2`
| :sg:`lerp(Vector2, float, bool, /) -> Vector2`

Returns a Vector which is a linear interpolation between self and the
given Vector. The second parameter determines how far between self and
other the result is going to be. It must be a value between ``0`` and ``1``
where ``0`` means self and ``1`` means other will be returned.

.. versionchanged:: 2.5.7 The ``do_clamp`` parameter is added with a default
value of ``True``. When it's ``True``, the second parameter is limited
to the closed interval ``[0, 1]``. When it's ``False``, the second parameter
is not limited and the lerp will extend beyond the original two vectors.

.. ## Vector2.lerp ##

.. method:: slerp
Expand Down
2 changes: 1 addition & 1 deletion src_c/doc/math_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#define DOC_MATH_VECTOR2_DISTANCESQUAREDTO "distance_squared_to(Vector2, /) -> float\ncalculates the squared Euclidean distance to a given vector."
#define DOC_MATH_VECTOR2_MOVETOWARDS "move_towards(Vector2, float, /) -> Vector2\nreturns a vector moved toward the target by a given distance."
#define DOC_MATH_VECTOR2_MOVETOWARDSIP "move_towards_ip(Vector2, float, /) -> None\nmoves the vector toward its target at a given distance."
#define DOC_MATH_VECTOR2_LERP "lerp(Vector2, float, /) -> Vector2\nreturns a linear interpolation to the given vector."
#define DOC_MATH_VECTOR2_LERP "lerp(Vector2, float, /) -> Vector2\nlerp(Vector2, float, bool, /) -> Vector2\nreturns a linear interpolation to the given vector."
#define DOC_MATH_VECTOR2_SLERP "slerp(Vector2, float, /) -> Vector2\nreturns a spherical interpolation to the given vector."
#define DOC_MATH_VECTOR2_SMOOTHSTEP "smoothstep(Vector2, float, /) -> Vector2\nreturns a smooth interpolation to the given vector."
#define DOC_MATH_VECTOR2_ELEMENTWISE "elementwise() -> VectorElementwiseProxy\nThe next operation will be performed elementwise."
Expand Down
9 changes: 6 additions & 3 deletions src_c/math.c
Original file line number Diff line number Diff line change
Expand Up @@ -1708,16 +1708,19 @@ vector_lerp(pgVector *self, PyObject *args)
pgVector *ret;
double t;
double other_coords[VECTOR_MAX_SIZE];
int do_clamp = 1;

if (!PyArg_ParseTuple(args, "Od:Vector.lerp", &other, &t)) {
if (!PyArg_ParseTuple(args, "Od|p:Vector.lerp", &other, &t, &do_clamp)) {
return NULL;
}
if (!pg_VectorCoordsFromObjOldDontUseInNewCode(other, other_coords,
self->dim)) {
return RAISE(PyExc_TypeError, "Expected Vector as argument 1");
}
if (t < 0 || t > 1) {
return RAISE(PyExc_ValueError, "Argument 2 must be in range [0, 1]");
if ((t < 0 || t > 1) && do_clamp > 0) {
return RAISE(PyExc_ValueError,
"Argument 2 must be in range [0, 1] when do_clamp is set "
"to True (the default value)");
}

ret = _vector_subtype_new(self);
Expand Down
8 changes: 8 additions & 0 deletions test/math_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1139,14 +1139,18 @@ def test_lerp(self):
v2 = Vector2(10, 10)
self.assertEqual(v1.lerp(v2, 0.5), (5, 5))
self.assertRaises(ValueError, lambda: v1.lerp(v2, 2.5))
self.assertEqual(v1.lerp(v2, 2.5, False), (25, 25))
self.assertEqual(v1.lerp(v2, -1, False), (-10, -10))

v1 = Vector2(0, 0)
v2 = Vector2(10, 10)
self.assertEqual(v1.lerp(v2, 0.1), (1, 1))
self.assertEqual(v1.lerp(v2, 10, False), (100, 100))

v1 = Vector2(-10, -5)
v2 = Vector2(10, 10)
self.assertEqual(v1.lerp(v2, 0.5), (0, 2.5))
self.assertEqual(v1.lerp(v2, -10, False), (-210, -155))

def test_smoothstep(self):
v1 = Vector2(0, 0)
Expand Down Expand Up @@ -2892,14 +2896,18 @@ def test_lerp(self):
v2 = Vector3(10, 10, 10)
self.assertEqual(v1.lerp(v2, 0.5), (5, 5, 5))
self.assertRaises(ValueError, lambda: v1.lerp(v2, 2.5))
self.assertEqual(v1.lerp(v2, 2.5, False), (25, 25, 25))
self.assertEqual(v1.lerp(v2, -1, False), (-10, -10, -10))

v1 = Vector3(0, 0, 0)
v2 = Vector3(10, 10, 10)
self.assertEqual(v1.lerp(v2, 0.1), (1, 1, 1))
self.assertEqual(v1.lerp(v2, 10, False), (100, 100, 100))

v1 = Vector3(-10, -5, -20)
v2 = Vector3(10, 10, -20)
self.assertEqual(v1.lerp(v2, 0.5), (0, 2.5, -20))
self.assertEqual(v1.lerp(v2, -10, False), (-210, -155, -20))

def test_smoothstep(self):
v1 = Vector3(0, 0, 0)
Expand Down
Loading