Skip to content

Commit 5a5b0b9

Browse files
committed
Added maths methods.
1 parent ba6ed10 commit 5a5b0b9

File tree

1 file changed

+314
-0
lines changed

1 file changed

+314
-0
lines changed

Runtime/MathsHelper.cs

Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,323 @@
22
// Purpose: Various static maths helper methods
33
// Created by: DavidFDev
44

5+
using System.Diagnostics.Contracts;
6+
using UnityEngine;
7+
58
namespace DavidFDev.Maths
69
{
710
public static class MathsHelper
811
{
12+
/// <summary>
13+
/// Shift the start value towards the end value without exceeding.
14+
/// </summary>
15+
/// <param name="start"></param>
16+
/// <param name="end"></param>
17+
/// <param name="shift"></param>
18+
/// <returns></returns>
19+
[Pure]
20+
public static float Approach(float start, float end, float shift)
21+
{
22+
if (start < end)
23+
{
24+
return Mathf.Min(start + shift, end);
25+
}
26+
27+
return Mathf.Max(start - shift, end);
28+
}
29+
30+
/// <summary>
31+
/// Shift the start angle towards the end angle (degrees).
32+
/// </summary>
33+
/// <param name="start"></param>
34+
/// <param name="end"></param>
35+
/// <param name="shift"></param>
36+
/// <returns></returns>
37+
[Pure]
38+
public static float ApproachAngle(float start, float end, float shift)
39+
{
40+
float deltaAngle = Mathf.DeltaAngle(start, end);
41+
if (-shift < deltaAngle && deltaAngle < shift)
42+
{
43+
return end;
44+
}
45+
46+
return Mathf.Repeat(Approach(start, start + deltaAngle, shift), 360f);
47+
}
48+
49+
/// <summary>
50+
/// Shift the start value towards zero without exceeding.
51+
/// </summary>
52+
/// <param name="start"></param>
53+
/// <param name="shift"></param>
54+
/// <returns></returns>
55+
[Pure]
56+
public static float Reduce(float start, float shift)
57+
{
58+
return Approach(start, 0f, shift);
59+
}
60+
61+
/// <summary>
62+
/// Shift the start angle towards zero (degrees).
63+
/// </summary>
64+
/// <param name="start"></param>
65+
/// <param name="shift"></param>
66+
/// <returns></returns>
67+
[Pure]
68+
public static float ReduceAngle(float start, float shift)
69+
{
70+
return ApproachAngle(start, 0f, shift);
71+
}
72+
73+
/// <summary>
74+
/// Pulse between min and max using a sine wave.
75+
/// </summary>
76+
/// <param name="time">Increasing value (e.g. Time.time).</param>
77+
/// <param name="frequency">How many min..max..min per second (lower is slower).</param>
78+
/// <param name="min"></param>
79+
/// <param name="max"></param>
80+
/// <returns></returns>
81+
[Pure]
82+
public static float Pulse(float time, float frequency, float min, float max)
83+
{
84+
float half = (max - min) * 0.5f;
85+
return min + half + Mathf.Sin(2f * Mathf.PI * frequency * time) * half;
86+
}
87+
88+
/// <summary>
89+
/// Alternate between true and false using a sine wave.
90+
/// </summary>
91+
/// <param name="time">Increasing value (e.g. Time.time).</param>
92+
/// <param name="frequency">How many false..true..false per second (lower is slower).</param>
93+
/// <returns></returns>
94+
[Pure]
95+
public static bool FlipFlop(float time, float frequency)
96+
{
97+
return Pulse(time, frequency, 0f, 1f) >= 0.5f;
98+
}
99+
100+
/// <summary>
101+
/// Alternate between true and false using a sine wave, only returning true when it's at its peak.
102+
/// </summary>
103+
/// <param name="time">Increasing value (e.g. Time.time).</param>
104+
/// <param name="frequency">Blip speed (lower is slower).</param>
105+
/// <returns></returns>
106+
[Pure]
107+
public static bool Blip(float time, float frequency)
108+
{
109+
return Pulse(time, frequency, 0f, 1f) == 1f;
110+
}
111+
112+
/// <summary>
113+
/// Sign method that returns -1, 0 or +1 depending on the sign of a given value.
114+
/// </summary>
115+
/// <param name="value"></param>
116+
/// <returns></returns>
117+
[Pure]
118+
public static float Sign(float value)
119+
{
120+
return value < 0f ? -1f : (value > 0f ? 1f : 0f);
121+
}
122+
123+
/// <summary>
124+
/// Retrive the sign of a value if it's over the threshold, otherwise return zero.
125+
/// </summary>
126+
/// <param name="value"></param>
127+
/// <param name="threshold"></param>
128+
/// <returns></returns>
129+
[Pure]
130+
public static float SignThreshold(float value, float threshold)
131+
{
132+
return Mathf.Abs(value) >= threshold ? Sign(value) : 0f;
133+
}
134+
135+
/// <summary>
136+
/// Get a vector with its original components passed through Sign().
137+
/// </summary>
138+
/// <param name="value"></param>
139+
/// <returns></returns>
140+
[Pure]
141+
public static Vector2 Sign(Vector2 value)
142+
{
143+
return new Vector2(Sign(value.x), Sign(value.y));
144+
}
145+
146+
/// <summary>
147+
/// Get a vector with its original components passed through Sign().
148+
/// </summary>
149+
/// <param name="value"></param>
150+
/// <returns></returns>
151+
[Pure]
152+
public static Vector3 Sign(Vector3 value)
153+
{
154+
return new Vector3(Sign(value.x), Sign(value.y), Sign(value.z));
155+
}
156+
157+
/// <summary>
158+
/// Check if a value is between min and max (inclusive).
159+
/// </summary>
160+
/// <param name="value"></param>
161+
/// <param name="min"></param>
162+
/// <param name="max"></param>
163+
/// <returns></returns>
164+
[Pure]
165+
public static bool Between(float value, float min, float max)
166+
{
167+
return value >= min && value <= max;
168+
}
169+
170+
/// <summary>
171+
/// Check if a value is between min and max (inclusive).
172+
/// </summary>
173+
/// <param name="value"></param>
174+
/// <param name="min"></param>
175+
/// <param name="max"></param>
176+
/// <returns></returns>
177+
[Pure]
178+
public static bool Between(int value, int min, int max)
179+
{
180+
return value >= min && value <= max;
181+
}
182+
183+
/// <summary>
184+
/// Check if a value is even.
185+
/// </summary>
186+
/// <param name="value"></param>
187+
/// <returns></returns>
188+
[Pure]
189+
public static bool IsEven(int value)
190+
{
191+
return value % 2 == 0;
192+
}
193+
194+
/// <summary>
195+
/// Check if a value is odd.
196+
/// </summary>
197+
/// <param name="value"></param>
198+
/// <returns></returns>
199+
[Pure]
200+
public static bool IsOdd(int value)
201+
{
202+
return !IsEven(value);
203+
}
204+
205+
/// <summary>
206+
/// Map a value from some arbitrary range to the 0 to 1 range.
207+
/// </summary>
208+
/// <param name="value"></param>
209+
/// <param name="min"></param>
210+
/// <param name="max"></param>
211+
/// <returns></returns>
212+
[Pure]
213+
public static float Map01(float value, float min, float max)
214+
{
215+
return (value - min) * 1f / (max - min);
216+
}
217+
218+
/// <summary>
219+
/// Map a value from some arbitrary range to the 1 to 0 range.
220+
/// </summary>
221+
/// <param name="value"></param>
222+
/// <param name="min"></param>
223+
/// <param name="max"></param>
224+
/// <returns></returns>
225+
[Pure]
226+
public static float Map10(float value, float min, float max)
227+
{
228+
return 1f - Map01(value, min, max);
229+
}
230+
231+
/// <summary>
232+
/// Map a value from one range to another range.
233+
/// </summary>
234+
/// <param name="value"></param>
235+
/// <param name="from1"></param>
236+
/// <param name="from2"></param>
237+
/// <param name="to1"></param>
238+
/// <param name="to2"></param>
239+
/// <returns></returns>
240+
[Pure]
241+
public static float Map(float value, float from1, float from2, float to1, float to2)
242+
{
243+
return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
244+
}
245+
246+
/// <summary>
247+
/// Convert from an angle (degrees) to a 2d direction.
248+
/// </summary>
249+
/// <param name="degrees"></param>
250+
/// <returns></returns>
251+
[Pure]
252+
public static Vector2 GetDirection(float degrees)
253+
{
254+
return new Vector2(Mathf.Cos(degrees * Mathf.Deg2Rad), Mathf.Sin(degrees * Mathf.Deg2Rad));
255+
}
256+
257+
/// <summary>
258+
/// Convert from a 2d direction to an angle (degrees).
259+
/// </summary>
260+
/// <param name="direction"></param>
261+
/// <returns></returns>
262+
[Pure]
263+
public static float GetAngle(Vector2 direction)
264+
{
265+
return Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
266+
}
267+
268+
/// <summary>
269+
/// Retrieve the angle (degrees) between two 2d directions.
270+
/// </summary>
271+
/// <param name="directionA"></param>
272+
/// <param name="directionB"></param>
273+
/// <returns></returns>
274+
[Pure]
275+
public static float GetAngleBetween(Vector2 directionA, Vector2 directionB)
276+
{
277+
return GetAngle(directionA - directionB);
278+
}
279+
280+
/// <summary>
281+
/// Check if a target 2d position is within a cone projected from the source 2d position.
282+
/// </summary>
283+
/// <param name="source"></param>
284+
/// <param name="target"></param>
285+
/// <param name="coneDirection"></param>
286+
/// <param name="degrees"></param>
287+
/// <returns></returns>
288+
[Pure]
289+
public static bool WithinAngle(Vector2 source, Vector2 target, Vector2 coneDirection, float degrees)
290+
{
291+
Vector2 direction = (target - source).normalized;
292+
float cosAngle = Vector2.Dot(direction, coneDirection);
293+
float angle = Mathf.Acos(cosAngle) * Mathf.Rad2Deg;
294+
return angle < degrees;
295+
}
296+
297+
/// <summary>
298+
/// Rotate a vector by an angle (degrees).
299+
/// </summary>
300+
/// <param name="value"></param>
301+
/// <param name="degrees"></param>
302+
/// <returns></returns>
303+
[Pure]
304+
public static Vector2 RotateVector(Vector2 value, float degrees)
305+
{
306+
return GetDirection(GetAngle(value) + degrees);
307+
}
308+
309+
/// <summary>
310+
/// Rotate a vector around a pivot point by an angle (degrees).
311+
/// </summary>
312+
/// <param name="value"></param>
313+
/// <param name="degrees"></param>
314+
/// <param name="pivot"></param>
315+
/// <returns></returns>
316+
[Pure]
317+
public static Vector2 RotateVector(Vector2 value, float degrees, Vector2 pivot)
318+
{
319+
Vector2 direction = value - pivot;
320+
direction = Quaternion.Euler(0f, 0f, degrees) * direction;
321+
return direction + pivot;
322+
}
9323
}
10324
}

0 commit comments

Comments
 (0)