Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I calculate and create positions of triangle shape?

Tags:

c#

unity3d

private void FormationTriangle()
{
    newpositions = new List<Vector3>();
    for (int x = 0; x < squadMembers.Count; x++)
    {
        for (int y = x; y < 2 * (squadMembers.Count - x) - 1; y++)
        {
            Vector3 position = new Vector3(x, y);
            newpositions.Add(position);
        }
    }

    move = true;
    formation = Formation.Square;
}

The loops are wrong. It put the squadMembers in one line one above the other. Not even close to a triangle shape. I want the squadMembers to stand in a triangle shape.

This is the moving part: But the problem is with the loops calculating the triangle shape positions. Other formations I did are working fine.

private void MoveToNextFormation()
{
    if (randomSpeed == false)
    {
        if (step.Length > 0)
            step[0] = moveSpeed * Time.deltaTime;
    }

    for (int i = 0; i < squadMembers.Count; i++)
    {
        squadMembers[i].transform.LookAt(newpositions[i]);
        if (randomSpeed == true)
        {
            squadMembers[i].transform.position = Vector3.MoveTowards(
                squadMembers[i].transform.position, newpositions[i], step[i]);
        }
        else
        {
            squadMembers[i].transform.position = Vector3.MoveTowards(
                squadMembers[i].transform.position, newpositions[i], step[0]);
        }
        if (Vector3.Distance(squadMembers[i].transform.position, newpositions[i]) < 
            threshold)
        {
            if (squareFormation == true)
            {
                Vector3 degrees = new Vector3(0, 0, 0);
                Quaternion quaternion = Quaternion.Euler(degrees);
                squadMembers[i].transform.rotation = Quaternion.Slerp(
                    squadMembers[i].transform.rotation, quaternion, 
                    rotateSpeed * Time.deltaTime);
            }
            else
            {
                squadMembers[i].transform.rotation = Quaternion.Slerp(
                    squadMembers[i].transform.rotation, quaternions[i], 
                    rotateSpeed * Time.deltaTime);
            }
        }
    }
}
like image 520
Dubi Duboni Avatar asked Dec 14 '22 14:12

Dubi Duboni


1 Answers

This answer will produce a triangle arranged like this:

    x
   x x
  x x x
 x x x x
x x x x x 

Or, if there aren't enough to fill a full triangle:

    x
   x x
  x x x
 x x x x
x   x   x 

Since you aren't guaranteed a perfectly triangular number of units, you should overestimate how big your triangle is, keep count of how many units you have placed, and then quit placing them when you reach your limit.

First, find the height of the smallest triangular number greater than your number of units, and that triangular number itself:

int height = Mathf.CeilToInt( (Mathf.Sqrt(8*squadMembers.Count+1f)-1f)/2 ) 
int slots = (int)(height * (height+1f)/2f)

Then, find the position of the first unit. We need to know how many rows of slots we have and how wide the bottom row of slots is:

float verticalModifier = 0.8f;  // 0.8f to decrease vertical space
float horizontalModifier = 1.25f; // 1.25f to increase horizontal space

float width = 0.5f * (height-1f);
Vector3 startPos = new Vector3(width* horizontalModifier, 0f, (float)(height-1f) * verticalModifier);

Then, add until you've added enough

int finalRowCount = height - slots + squadMembers.Count;
for (int rowNum = 0 ; rowNum < height && newpositions.Count < squadMembers.Count; rowNum++) {
    for (int i = 0 ; i < rowNum+1 && newpositions.Count < squadMembers.Count ; i++ ) {
        float xOffset = 0f;

        if (rowNum+1 == height) {
            // If we're in the last row, stretch it ...
            if (finalRowCount !=1) {
                // Unless there's only one item in the last row. 
                // If that's the case, leave it centered.

                xOffset = Mathf.Lerp(
                        rowNum/2f,
                        -rowNum/2f,
                        i/(finalRowCount-1f)
                        ) * horizontalModifier;
            }
        }
        else {
            xOffset = (i-rowNum /2f) * horizontalModifier; 
        }

        float yOffset = (float)rowNum * verticalModifier; 

        Vector3 position = new Vector3(
                startPos.x + xOffset, 0f, startPos.y - yOffset);
        newpositions.Add(position);

    }
}
like image 106
Ruzihm Avatar answered Jan 11 '23 23:01

Ruzihm