A more simplistic way for this?

Started by
2 comments, last by haegarr 8 years, 9 months ago

So uh I figure out how to make a joystick on monogame. But im just wondering if some people here code a joystick in a more simplistic way.

This is the code I got from a tutorial


mousex = mouseState.X;
                mousey = mouseState.Y;
        

                // the formula in here is slope of a line
                dx =   mousex - sprite.originalPosition.X;
                dy = mousey - sprite.originalPosition.Y;


                // the difference between atan and atan2 http://stackoverflow.com/questions/283406/what-is-the-difference-between-atan-and-atan2-in-c
                angle = (float) Math.Atan(Math.Abs(dy/dx));
             
                c = (float)Math.Sqrt(dx*dx + dy*dy);    // pythogrean theorem
               
                if (c > radius)
                {
                    if (dx > 0 && dy > 0)   // bottom right(1st quadrant)
                    {
                        mousex = (float)sprite.originalPosition.X + (radius * (float)Math.Cos(angle));
                        mousey = (float)sprite.originalPosition.Y + (radius * (float)Math.Sin(angle));
                    }else if (dx > 0 && dy < 0) // top right ( 2nd quadrant of circle)
                    {
                        mousex = (float)sprite.originalPosition.X + (radius * (float)Math.Cos(angle));
                        mousey = (float)sprite.originalPosition.Y - (radius * (float)Math.Sin(angle));
                    }else if (dx < 0 && dy < 0) // top left ( 3rd quadrant of circle)
                    {
                        mousex = (float)sprite.originalPosition.X - (radius * (float)Math.Cos(angle));
                        mousey = (float)sprite.originalPosition.Y - (radius * (float)Math.Sin(angle));
                    }else if (dx < 0 && dy > 0) // bottom left ( 4th quadrant of circle)
                    {
                        mousex = (float)sprite.originalPosition.X - (radius * (float)Math.Cos(angle));
                        mousey = (float)sprite.originalPosition.Y + (radius * (float)Math.Sin(angle));
                    }

Im just wondering if you guys implement the same functionality with minimal ifs. and if so how did you do it?

thanks.

Advertisement

Im just wondering if you guys implement the same functionality with minimal ifs. and if so how did you do it?

1.) The if clauses are not complete, because none of the conditions checks for dx==0 or dy==0. However probable such a case is, it does cost nothing to check it but will fail if not doing so.

2.) All the if clauses would not be needed if the atan2 function would be used. As you already have noticed, there is a meaning with the atan2 function that makes it superior (in many cases) compared to the atan function.

3.) The entire approach can be replaced by using vector math. If I understand the code snippet correctly then something along


                // elements of difference vector
                dx = mousex - sprite.originalPosition.X;
                dy = mousey - sprite.originalPosition.Y;

                // length of difference vector
                c = (float)Math.Sqrt(dx*dx + dy*dy);
               
                if (c > radius)
                {
                        // direction vector (normalized difference vector)
                        dx /= c;
                        dy /= c;

                        // adding scaled direction vector to position
                        mousex = (float)sprite.originalPosition.X + (radius * dx);
                        mousey = (float)sprite.originalPosition.Y + (radius * dy);
                }

should do the same thing. (Notice that the above solution assumes that dx, dy, and c are floating point variables.)

BTW: I'm missing what exactly this has to do with a joystick...

BTW: I'm missing what exactly this has to do with a joystick...

Its kinda hard to explain but I think the formula I use is to follow the the touch but will only do so if the stick is still inside its circle boundary if not it will just follow the direction of the touch.

Here is the entire code if not clear


mouseState = Mouse.GetState();
            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                mousex = mouseState.X;
                mousey = mouseState.Y;
        

                // the formula in here is slope of a line
                dx =   mousex - sprite.originalPosition.X;
                dy = mousey - sprite.originalPosition.Y;


                // the difference between atan and atan2 http://stackoverflow.com/questions/283406/what-is-the-difference-between-atan-and-atan2-in-c
                angle = (float) Math.Atan(Math.Abs(dy/dx));
             
                c = (float)Math.Sqrt(dx*dx + dy*dy);    // pythogrean theorem
               
                if (c > radius)
                {
                    if (dx > 0 && dy > 0)   // bottom right(1st quadrant)
                    {
                        mousex = (float)sprite.originalPosition.X + (radius * (float)Math.Cos(angle));
                        mousey = (float)sprite.originalPosition.Y + (radius * (float)Math.Sin(angle));
                    }else if (dx > 0 && dy < 0) // top right ( 2nd quadrant of circle)
                    {
                        mousex = (float)sprite.originalPosition.X + (radius * (float)Math.Cos(angle));
                        mousey = (float)sprite.originalPosition.Y - (radius * (float)Math.Sin(angle));
                    }else if (dx < 0 && dy < 0) // top left ( 3rd quadrant of circle)
                    {
                        mousex = (float)sprite.originalPosition.X - (radius * (float)Math.Cos(angle));
                        mousey = (float)sprite.originalPosition.Y - (radius * (float)Math.Sin(angle));
                    }else if (dx < 0 && dy > 0) // bottom left ( 4th quadrant of circle)
                    {
                        mousex = (float)sprite.originalPosition.X - (radius * (float)Math.Cos(angle));
                        mousey = (float)sprite.originalPosition.Y + (radius * (float)Math.Sin(angle));
                    }
                }
               sprite.destination = new Vector2(mousex - sprite.texture.Width / 2, mousey - sprite.texture.Height / 2);

I use mouse state as I am trying to do it first in desktop to save time.

BTW thanks for the formula shorter and simpler.

Im just wondering what sort of trig formula is this


dx /= c;
dy /= c;

change of x = change of x/ hypotenuse?


Im just wondering what sort of trig formula is this

dx /= c;
dy /= c;

change of x = change of x/ hypotenuse?

Together with the computation of c it is a standard operation in vector algebra called "normalization", in this case using the so-called Euclidean norm or 2-norm. The Euclidean norm of a vector denotes the length of the vector in Euclidean space. Then dividing the difference vector (which is given by the 2 differences as (dx dy) ) by its own length results in a vector that points in the same direction as the original vector but has a length of 1 (i.e. it has unit length); thus it is called "normalization". Hence the resulting endpoint lies somewhere on the unit circle, i.e. the circle with radius 1. So the normalization step is equivalent to

dx := cos( angle ) = r * cos( a ) where r==1

dy := sin( angle ) = r * sin( a ) where r==1

but where the angle a is anything in [0,2pi] (as opposed of what you compute as angle in the OP).

This topic is closed to new replies.

Advertisement