Search code examples
javaatan2

Issue when rotating an object through the atan2 method


I'm trying to have an image follow my cursor, smoothly moving where it is located and turning to face it.

When i'm near the origin, it works flawlessy: the image will flip completely without issues, however the further i go from the origin of the window, the less the image turns. When i'm at the other side of the screen, instead of flipping over it'll rotate 5°-15° instead.

I'd love if somebody could point out what the issue is =)

Here's my current code for the image:

lblRover = new JLabel(sees) { // sees is an ImageIcon
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
            AffineTransform aT = g2.getTransform();
            Shape oldshape = g2.getClip();
            double x = getWidth()/2.0;
            double y = getHeight()/2.0;
            aT.rotate(Math.toRadians(degrees), x, y);
            g2.setTransform(aT);
            g2.setClip(oldshape);
            super.paintComponent(g);
        }
    };
    lblRover.setSize(179, 180);
    lblRover.setLocation(500, 300);
    JFrame.getFrames()[0].add(lblRover);

And this is the code that handles the rotation, plus its movement:

        NewJFrame.PInf = MouseInfo.getPointerInfo();
        /* The frame is contained in NewJFrame, PInf is a PointerInfo */
        p = (NewJFrame.PInf.getLocation()); // p is a point
        p.x-=NewJFrame.getWindows()[0].getLocationOnScreen().x;
        p.y-=NewJFrame.getWindows()[0].getLocationOnScreen().y;
        //i subtract the location of the window relative to the screen
        img = NewJFrame.lblRover.getLocation();
        img.x+=NewJFrame.lblRover.getWidth()/2;
        img.y+=NewJFrame.lblRover.getHeight()/2;
        // img will be the point with the center of my image

        sas=getAngle(p,img); // sas is a float variable
        NewJFrame.degrees=sas;
        //
        // From now on i move the image
        //
        diffx = p.x-img.x;
        diffy = p.y-img.y;
        diffx/=80; // 80 is an arbitrary number to smooth the effect
        diffy/=80; // high numbers will make the image not move at all
        Point var = new Point(NewJFrame.lblRover.getLocation());
        // I may have to use img here or subtract width and height /2
        var.x+=diffx;
        var.y+=diffy;
        NewJFrame.lblRover.setLocation(var);

        // A 5ms sleep to smooth the movement
        // I also refresh a debug label
        // Also i do refresh the frame, otherwise nothing happens

        NewJFrame.jLabel1.setText(""+NewJFrame.lblRover.getLocation().y 
        +"/"+ p.y+" "+NewJFrame.lblRover.getLocation().x +"/"+ p.x );

        NewJFrame.getFrames()[0].repaint();
        try {
            sleep(5);
        } catch (InterruptedException ex) {
            Logger.getLogger(thread.class.getName()).log(Level.SEVERE, null, ex);
        }

Solution

  • Well, after multiple tries i've narrowed it down.

    Now, the rotation code is put last, before the repaint, and it looks like this:

    sas=this.getAngle((float)diffy,(float)diffx);
    NewJFrame.degrees=sas;
    

    I've also created this new method that uses two float instead of two points:

    public float getAngle(Float x, Float y) {
    float angle = (float) Math.toDegrees(Math.atan2(x, y));
    //System.out.println(angle);
    return angle;
    

    I have no clue why it works now but it didn't before as the procedure is basically identical...but hey it works! =D