Java鼠标“手电筒”效果如何?

我正在编写一个简单的2D迷宫游戏,你可以通过很多房间。 我希望通过限制玩家的观点来使其变得有点挑战。 起初我想过将框架中的默认鼠标图标替换为半透明的PNG椭圆,但后来我意识到我需要阻止它周围的东西。

我能想到的唯一方法是将鼠标指针图标设置为比框架大的图像(因此当用户移动到角落时仍然是黑色时)填充它然后放置清晰褪色的椭圆在指针区域。

我想知道的是,这是可能的,我将如何做到这一点? 我正在学习java所以示例和oracle文档对我很有帮助。 提前致谢!

从这里看到这个链接 (加载需要一段时间)PS:我正在使用eclipse。

在此处输入图像描述

所以你已经确定了基本要求。

  • 您需要一个鼠标监听器来监控鼠标的移动,这样您就可以更新聚光灯的位置。 阅读如何编写鼠标监听器
  • 您需要在图像上渲染聚光灯效果

以下示例基本上使用RadialGradientPaint在图像上绘制“聚光灯”。 它使用MouseMoitionListener监视鼠标的位置,并在您前进时更新聚光灯。

在此处输入图像描述

 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(); } } } 

您正在寻找的东西通常被称为“聚光灯”效果。 您将需要使用JLayer,如本教程所述 。

以下是本教程的代码摘录:

 class SpotlightLayerUI extends LayerUI { 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 = px; mY = py; l.repaint(); } } 

我建议阅读关于Swing的整个教程 ,这样你就能理解听众的工作方式以及整个代码的工作原理。