I'm trying to paint "pixels". I created Conway's game of life in Unity and i want to add a feature where you press mouse button and when it's pressed you "paint" - set cells alive. So my idea was:
In Update() if mouse button is pressed Start Coroutine.
In Coroutine you have loop that sets cell pointed by Input.mousePosition to Alive-state then waits for end of frame. Loop, and by that Coroutine ends when that mouse button is released.
My problem is that if you move mouse rapidly created line will not be continuous, because inputs form mouse from two frames will be different (far apart).
Since you can take Input.mousePosition only once per frame i tried approximating this by storing mousePosition from previous frame and calculating all points that lie on Edge between CurrentMousePosition and PreviousMousePosition
However i was not happy with the result.
My Question is: is there a better way to prevent this un-continuous line than letting it be and then fixing it? And if not is there a better way to approximate points that lie on Edge?
void Update()
{
if (Input.GetMouseButtonDown(1))
{
StartCoroutine(BrushPixel());
}
UpdatePlane(true);
}
IEnumerator BrushPixel()
{
int prevX = 0;
int prevY = 0;
bool firstIteratrion = true;
while (true)
{
IntVector3 currentPos = new IntVector3(Camera.main.ScreenToWorldPoint(Input.mousePosition));
int xPos = currentPos.x + sizeX/2;
int yPos = currentPos.y + sizeY/2;
if (xPos >= 0 && xPos < sizeX && yPos >= 0 && yPos < sizeY)
{
if (firstIteratrion)
{
firstIteratrion = false;
prevX = xPos;
prevY = yPos;
}
mainMatrix[xPos, yPos] = true;
Queue<IntVector3> pointsAlong = AproximatePoints(xPos, yPos, prevX, prevY);
while(pointsAlong.Count != 0)
{
IntVector3 temp = pointsAlong.Dequeue();
if(temp.x >= 0 && temp.x < sizeX && temp.y >= 0 && temp.y < sizeY)
{
mainMatrix[temp.x, temp.y] = true;
}
}
UpdatePlane();
prevX = xPos;
prevY = yPos;
}
if (Input.GetKeyUp(KeyCode.Mouse1))
{
break;
}
yield return null;
}
}
public Queue<IntVector3> AproximatePoints (int curX, int curY, int prevX, int prevY)
{
Queue<IntVector3> additional = new Queue<IntVector3>();
if(curX == prevX && curY == prevY)
{
return additional;
}
int distance = (int)Math.Sqrt( (double)((curX - prevX) * (curX - prevX)) + (double)((curY - prevY) * (curY - prevY)) );
int count = distance;
int d = distance / count;
double angle = Math.Atan2(curX - prevX, curY - prevY);
for (int i = 0; i < count; i++)
{
additional.Enqueue(new IntVector3((int)Math.Floor(curX + i * d * Math.Cos(angle)), (int)Math.Floor(curY + i * d * Math.Cos(angle)), 0));
}
return additional;
}
Additional notes: MainMatrix is bool[sizeX, sizeY] that holds states of current generation where true is Alive and false is dead. In line
IntVector3 currentPos = new IntVector3(Camera.main.ScreenToWorldPoint(Input.mousePosition));
int xPos = currentPos.x + sizeX/2;
int yPos = currentPos.y + sizeY/2;
i translate Input from mouse to addres in MainMatrix. IntVector3 is my struct just like Unity Vector3 but holds x, y, z as Integers. UpdatePlane() is generating image that will be changed. UpdatePlane(bool k) is generating image that will be changed and calculates next generation of cells.
Current approximation gives pic1 when trying to draw line form UpperLeft corner to LowerRight corner. pic1
IPointerevents. You can get the position every frame usingOnDragor get the location when the user clicks and releases the mouse. - TEEBQNE