parallax effect sensitivity control

45 Views Asked by At

I've written some code for a parallax effect by myself.

import java.awt.Dimension;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Main());
    }
    
    public Main() {
        Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
        Parallax parallax = new Parallax(new Point((int) size.getWidth() / 2, (int) size.getHeight() / 2), new Rectangle(0, 0, 1920, 1080));
        
        JFrame f = new JFrame();
        JLabel l = new JLabel();
        
        
        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        
        try {
            l.setIcon(new ImageIcon(ImageIO.read(getClass().getResourceAsStream("example.jpg")).getScaledInstance(1920, 1080, Image.SCALE_FAST)));
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        
        f.add(l);
        f.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                parallax.update();
                l.setLocation(parallax.getObject().x, parallax.getObject().y);
            }
        });
    }
    
    public class Parallax {
        
        private Point parallaxCenter;
        private Rectangle object;
        
        public Parallax(Point parallaxCenter, Rectangle object) {
            this.parallaxCenter = parallaxCenter;
            this.object = object;
        }

        public void update() {
                Point mousePosition = MouseInfo.getPointerInfo().getLocation();
                Point inverse = new Point(-mousePosition.x + parallaxCenter.x, -mousePosition.y + parallaxCenter.y);
                
                object.setLocation(inverse);
        }
        
        public Rectangle getObject() {
            return object;
        }
    }
}

Now to simply explain this code, it takes the location of the mouse from the center point and then inverts it. Here's an image to basically explain it to all those who don't understand my variable naming ;> ->

(Remember!: The white background isn't visible if you are on light mode)

Well with the current method I have come up with, I don't seem to know an exact way that I could control the sensitivity. I do not really know where to start and I would appreciate any kind of help.

Here's an example on what I am trying to achieve ->

I do not really know what went wrong with the thing and I hope the movement of the background is visible

1

There are 1 best solutions below

1
camickr On

Not sure I understand what a parallax is but based on the code provided I added an adjustment to the x/y location based on the distance the mouse is from the center:

    public void update() {
            Point mousePosition = MouseInfo.getPointerInfo().getLocation();
            int sensitivityX = (mousePosition.x - parallaxCenter.x) * 5;
            int sensitivityY = (mousePosition.y - parallaxCenter.y) * 5;
            Point inverse = new Point(-mousePosition.x + parallaxCenter.x + sensitivityX, -mousePosition.y + parallaxCenter.y + sensitivityY);

            object.setLocation(inverse);
    }

Theoretically the image should move faster as you get to the edges of the frame?

Other issues with the code:

  1. the code assumes the frame is centered on the desktop. If you move the frame you get different scrolling
  2. this problem should not be solved using setLocation(...). Try moving the mouse to an edge of the frame. When the mouse reaches the edge, resize the frame. The image will snap back to the middle since the layout manager is invoked and it will reset the label to its default location.

I would suggest you should not be using the MouseInfo class, but instead create a custom component and do custom painting to "draw" the image at your calculated location. You would then need to add a MouseMotionListener to this component and handle the "mouseMoved" event to do your calculation.

For the basics of custom painting read the section from the Swing tutorial on Custom Painting.