2013-03-18 74 views
3

我正在编写一个简单的2D迷宫游戏,你经过很多房间。我想通过限制玩家的观点来让它变得富有挑战性。起初,我想将框架内的默认鼠标图标替换为半透明的PNG椭圆,但后来我意识到我需要阻止它周围的东西。Java鼠标“手电筒”效果如何?

我能想到的唯一方法就是让鼠标指针图标变成比框架大的图像(所以当用户移动到角落时它仍然是黑色的)填充它,然后放置指针区域内的褪色椭圆。

我想知道的是,这是否可能,我该如何去做这件事?我正在学习java,因此示例和oracle文档将帮助我很多。提前致谢!

正如从这里看到的和这link(它需要一段时间加载)PS:我使用日食。

enter image description here

+0

当然有可能,我个人将基本上创建从向外发出的鼠标的位置,将在一定距离后逐渐和黑色变暗每个像素从x,的Y位置的梯度老鼠,有可能是一个更有效的soltuion – SGM1 2013-03-18 23:31:39

+2

[你有什么尝试?](http://mattgemmell.com/2008/12/08/what-have-you-tried/) – 2013-03-18 23:33:36

+0

@zachlatta大声笑,爱链接 – SGM1 2013-03-18 23:34:45

回答

8

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

  • 你需要一个鼠标监听器来监视鼠标的移动,所以你可以更新聚光灯的位置。以读通过how to write a mouse listener
  • 您需要呈现在图像

下面的例子主要使用RadialGradientPaint在图像上画一个“聚光灯”聚光灯效应。它使用MouseMoitionListener来监视鼠标的位置并随时更新焦点。

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

+1为'RadialGradientPaint' – tenorsax 2013-03-19 00:30:30

+0

感谢您的示例!我仍在阅读它,这两个例子似乎都非常有帮助。 – SelfDeceit 2013-03-19 01:04:10

+0

我已经决定这个更容易适用于我的小程序,但这两个答案都很有帮助。这只是我决定使用的那个。 PS:我喜欢Wall-E图像!你知道艺术家的名字吗? – SelfDeceit 2013-03-19 01:28:51

5

你在找什么是通常被称为一个“聚光灯”的效果。您将需要使用JLayer,因为此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(); 
    } 
} 

我建议在Swing上阅读entire tutorial让您了解听众是如何工作的,这整个代码基本上是如何工作的。

+1

JLayer的+1 ... – MadProgrammer 2013-03-18 23:49:01

+0

对不起,很长的回复!我正在看两个例子,谢谢你们两位! – SelfDeceit 2013-03-19 01:02:56