2013-03-18 73 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