2012-12-21 38 views
3

我正在嘗試在2D遊戲中製作手電筒效果。我的手電筒被表示爲以特定角度從實體延伸的線段。手電筒可以指向任何方向。手電筒的強度也有所不同(手電筒光束的長度)。我應該如何渲染2D手電筒效果?

我有一個問題,試圖找出最好(最簡單?)和最靈活的方式來呈現手電筒效果。特別是平鋪地圖。

我能想到兩種方法。但我也沒辦法實現它們:

  1. 只畫平鋪地圖
  2. 覆蓋屏幕,黑色質感的錐形/圓弧段的一部分,並與代碼衝壓孔成黑色質感。這樣我可以改變洞的屬性。

我很無知,從哪裏開始/這些被稱爲/如果libGDX可以做到這一點。

+0

你的意思是這樣的嗎? http://piledriverengine.com/images/flashlightBeam.png –

+0

是的,但我想在閃光燈的「電池」死亡時加長/縮短光束。顯而易見的方法是縮放圖像,但在某些時候會顯示地圖。加上是否是一個巨大的黑色質地不好的做法? – yahfree

回答

6

第一個稱爲模板緩衝區。但是你會發現很難達到軟效果。 - 簡單。

第二個:你只需要一個光的紋理。可以繪製完全黑色的區域,重複出現在精靈周圍的一個黑色精靈(左,右,上,下)。或者你可以將它與模板緩衝區混合使用。或者您可以仔細計算您的紋理座標,並使用GL.clamp_to_edge傳播所有黑色像素。根據渲染場景的方式,可以先用alpha信息渲染燈光,然後混合場景(根據dst_alpha變暗)。 - 不難實現。

第三個將着色器(GLES 2.0)的研究。您可以渲染網格來填充孔屏幕並使用一些着色器計算將其變暗。 - 這是最靈活的選擇,也是最困難的(無論如何都不是火箭科學)。

有些選項比其他選項聽起來更好,但是提供了您提供的信息,除此之外,我無法告訴您。從哪裏開始研究,你有一個很好的起點。

**如果您選擇使用紋理,請根據電池情況考慮使用幾種不同的紋理。您可以稍微調整它們或調整它們,但使用不同的紋理更加靈活。

+0

好的謝謝!我不知道模板緩衝區的東西太簡單了!我決定走這條路線,並簡單地繪製一個漸變黑色矩形的淡出效果。 – yahfree

5

如果圖形元素是BufferedImageGraphics2D實例,則可以這樣處理它。

Flashlight using incandescent (yellow) beam

Flashlight using halogen (blue) beam

import java.awt.*; 
import java.awt.geom.*; 
import java.awt.image.BufferedImage; 
import javax.swing.*; 

public class FlashLight { 

    public static void main(String[] args) throws Exception { 
     Robot robot = new Robot(); 
     int w = 500, h = 200; 
     Rectangle rect = new Rectangle(0, 0, w, h); 
     final BufferedImage bi = robot.createScreenCapture(rect); 
     final BufferedImage bi2 = FlashLight.draw(
       bi, 10, 180, 420, 90, .3, 
       new Color(255, 255, 120, 15), new Color(0, 0, 0, 220)); 
     final BufferedImage bi3 = FlashLight.draw(
       bi, 10, 180, 420, 90, .3, 
       new Color(180, 250, 255, 15), new Color(0, 0, 0, 220)); 

     Runnable r = new Runnable() { 

      @Override 
      public void run() { 
       JPanel gui = new JPanel(new GridLayout(3,0,2,2)); 
       gui.add(new JLabel(new ImageIcon(bi2))); 
       gui.add(new JLabel(new ImageIcon(bi))); 
       gui.add(new JLabel(new ImageIcon(bi3))); 

       JOptionPane.showMessageDialog(null,gui); 
      } 
     }; 
     // Swing GUIs should be created and updated on the EDT 
     // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html 
     SwingUtilities.invokeLater(r); 
    } 

    public static BufferedImage draw(
      BufferedImage source, 
      double x1, double y1, double x2, double y2, 
      double beamWidth, 
      Color beamColor, Color darknessColor) { 
     RenderingHints hints = new RenderingHints(
       RenderingHints.KEY_ANTIALIASING, 
       RenderingHints.VALUE_ANTIALIAS_ON); 

     BufferedImage bi = new BufferedImage(
       source.getWidth(), source.getHeight(), 
       BufferedImage.TYPE_INT_ARGB); 

     Graphics2D g = bi.createGraphics(); 
     g.setRenderingHints(hints); 

     g.drawImage(source, 0, 0, null); 

     // Create a conical shape to constrain the beam 
     double distance = Math.sqrt(Math.pow(x1 - x2, 2d) + Math.pow(y1 - y2, 2d)); 
     double tangent = (y2 - y1)/(x2 - x1); 
     double theta = Math.atan(tangent); 
     System.out.println(
       "distance: " + distance 
       + " tangent: " + tangent 
       + " theta: " + theta); 
     double minTheta = theta + beamWidth/2; 
     double maxTheta = theta - beamWidth/2; 
     double xMin = x1 + distance * Math.cos(minTheta); 
     double yMin = y1 + distance * Math.sin(minTheta); 

     double xMax = x1 + distance * Math.cos(maxTheta); 
     double yMax = y1 + distance * Math.sin(maxTheta); 

     Polygon beam = new Polygon(); 
     beam.addPoint((int) x1, (int) y1); 
     beam.addPoint((int) xMax, (int) yMax); 
     beam.addPoint((int) xMin, (int) yMin); 

     g.setColor(beamColor); 
     GradientPaint gp = new GradientPaint(
       (int)x1,(int)y1, beamColor, 
       (int)x2,(int)y2, darknessColor); 
     g.setClip(beam); 
     g.setPaint(gp); 
     g.fillRect(0, 0, bi.getWidth(), bi.getHeight()); 

     // create an area the size of the image, but lacking the beam area 
     Area darknessArea = new Area(new Rectangle(0, 0, bi.getWidth(), bi.getHeight())); 
     darknessArea.subtract(new Area(beam)); 
     g.setColor(darknessColor); 
     g.setClip(darknessArea); 
     g.fillRect(0, 0, bi.getWidth(), bi.getHeight()); 

     // fill in the beam edges with black (mostly to smooth lines) 
     g.setClip(null); 
     g.setColor(Color.BLACK); 
     g.setStroke(new BasicStroke(2)); 
     g.draw(new Line2D.Double(x1,y1,xMin,yMin)); 
     g.draw(new Line2D.Double(x1,y1,xMax,yMax)); 

     g.dispose(); 

     return bi; 
    } 
} 
+0

請[accept](http://meta.stackexchange。com/a/65088/155831)一個答案,如果它有助於解決問題。 –