Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何渲染2D闪光灯效果?_Java_Libgdx - Fatal编程技术网

Java 如何渲染2D闪光灯效果?

Java 如何渲染2D闪光灯效果?,java,libgdx,Java,Libgdx,我想在我的2D游戏中制作一个手电筒效果。我的手电筒表示为从实体以特定角度延伸的线段。手电筒可以指向任何方向。手电筒的强度也不同(手电筒光束的长度) 我在尝试找出最佳(最简单?)和最灵活的方式来渲染手电筒效果时遇到了一个问题。特别是对于平铺贴图 我可以想出两种方法。但我不知道如何实施: 仅绘制平铺贴图的圆锥形/圆形线段部分 用黑色纹理覆盖屏幕,并用代码在黑色纹理上打孔。这样我可以更改孔的属性 我不知道从何处开始/这些被称为什么/如果libGDX可以做它们。第一个被称为模具缓冲区。但你会发现很难实现

我想在我的2D游戏中制作一个手电筒效果。我的手电筒表示为从实体以特定角度延伸的线段。手电筒可以指向任何方向。手电筒的强度也不同(手电筒光束的长度)

我在尝试找出最佳(最简单?)和最灵活的方式来渲染手电筒效果时遇到了一个问题。特别是对于平铺贴图

我可以想出两种方法。但我不知道如何实施:

  • 仅绘制平铺贴图的圆锥形/圆形线段部分
  • 用黑色纹理覆盖屏幕,并用代码在黑色纹理上打孔。这样我可以更改孔的属性

  • 我不知道从何处开始/这些被称为什么/如果libGDX可以做它们。

    第一个被称为模具缓冲区。但你会发现很难实现软效果简单

    第二点:你只需要一个带有灯光的纹理。完全黑色的区域可以在灯光精灵周围重复绘制黑色精灵(左、右、上、下)。也可以将其与模具缓冲区混合。或者,您可以仔细计算纹理坐标,并使用GL.clamp_to_edge传播所有黑色像素。根据渲染场景的方式,可以先使用alpha信息渲染灯光,然后混合场景(根据dst_alpha变暗)实施起来并不难

    第三个是对着色器的研究(GLES 2.0)。您可以渲染网格以填充孔屏幕,并使用一些着色器计算使其变暗。-这是最灵活的选择,也是最困难的(无论如何都离火箭科学相去甚远)

    有些选项听起来比其他选项更好,但提供您提供的信息,我无法告诉您更多。从哪里开始研究,你有一个很好的起点


    **如果你选择使用纹理,考虑有两个不同的纹理取决于电池。您可以对它们进行一些缩放或着色,但使用不同的纹理更为灵活。

    如果图形元素是
    缓冲图像
    图形2D
    实例,您可以这样处理

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


    你是说像这样的?是的,但我想在闪光灯的“电池”耗尽时延长/缩短光束。最明显的方法是缩放图像,但在某个点会显示地图。另外,制作一个巨大的黑色纹理不是很糟糕吗?好的,谢谢!我不知道模具缓冲区的东西这么简单!我决定走这条路,简单地画一个渐变的黑色矩形以产生淡入淡出的效果。如果它有助于解决问题,请给出答案。