- Home /
How would you convert circular joystick input to a square overlay?
I'm having an issue converting joystick input to match a square screen. If you directly translate input to the screen, you will get an oval, what I want is a dynamic equation or method for also filling in the corners. I've attempted to go about this several ways and was wondering if anyone has encountered this before. joystick input is debugged, I have the correct values from joystick.value.
// Perfect Oval matching rectangular screen
public void DirectTranslation()
{
// Input Extremes: (1,0) (0.7, 0.7) (0, 1) (-0.7, 0.7) (-1,0) (-0.7, -0.7) (0,-1) (0.7, -0.7)
float x = joystick.HorizontalInput;
float y = joystick.VerticalInput;
float xPos = x * Screen.width / 2;
float yPos = y * Screen.height / 2;
reticle.rectTransform.anchoredPosition = new Vector2(xPos, yPos);
}
This was my first attempt to make up for the lost space when in a corner, but ended up with a cross cutout. It perfectly reaches the corners, but skips over any input value from -0.3 to 0.3 (I understand why, but could not get it to be a perfect fix):
// Perfect to the corners, but a cross of null space when x || y are < 0.3
public void Attempt1Fix()
{
float x = joystick.HorizontalInput;
float y = joystick.VerticalInput;
float inputMagnitude = Mathf.Abs(x) + Mathf.Abs(y);
float xRemainder = 0;
float yRemainder = 0;
xRemainder = 1 - Mathf.Abs(x);
xRemainder = Mathf.Clamp(xRemainder, 0, 0.3f);
yRemainder = 1 - Mathf.Abs(y);
yRemainder = Mathf.Clamp(yRemainder, 0, 0.3f);
float xPos = x * Screen.width / 2;
float yPos = y * Screen.height / 2;
float xExtenstion = xRemainder * (Screen.width / 2);
float yExtenstion = yRemainder * (Screen.height / 2);
// Q1: Top Right
if (x > 0 && y > 0) reticle.rectTransform.anchoredPosition = new Vector2(xPos + xExtenstion, yPos + yExtenstion);
// Q2: Top Left
if (x < 0 && y > 0) reticle.rectTransform.anchoredPosition = new Vector2(xPos - xExtenstion, yPos + yExtenstion);
// Q3: Bottom Left
if (x < 0 && y < 0) reticle.rectTransform.anchoredPosition = new Vector2(xPos - xExtenstion, yPos - yExtenstion);
// Q4: Bottom Right
if (x > 0 && y < 0) reticle.rectTransform.anchoredPosition = new Vector2(xPos + xExtenstion, yPos - yExtenstion);
}
So now I started searching for a solution, and I came across this https://stackoverflow.com/questions/13211595/how-can-i-convert-coordinates-on-a-circle-to-coordinates-on-a-square which seems to be a perfect solution my issue. I attempted to translate the mathematics equation to C# code, but it returns some NAN values in certain joystick positions:
// NAN values in some cases
public void Attemp2Fix()
{
float x = joystick.HorizontalInput;
float y = joystick.VerticalInput;
// Equation found at URL in question
// x = ½ √(2 + u² -v² +2u√2 ) - ½ √(2 + u² -v² -2u√2 )
// y = ½ √(2 - u² +v² +2v√2 ) - ½ √(2 - u² +v² -2v√2 )
// Attemp to recreate equation
float xCircle = x * Screen.width / 2;
float yCircle = y * Screen.height / 2;
float xSquare = 0.5f * Mathf.Sqrt(2 + (xCircle * xCircle) - (yCircle * yCircle) + 2 * xCircle * Mathf.Sqrt(2)) - 0.5f * Mathf.Sqrt(2 + (xCircle * xCircle) - (yCircle * yCircle) - 2 * xCircle * Mathf.Sqrt(2));
float ySquare = 0.5f * Mathf.Sqrt(2 - (xCircle * xCircle) + (yCircle * yCircle) + 2 * xCircle * Mathf.Sqrt(2)) - 0.5f * Mathf.Sqrt(2 - (xCircle * xCircle) + (yCircle * yCircle) - 2 * xCircle * Mathf.Sqrt(2));
// Then apply math to reticle position
reticle.rectTransform.anchoredPosition = new Vector2(xSquare, ySquare);
}
Answer by Captain_Pineapple · Jun 20, 2019 at 04:04 PM
Hey there,
i guess your issue is that you did not follow the equations given in your link completly. They do a straight transformation of a circle into a square. But you apply (probably unintentionally) another transformation on your circle coordinates before you apply the equations. That is the linear scaling with the screen width and height. -> one could say you form an ellipse from your circle coordinates and then try to format them as a circle.
So how to fix it? Simply move the scaling to the back. Do it last after you did the circle to square transform and it should work out fine. If it doesn't let me know, i'll try to take a deeper look into it then.
Hey man! Thank you so much for taking a look into that. I must have been tired when trying to enter it in. Yes 99%, there was also two errors in the equation. After taking your answer into consideration I managed to get all the kinks out, so thank you it works perfectly now.
public void Attempt2Fix()
{
float xInput = joystick.HorizontalInput;
float yInput = joystick.VerticalInput;
// Attemp to recreate equation
float u = xInput;
float v = yInput;
// Equation found at URL in question
// x = ½ √ (2 + u² - v² + 2 u √ 2 ) - ½ √ (2 + u² - v² - 2 u √ 2 )
float x = 0.5f * $$anonymous$$athf.Sqrt(2 + (u * u) - (v * v) + 2 * u * $$anonymous$$athf.Sqrt(2)) - 0.5f * $$anonymous$$athf.Sqrt(2 + (u * u) - (v * v) - 2 * u * $$anonymous$$athf.Sqrt(2));
// y = ½ √ (2 - u² + v² + 2 v √ 2 ) - ½ √ (2 - u² + v² - 2 v √ 2 )
float y = 0.5f * $$anonymous$$athf.Sqrt(2 - (u * u) + (v * v) + 2 * v * $$anonymous$$athf.Sqrt(2)) - 0.5f * $$anonymous$$athf.Sqrt(2 - (u * u) + (v * v) - 2 * v * $$anonymous$$athf.Sqrt(2));
// Then apply math to reticle position
reticle.rectTransform.anchoredPosition = new Vector2(x * Screen.width/2, y * Screen.height/2);
}
This looks horrible in this window, but if you copy paste it into VS it will be legible. Thanks again
Your answer
Follow this Question
Related Questions
Circular Analog Input? 1 Answer
How to use Handles.DrawSolidArc() in execute mode 0 Answers
joystick connected 1 Answer
Controller input not working correctly 0 Answers
Analog stick control 1 Answer