Java Mouse “Flashlight” effect?

前端 未结 2 1955
谎友^
谎友^ 2020-12-10 21:05

I\'m coding a simple 2D maze game where you go through many rooms. I want to make it a bit challenging by limiting the view of the player. At first I thought of replacing th

相关标签:
2条回答
  • 2020-12-10 21:46

    So you've identified the basic requirements.

    • You need a mouse listener to monitor the movements of the mouse, so you can update the position of the spot light. Take a read through how to write a mouse listener
    • You need to render the spot light effect over the image

    The following example basically uses a RadialGradientPaint to paint a "spotlight" over an image. It uses a MouseMoitionListener to monitor the position of the mouse and updates the spotlight as you go.

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Paint;
    import java.awt.Point;
    import java.awt.RadialGradientPaint;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class MouseCover {
    
        public static void main(String[] args) {
            new MouseCover();
        }
    
        public MouseCover() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public static class TestPane extends JPanel {
    
            public static final int RADIUS = 200;
            private Point mousePoint = null;
            private BufferedImage background;
    
            public TestPane() {
    
                MouseAdapter mouseHandler = new MouseAdapter() {
                    @Override
                    public void mouseMoved(MouseEvent e) {
                        mousePoint = e.getPoint();
                        repaint();
                    }
    
                    @Override
                    public void mouseExited(MouseEvent e) {
                        mousePoint = null;
                        repaint();
                    }
                };
    
                addMouseMotionListener(mouseHandler);
                addMouseListener(mouseHandler);
                try {
                    background = ImageIO.read(...);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
    
            @Override
            public Dimension getPreferredSize() {
                return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
    
                if (background != null) {
                    int x = (getWidth() - background.getWidth()) / 2;
                    int y = (getHeight() - background.getHeight()) / 2;
                    g2d.drawImage(background, x, y, this);
                }
    
                Paint paint = Color.BLACK;
                if (mousePoint != null) {
                    paint = new RadialGradientPaint(
                            mousePoint,
                            RADIUS,
                            new float[]{0, 1f},
                            new Color[]{new Color(0, 0, 0, 0), new Color(0, 0, 0, 255)});
                }
    
                g2d.setPaint(paint);
                g2d.fillRect(0, 0, getWidth(), getHeight());
    
                g2d.dispose();
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-10 21:49

    What you are looking for is more commonly known as a "Spotlight" effect. You will need to use a JLayer, as this tutorial explains.

    Here is the code excerpt from the tutorial:

    class SpotlightLayerUI extends LayerUI<JPanel> {
      private boolean mActive;
      private int mX, mY;
    
      @Override
      public void installUI(JComponent c) {
        super.installUI(c);
        JLayer jlayer = (JLayer)c;
        jlayer.setLayerEventMask(
          AWTEvent.MOUSE_EVENT_MASK |
          AWTEvent.MOUSE_MOTION_EVENT_MASK
        );
      }
    
      @Override
      public void uninstallUI(JComponent c) {
        JLayer jlayer = (JLayer)c;
        jlayer.setLayerEventMask(0);
        super.uninstallUI(c);
      }
    
      @Override
      public void paint (Graphics g, JComponent c) {
        Graphics2D g2 = (Graphics2D)g.create();
    
        // Paint the view.
        super.paint (g2, c);
    
        if (mActive) {
          // Create a radial gradient, transparent in the middle.
          java.awt.geom.Point2D center = new java.awt.geom.Point2D.Float(mX, mY);
          float radius = 72;
          float[] dist = {0.0f, 1.0f};
          Color[] colors = {new Color(0.0f, 0.0f, 0.0f, 0.0f), Color.BLACK};
          RadialGradientPaint p =
              new RadialGradientPaint(center, radius, dist, colors);
          g2.setPaint(p);
          g2.setComposite(AlphaComposite.getInstance(
              AlphaComposite.SRC_OVER, .6f));
          g2.fillRect(0, 0, c.getWidth(), c.getHeight());
        }
    
        g2.dispose();
      }
    
      @Override
      protected void processMouseEvent(MouseEvent e, JLayer l) {
        if (e.getID() == MouseEvent.MOUSE_ENTERED) mActive = true;
        if (e.getID() == MouseEvent.MOUSE_EXITED) mActive = false;
        l.repaint();
      }
    
      @Override
      protected void processMouseMotionEvent(MouseEvent e, JLayer l) {
        Point p = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), l);
        mX = p.x;
        mY = p.y;
        l.repaint();
      }
    }
    

    I suggest reading the entire tutorial on Swing so you understand how listeners work and basically how this entire code works.

    0 讨论(0)
提交回复
热议问题