Тема: Алгоритм руху точок по кривій
Є структура "Coordinates", яка містить інформацію про точку в двовимірному просторі
struct Coordinates
{
public float x;
public float y;
}
Створюється об'єкт будь-якої кривої (точки по яким можна з'єднати криву).
Приклад, крива що нагадує квадрат
square = new Coordinates[4];
square[0].x = -2.5f;
square[0].y = 2.5f;
square[1].x = 2.5f;
square[1].y = 2.5f;
square[2].x = 2.5f;
square[2].y = -2.5f;
square[3].x = -2.5f;
square[3].y = -2.5f;
Потрібно зробити рух цих точок по уявній кривій.
square[0] рухається до square[1], square[1] рухається до square[2] і т.д.
Червоним кольором показаний рух за часовою стрілкою, зеленим - проти.
1) Рух має бути справжнім, тобто не можна зробити так, що коли одна точка дійшла до наступної (наприклад, square[0] до позиції де була точка square[1]), ця точка миттєво поверталася до своєї початкової позиції, і починала рух спочатку до square[1]. Згодом буде додана можливість видаляти якість точки, тому ілюзія руху не підійде.
2) Якщо одна з точок добралася до наступної позиції раніше інших, то ця точка має чекати поки всі інші точки не доберуться до свої наступних позицій, і тільки тоді продовжувати свій рух. (звичайно, у кривій яка схожа на квадрат, всі точки будуть рухатися рівномірно, але як я казав, можна створити будь яку криву)
3) Швидкість: виклик функції прив'язаний до часу, тому можна зробити додаткову змінну (наприклад speedMoveAlongCurve) яка буде відповідати за швидкість
4) Напрямок руху: по часовій стрілці, або проти. Як напрямок руху краще задавати я не знаю, можна зробити додатну і від'ємну швидкість: "+" це по часовій стрілці, "-" проти часової стрілки. Можливо зробити окрему булеву змінну...
Допоможіть скласти алгоритм, або код на C#.
Дальше краще не читайте, бо там все дуже погано ... , легше почати все спочатку.
Створюю цикл де b відповідає за кількість ітерації (b < всі_точок)
i - точка яка буде рухатися, j точка до якої потрібно рухатися
moveAlongCurveInd - глобальний індекс (поза функцією), що перемикає точки
for(
ushort b = 0,
i = moveAlongCurveInd,
j = (ushort)(moveAlongCurveInd + 1);
b < points.Length;
b++, i++, j++
)
Дізнаюся, точка до якої потрібно рухатися має значення зі знаком "-" чи "+"
if (points[j].x < 0)
{
speedMoveAlongCurve = -(Mathf.Abs( speedMoveAlongCurve ));
}
else
{
speedMoveAlongCurve = +(Mathf.Abs(speedMoveAlongCurve));
}
Якщо точки, яка рухається і до якої потрібно рухатися, не однакові, то збільшую її на інтервал швидкість speedMoveAlongCurve.
float _X = _PointArr[i].transform.position.x;
if (points[j].x != _PointArr[i].transform.position.x)
{
_X = _PointArr[i].transform.position.x + speedMoveAlongCurve;
}
те ж саме роблю з "У" точками.
Перевіряю чи всі точки дійшли до запланованих позицій
nextInd[j] = false;
if (points[j].x < 0)
{
//-
if (_X <= points[j].x)
{
nextInd[j] = true;
}
else
{
nextInd[j] = false;
}
}
else
{
//+
if (_X >= points[j].x)
{
nextInd[j] = true;
}
else
{
nextInd[j] = false;
}
}
//
if (points[j].y < 0)
{
//-
if (_Y <= points[j].y)
{
nextInd[j] = nextInd[j] && true;
}
else
{
nextInd[j] = nextInd[j] && false;
}
}
else
{
//+
if (_Y >= points[j].y)
{
nextInd[j] = nextInd[j] && true;
}
else
{
nextInd[j] = nextInd[j] && false;
}
}
bool indSum = nextInd[0];
for (int k = 1; k < points.Length; k++)
indSum = nextInd[k] && indSum;
Збільшую глобальний індекс, якщо всі точки добралися до запланованих позицій
if (indSum && moveAlongCurveInd + 1 < points.Length)
{ moveAlongCurveInd += 1; }
else if (indSum && moveAlongCurveInd >= points.Length)
{ moveAlongCurveInd = 0; }
Весь код
/*Move along the Curve*/
private ushort moveAlongCurveInd;
private bool[] nextInd;
private void moveAlongCurve(Coordinates[] points, bool direction/*0 - left, 1 - right*/)
{
for (
ushort b = 0,
i = moveAlongCurveInd,
j = (ushort)(moveAlongCurveInd + 1);
b < points.Length;
b++, i++, j++
)
{
if (i == 4) i = 0;
if (j == 4) j = 0;
if (points[j].x < 0)
{
speedMoveAlongCurve = -(Mathf.Abs( speedMoveAlongCurve ));
}
else
{
speedMoveAlongCurve = +(Mathf.Abs(speedMoveAlongCurve));
}
float _X = _PointArr[i].transform.position.x;
if (points[j].x != _PointArr[i].transform.position.x)
{
_X = _PointArr[i].transform.position.x + speedMoveAlongCurve;
}
if (points[j].y < 0)
{
speedMoveAlongCurve = -(Mathf.Abs(speedMoveAlongCurve));
}
else
{
speedMoveAlongCurve = +(Mathf.Abs(speedMoveAlongCurve));
}
float _Y = _PointArr[i].transform.position.y;
if (points[j].y != _PointArr[i].transform.position.y)
{
_Y = _PointArr[i].transform.position.y + speedMoveAlongCurve;
}
nextInd[j] = false;
if (points[j].x < 0)
{
//-
if (_X <= points[j].x)
{
nextInd[j] = true;
}
else
{
nextInd[j] = false;
}
}
else
{
//+
if (_X >= points[j].x)
{
nextInd[j] = true;
}
else
{
nextInd[j] = false;
}
}
//
if (points[j].y < 0)
{
//-
if (_Y <= points[j].y)
{
nextInd[j] = nextInd[j] && true;
}
else
{
nextInd[j] = nextInd[j] && false;
}
}
else
{
//+
if (_Y >= points[j].y)
{
nextInd[j] = nextInd[j] && true;
}
else
{
nextInd[j] = nextInd[j] && false;
}
}
//
bool indSum = nextInd[0];
for (int k = 1; k < points.Length; k++)
indSum = nextInd[k] && indSum;
if (indSum && moveAlongCurveInd + 1 < points.Length)
{ moveAlongCurveInd += 1; }
else if (indSum && moveAlongCurveInd >= points.Length)
{ moveAlongCurveInd = 0; }
_PointArr[i].transform.position = new Vector3(
_X,
_Y,
0
);
}
}